Android 中间滚动选择器,可自定义中间控件(基于recyclerview实现)
描述:这是一个基于recyclerview实现的 Android 中间滚动选择器,可自定义中间控件。
项目代码在最后面!!!!跳转到最后
控件效果如下:
此控为Android 中间滚动选择器,可进行滚轮选择。
实现功能:
- 返回滚轮View 和 是否处于中间的状态 可依此进行中间View的自定义
- 可自定义滚轮数量
- 可传入中间坐标背景 会适配到中间滚轮位置
- 中间选择回调
- 默认前后可放大和缩小
- 为无限循环滚动(跳转回之前相似的postion)
设计核心:
主要的设计核心是依赖于recyclerview进行设计的,主要通过重写layoutmanager,LinearSnapHelper,RecyclerView等来实现
核心代码:
PickerLayoutManager .java
中间状态监听和回调,以及根据数量进行高度调整
package com.ui.design.view.pickviewselect.view;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Color;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.LinearSnapHelper;
import androidx.recyclerview.widget.RecyclerView;
import com.ui.design.R;
import com.ui.design.view.pickviewselect.adapter.PickAdapter;
import org.jetbrains.annotations.NotNull;
public class PickerLayoutManager extends LinearLayoutManager implements View.OnTouchListener {
private float mScale = 0.5f;
private boolean mIsAlpha = true;
private final LinearSnapHelper mLinearSnapHelper;
private OnSelectedViewListener mOnSelectedViewListener;
private int mItemViewWidth;
private int mItemViewHeight;
private int mItemCount = -1;
private PickRecycleView mRecyclerView;
private final int mOrientation;
private int mPickCount;
private int mScreenWidth;
private int[] mTopAndBottomPathHeight;
public PickerLayoutManager(Context context, int orientation, boolean reverseLayout) {
super(context, orientation, reverseLayout);
this.mLinearSnapHelper = new PickerSnapHelper();
this.mOrientation = orientation;
}
@SuppressLint("ClickableViewAccessibility")
public PickerLayoutManager(Context context, PickRecycleView recyclerView, int orientation, boolean reverseLayout, int itemCount, float scale, boolean isAlpha, int pickCount) {
super(context, orientation, reverseLayout);
this.mLinearSnapHelper = new PickerSnapHelper();
this.mPickCount = pickCount;
this.mItemCount = itemCount;
if (mItemCount % 2 == 0) {
mItemCount = mItemCount + 1;
}
mScreenWidth = context.getResources().getDisplayMetrics().widthPixels;
this.mOrientation = orientation;
this.mRecyclerView = recyclerView;
mRecyclerView.setLayoutManager(this);
mRecyclerView.setOnTouchListener(this);
this.mIsAlpha = isAlpha;
this.mScale = scale;
if (mItemCount != 0) setAutoMeasureEnabled(false);
}
/**
* 添加LinearSnapHelper
*/
@Override
public void onAttachedToWindow(RecyclerView view) {
super.onAttachedToWindow(view);
mLinearSnapHelper.attachToRecyclerView(view);
}
/**
* 没有指定显示条目的数量时,RecyclerView的宽高由自身确定
* 指定显示条目的数量时,根据方向分别计算RecyclerView的宽高
*/
@Override
public void onMeasure(@NotNull RecyclerView.Recycler recycler, @NotNull RecyclerView.State state, int widthSpec, int heightSpec) {
if (getItemCount() != 0 && mItemCount != 0 && state.getItemCount()>0) {
View view = recycler.getViewForPosition(0);
measureChildWithMargins(view, widthSpec, heightSpec);
mItemViewWidth = view.getMeasuredWidth();
mItemViewHeight = view.getMeasuredHeight();
if (mItemViewWidth <= 0) {
if (mPickCount > 0) {
mItemViewWidth = mScreenWidth / mPickCount;
}
}
if (mOrientation == HORIZONTAL) {
int paddingHorizontal = (int) ((mItemCount - 1) * 1.0f / 2 * mItemViewWidth);
mRecyclerView.setClipToPadding(false);
mRecyclerView.setPadding(paddingHorizontal, 0, paddingHorizontal, 0);
setMeasuredDimension(mItemViewWidth * mItemCount, mItemViewHeight);
} else if (mOrientation == VERTICAL) {
int paddingVertical = (mItemCount - 1) / 2 * mItemViewHeight;
mRecyclerView.setClipToPadding(false);
if (!mIsCycle) {
mRecyclerView.setPadding(0, paddingVertical, 0, paddingVertical);
}
setMeasuredDimension(mItemViewWidth, mItemViewHeight * mItemCount);
}
} else {
super.onMeasure(recycler, state, widthSpec, heightSpec);
}
}
int getItemViewHeight() {
return mItemViewHeight;
}
int getHalfItemCount(){
return mItemCount/2;
}
@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
super.onLayoutChildren(recycler, state);
if (getItemCount() < 0 || state.isPreLayout()) return;
if (mOrientation == HORIZONTAL) {
scaleHorizontalChildView();
} else if (mOrientation == VERTICAL) {
scaleVerticalChildView();
}
}
@Override
public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler, RecyclerView.State state) {
scaleHorizontalChildView();
return super.scrollHorizontallyBy(dx, recycler, state);
}
@Override
public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) {
scaleVerticalChildView();
return super.scrollVerticallyBy(dy, recycler, state);
}
/**
* 横向情况下的缩放
*/
private void scaleHorizontalChildView() {
float mid = getWidth() / 2.0f;
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
float childMid = (getDecoratedLeft(child) + getDecoratedRight(child)) / 2.0f;
float scale = 1.0f + (-1 * (1 - mScale)) * (Math.min(mid, Math.abs(mid - childMid))) / mid;
child.setScaleX(scale);
child.setScaleY(scale);
if (mIsAlpha) {
child.setAlpha(scale);
}
}
}
private void scrollTargetPos(View view) {
if (mRecyclerView == null) {
return;
}
RecyclerView.LayoutManager layoutManager = mRecyclerView.getLayoutManager();
if (layoutManager == null) {
return;
}
int[] snapDistance = mLinearSnapHelper.calculateDistanceToFinalSnap(layoutManager, view);
assert snapDistance != null;
if (snapDistance[0] != 0 || snapDistance[1] != 0) {
mRecyclerView.smoothScrollBy(snapDistance[0], snapDistance[1]);
}
}
private View centerView;//记录中间View
/**
* 竖向方向上的缩放
*/
private void scaleVerticalChildView() {
centerView = mLinearSnapHelper.findSnapView(this);
float mid = getHeight() / 2.0f;
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
float childMid = (getDecoratedTop(child) + getDecoratedBottom(child)) / 2.0f;
float scale = 1.0f + (-1 * (1 - mScale)) * (Math.min(mid, Math.abs(mid - childMid))) / mid;
child.setScaleX(scale);
child.setScaleY(scale);
if (mIsAlpha) {
if (child.equals(centerView)) {
child.setAlpha(1.f);
mOnSelectedViewListener.onScrollMidView(child,true);
// scrollTargetPos();
} else {
child.setAlpha(scale - 0.3f);
mOnSelectedViewListener.onScrollMidView(child,false);
((TextView)child.findViewById(R.id.item_wheel_tv)).setTextColor(Color.BLACK);
}
}
}
}
/**
* 当滑动停止时触发回调
*/
@Override
public void onScrollStateChanged(int state) {
super.onScrollStateChanged(state);
if (state == 0) {
if (mOnSelectedViewListener != null && mLinearSnapHelper != null) {
View view = mLinearSnapHelper.findSnapView(this);
if (view != null) {
int position = getPosition(view);
PickAdapter adapter = (PickAdapter) mRecyclerView.getAdapter();
mOnSelectedViewListener.onSelectedView(view, position, adapter.getCycleNum() / 2);
}
}
}
}
public void setOnSelectedViewListener(OnSelectedViewListener listener) {
this.mOnSelectedViewListener = listener;
}
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
View view = mLinearSnapHelper.findSnapView(this);
assert view != null;
if (!view.equals(centerView)) {
scrollTargetPos(view);
}
break;
default:
break;
}
return false;
}
/**
* 停止时,显示在中间的View的监听
*/
public interface OnSelectedViewListener {
void onSelectedView(View view, int i, int position);
void onScrollMidView(View view,boolean iscenter);//中间VIew 移动回调
}
/**
* 滚动到目标位置 无限循环时调用此方法
*
* @param position 目标位置
*/
public void scrollToPositionForCycle(int position, int size, int cycleNum) {
if (cycleNum == 0) {
cycleNum = ((PickAdapter) mRecyclerView.getAdapter()).getCycleNum() / 2;
}
if (mIsCycle) {
scrollToPositionWithOffset(size * cycleNum + position % size - mItemCount / 2, 0);
}
}
/**
* 滚动到目标位置 不是无循环时调用
*
* @param position 目标位置
*/
public void scrollToPosition(int position) {
if (!mIsCycle) {
scrollToPositionWithOffset(position, 0);
}
}
private boolean mIsCycle;
/**
* 设置是否循环
*/
public void setCycle(boolean cycleFlag) {
mIsCycle = cycleFlag;
}
public boolean getCycle() {
return mIsCycle;
}
}
PickerSnapHelper.java
中间位置计算
package com.ui.design.view.pickviewselect.view;
import android.graphics.PointF;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearSnapHelper;
import androidx.recyclerview.widget.OrientationHelper;
import androidx.recyclerview.widget.RecyclerView;
public class PickerSnapHelper extends LinearSnapHelper {
@Nullable
private OrientationHelper mHorizontalHelper;
private OrientationHelper mVerticalHelper;
@Override
public int findTargetSnapPosition(RecyclerView.LayoutManager layoutManager, int velocityX, int velocityY) {
return findTargetSnapPosition1(layoutManager, velocityX, velocityY);
//snapToTargetExistingView()
}
private int findTargetSnapPosition1(RecyclerView.LayoutManager layoutManager, int velocityX, int velocityY) {
if (!(layoutManager instanceof RecyclerView.SmoothScroller.ScrollVectorProvider)) {
return RecyclerView.NO_POSITION;
}
final int itemCount = layoutManager.getItemCount();
if (itemCount == 0) {
return RecyclerView.NO_POSITION;
}
final View currentView = findSnapView(layoutManager);//获取到目标view
if (currentView == null) {
return RecyclerView.NO_POSITION;
}
final int currentPosition = layoutManager.getPosition(currentView);//获取到目标view的索引
if (currentPosition == RecyclerView.NO_POSITION) {
return RecyclerView.NO_POSITION;
}
RecyclerView.SmoothScroller.ScrollVectorProvider vectorProvider = (RecyclerView.SmoothScroller.ScrollVectorProvider) layoutManager;
// 通过ScrollVectorProvider接口中的computeScrollVectorForPosition()方法
// 来确定layoutManager的布局方向
PointF vectorForEnd = vectorProvider.computeScrollVectorForPosition(itemCount - 1);
if (vectorForEnd == null) {
return RecyclerView.NO_POSITION;
}
//计算一屏的item数
int deltaThreshold = 3;
int deltaJump, xdeltaJump, hdeltaJump;
if (layoutManager.canScrollHorizontally()) {
//layoutManager是横向布局,并且内容超出一屏,canScrollHorizontally()才返回true
//估算fling结束时相对于当前snapView位置的横向位置偏移量
xdeltaJump = estimateNextPositionDiffForFling(layoutManager, getHorizontalHelper(layoutManager), velocityX, 0);
if (xdeltaJump > deltaThreshold) {
xdeltaJump = deltaThreshold;
}
if (xdeltaJump < -deltaThreshold) {
xdeltaJump = -deltaThreshold;
}
//vectorForEnd.x < 0代表layoutManager是反向布局的,就把偏移量取反
if (vectorForEnd.x < 0) {
//不能横向滚动,横向位置偏移量当然就为0
xdeltaJump = -xdeltaJump;
}
} else {
xdeltaJump = 0;
}
if (layoutManager.canScrollVertically()) {
hdeltaJump = estimateNextPositionDiffForFling(layoutManager,
getVerticalHelper(layoutManager), 0, velocityY);
if (hdeltaJump > deltaThreshold) {
hdeltaJump = deltaThreshold;
}
if (hdeltaJump < -deltaThreshold) {
hdeltaJump = -deltaThreshold;
}
if (vectorForEnd.y < 0) {
hdeltaJump = -hdeltaJump;
}
} else {
hdeltaJump = 0;
}
deltaJump = layoutManager.canScrollVertically() ? hdeltaJump : xdeltaJump;
if (deltaJump == 0) {
return RecyclerView.NO_POSITION;
}
//当前位置加上偏移位置,就得到fling结束时的位置,这个位置就是targetPosition
int targetPos = currentPosition + deltaJump;
if (targetPos < 0) {
targetPos = 0;
}
if (targetPos >= itemCount) {
targetPos = itemCount - 1;
}
return targetPos;
}
private int estimateNextPositionDiffForFling(RecyclerView.LayoutManager layoutManager, OrientationHelper helper, int velocityX, int velocityY) {
//计算滚动的总距离,这个距离受到触发fling时的速度的影响
int[] distances = calculateScrollDistance(velocityX, velocityY);
//计算每个ItemView的长度
float distancePerChild = computeDistancePerChild(layoutManager, helper);
if (distancePerChild <= 0) {
return 0;
}
//这里其实就是根据是横向布局还是纵向布局,来取对应布局方向上的滚动距离
int distance = Math.abs(distances[0]) > Math.abs(distances[1]) ? distances[0] : distances[1];
//distance的正负值符号表示滚动方向,数值表示滚动距离。横向布局方式,内容从右往左滚动为正;竖向布局方式,内容从下往上滚动为正
// 滚动距离/item的长度=滚动item的个数,这里取计算结果的整数部分
return Math.round(distance / distancePerChild);
}
private float computeDistancePerChild(RecyclerView.LayoutManager layoutManager,
OrientationHelper helper) {
View minPosView = null;
View maxPosView = null;
int minPos = Integer.MAX_VALUE;
int maxPos = Integer.MIN_VALUE;
int childCount = layoutManager.getChildCount();
if (childCount == 0) {
return INVALID_DISTANCE;
}
//循环遍历layoutManager的itemView,得到最小position和最大position,以及对应的view
for (int i = 0; i < childCount; i++) {
View child = layoutManager.getChildAt(i);
final int pos = layoutManager.getPosition(child);
if (pos == RecyclerView.NO_POSITION) {
continue;
}
if (pos < minPos) {
minPos = pos;
minPosView = child;
}
if (pos > maxPos) {
maxPos = pos;
maxPosView = child;
}
}
if (minPosView == null || maxPosView == null) {
return INVALID_DISTANCE;
}
//最小位置和最大位置肯定就是分布在layoutManager的两端,但是无法直接确定哪个在起点哪个在终点(因为有正反向布局)
//所以取两者中起点坐标小的那个作为起点坐标
//终点坐标的取值一样的道理
int start = Math.min(helper.getDecoratedStart(minPosView),
helper.getDecoratedStart(maxPosView));
int end = Math.max(helper.getDecoratedEnd(minPosView),
helper.getDecoratedEnd(maxPosView));
//终点坐标减去起点坐标得到这些itemview的总长度
int distance = end - start;
if (distance == 0) {
return INVALID_DISTANCE;
}
// 总长度 / itemview个数 = itemview平均长度
return 1f * distance / ((maxPos - minPos) + 1);
}
@NonNull
private OrientationHelper getHorizontalHelper(
@NonNull RecyclerView.LayoutManager layoutManager) {
if (mHorizontalHelper == null) {
mHorizontalHelper = OrientationHelper.createHorizontalHelper(layoutManager);
}
return mHorizontalHelper;
}
private static final float INVALID_DISTANCE = 1f;
@NonNull
private OrientationHelper getVerticalHelper(@NonNull RecyclerView.LayoutManager layoutManager) {
if (mVerticalHelper == null) {
mVerticalHelper = OrientationHelper.createVerticalHelper(layoutManager);
}
return mVerticalHelper;
}
}
PickRecycleView .java
可用来设置中间背景
package com.ui.design.view.pickviewselect.view;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import com.ui.design.utils.DensityUtil;
public class PickRecycleView extends RecyclerView {
private int mWidth;
private int mHeight;
private Context mContext;
private View CenterView;
public PickRecycleView(Context context) {
this(context, null);
}
public PickRecycleView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public PickRecycleView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setOverScrollMode(OVER_SCROLL_NEVER);
this.mContext = context;
}
@Override
protected void onMeasure(int widthSpec, int heightSpec) {
mWidth = getMeasuredWidth();
mHeight = getMeasuredHeight();
super.onMeasure(widthSpec, heightSpec);
}
@Override
public void onDraw(Canvas c) {
super.onDraw(c);
PickerLayoutManager layoutManager = (PickerLayoutManager) getLayoutManager();
if (layoutManager != null) {
if (CenterView!=null&&CenterView.getTop()==0){
CenterView.layout(getLeft(),getTopAndBottomPathHeight()[0],getLeft()+CenterView.getWidth(),getTopAndBottomPathHeight()[1]);//手动移动到选择器中间位置 只需移动一次
}
}
}
public void setCenterView(View view){
CenterView=view;
}
public int[] getTopAndBottomPathHeight() {
PickerLayoutManager layoutManager = (PickerLayoutManager) getLayoutManager();
int[] height = new int[]{
0, 0};
if (layoutManager != null) {
height[0] = (int) ( layoutManager.getItemViewHeight() *layoutManager.getHalfItemCount());
height[1] = (int) (layoutManager.getItemViewHeight() *(layoutManager.getHalfItemCount()+1));
}
return height;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent e) {
return super.onInterceptTouchEvent(e);
}
}
PickAdapter.java 在Adapter中将size增加 不然无法实现无限循环滚动
package com.ui.design.view.pickviewselect.adapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import com.ui.design.R;
import com.ui.design.main.application.MyApplication;
import com.ui.design.view.pickviewselect.bean.TestBean;
import com.ui.design.view.pickviewselect.view.PickerLayoutManager;
import java.util.List;
public class PickAdapter extends RecyclerView.Adapter<PickAdapter.ViewHolder> {
private final List<TestBean> mList;
private final RecyclerView mRecyclerView;
private int mCycleNum=8;
private final Context mContext;
public PickAdapter(Context context,List<TestBean> list, RecyclerView recyclerView) {
this.mList = list;
this.mRecyclerView = recyclerView;
this.mContext=context;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.item_pickview_wheel, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
if (mList == null || mList.size() == 0) {
return;
}
holder.tvText.setText(mList.get(position % mList.size()).name);
}
@Override
public int getItemCount() {
if (mList == null) {
return 0;
}
if (mRecyclerView.getLayoutManager() instanceof PickerLayoutManager) {
if (((PickerLayoutManager) mRecyclerView.getLayoutManager()).getCycle()) {
return mList.size() + mList.size() * mCycleNum;
}
}
return mList.size();
}
static class ViewHolder extends RecyclerView.ViewHolder {
TextView tvText;
public ViewHolder(View itemView) {
super(itemView);
tvText = (TextView) itemView.findViewById(R.id.item_wheel_tv);
}
}
public void setCycleNum(int cycleNum) {
if (cycleNum % 2 != 0) {
cycleNum += 1;
}
this.mCycleNum = cycleNum;
}
public int getCycleNum() {
return mCycleNum;
}
}
使用示例:
PickActivity.java
package com.ui.design.view.pickviewselect;
import android.graphics.Color;
import android.view.View;
import android.widget.TextView;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.ui.design.R;
import com.ui.design.main.base.BaseActivity;
import com.ui.design.main.constants.Constants;
import com.ui.design.utils.RandomValue;
import com.ui.design.view.pickviewselect.adapter.PickAdapter;
import com.ui.design.view.pickviewselect.bean.TestBean;
import com.ui.design.view.pickviewselect.view.PickRecycleView;
import com.ui.design.view.pickviewselect.view.PickerLayoutManager;
import java.util.ArrayList;
import java.util.List;
@Route(path = Constants.PickActivity)
public class PickActivity extends BaseActivity {
private PickerLayoutManager mPickerLayoutManager1;
private List<TestBean> testBeanList;
@Override
protected int initLayout() {
return R.layout.activity_pick;
}
@Override
protected void initView() {
TextView content = findViewById(R.id.content);
View bg=findViewById(R.id.bg);
PickRecycleView textRv = findViewById(R.id.text_rv);
testBeanList = new ArrayList<>();
testBeanList.addAll(getTestBeans());
mPickerLayoutManager1 = new PickerLayoutManager(this, textRv, PickerLayoutManager.VERTICAL, false,9,0.5f,true,3);
mPickerLayoutManager1.setCycle(true);
mPickerLayoutManager1.setOnSelectedViewListener(new PickerLayoutManager.OnSelectedViewListener() {
@Override
public void onSelectedView(View view, int position, int cycleNum) {
content.setText(testBeanList.get(position % testBeanList.size()).name);
if (position < testBeanList.size() * cycleNum || position >= testBeanList.size() * (cycleNum + 1)) {
mPickerLayoutManager1.scrollToPositionForCycle(position, testBeanList.size(), cycleNum);
}
}
@Override
public void onScrollMidView(View view, boolean iscenter) {
//中间VIew监听回调
if (iscenter){
((TextView)view.findViewById(R.id.item_wheel_tv)).setTextColor(Color.WHITE);//颜色设置 自定义效果
}else {
((TextView)view.findViewById(R.id.item_wheel_tv)).setTextColor(Color.BLACK);//颜色设置 自定义效果
}
}
});
textRv.setCenterView(bg);
PickAdapter pickAdapter = new PickAdapter(this, testBeanList, textRv);
textRv.setAdapter(pickAdapter);
}
@Override
protected void initData() {
}
private List<TestBean> getTestBeans() {
List<TestBean> testBeans = new ArrayList<>();
for (int i = 0; i < 10; i++) {
testBeans.add(new TestBean(RandomValue.getChineseName(),"123"+i));
}
return testBeans;
}
}
activity_pick.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/title_include" />
<TextView
android:id="@+id/content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_centerVertical="true"
android:layout_marginStart="20dp"
android:textSize="14sp"
android:textStyle="bold"/>
<RelativeLayout
android:id="@+id/relativeLayout"
android:layout_alignParentEnd="true"
android:layout_marginTop="100dp"
android:layout_marginBottom="50dp"
android:layout_width="200dp"
android:background="@color/cornflowerblue"
android:layout_height="match_parent">
<com.ui.design.view.pickviewselect.view.PickRecycleView
android:id="@+id/text_rv"
android:layout_width="wrap_content"
android:layout_height="match_parent"/>
<View
android:id="@+id/bg"
android:background="@android:color/darker_gray"
android:alpha="0.5"
android:layout_width="200dp"
android:layout_height="100dp"/>
</RelativeLayout>
</RelativeLayout>
项目代码仓库
如果直接复制可能会出现代码缺陷,完整代码请去仓库下载
如果觉得还行,耽误您几秒钟的时间去我的仓库点点star,万一以后用到了呢?