Android 横向滑动选择

时间:2021-03-24 19:43:37
横向滑动选择,自定义adapter,支持adapter宽度不一样,兼容性高
 
 
 
selectView = new LateralSlidingSelectionView(this);
selectView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,width/4));
selectView.setmIndex(index);//默认为0 final String[] text = new String[10];
text[0] = "可以";
text[1] = "可以大发";
text[2] = "可以大发";
text[3] = "可以大发";
text[4] = "可以范德萨发";
text[5] = "可以范德萨发";
text[6] = "可以范德萨发";
text[7] = "可";
text[8] = "可";
text[9] = "可以大";
final LateralSlidingSeletionAdapter adapter = new LateralSlidingSeletionAdapter(this,text);
selectView.setMyOnListener(new LateralSlidingSelectionViewListener() {
    @Override
    public void click(int index) {
        Log.d("LateralSlidingSelection2View",text[index]);
        adapter.setSelectIndex(index);
        adapter.notifyDataSetChanged();
        selectView.updataAdapter(adapter);
    }
});
selectView.setAdapter(adapter);
selectView.startCanvase();

 
public class LateralSlidingSelectionView extends LinearLayout {

    private Context mContext;
    private OverScroller mOverScroller;
    private LateralSlidingSelectionViewListener mOnListener;
    private float downX;
    private float moveX;
    private Adapter mAdapter;
    private int mIndex;
    private LinearLayout linearLayout;
    private int[] adapterWidth;
    private int mStartX = 0;
    private int linearLayoutWidth;
    private int disX;
    private int mMoveStartX;

    public LateralSlidingSelectionView(Context context) {
        super(context);
        init(context);
    }

    public LateralSlidingSelectionView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public LateralSlidingSelectionView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }
    public void startCanvase(){
        addView();
    }

    private void addView(){
        if(mAdapter == null)
            return;
        removeAllViews();
        adapterWidth = new int[mAdapter.getCount()];
        linearLayout = new LinearLayout(mContext);
        LayoutParams linearLayoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        linearLayout.setLayoutParams(linearLayoutParams);
        linearLayout.setGravity(Gravity.CENTER);
        for (int i = 0; i < mAdapter.getCount(); i++) {
            View v = mAdapter.getView(i, null, null);
            final int finalI = i;
            v.setOnTouchListener(new OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    switch (event.getAction()) {
                        case MotionEvent.ACTION_DOWN:
                            downX = event.getRawX();
                            disX = 0;
                            break;
                        case MotionEvent.ACTION_MOVE:
                            moveX = event.getRawX();
                            disX = (int)(moveX - downX);
                            smoothScrollTo(-disX-mStartX);
                            mMoveStartX = mStartX + disX;
                            int index = getUpIndex(mMoveStartX);//滑动过程中计算index  if(mIndex!=index){
                                mIndex = index;
                                if(mOnListener!=null){
                                    mOnListener.click(index);
                                }
                            }
                            break;
                        case MotionEvent.ACTION_UP:
                            //判断滑动是否超过10  if(Math.abs(disX) > 10) {
                                mStartX += disX;
                                setIndex(getUpIndex(mStartX));
                            }else{
                                mIndex = finalI;
                                if(mOnListener!=null){
                                    mOnListener.click(finalI);
                                }
                                setIndex(finalI);
                            }
                            break;
                    }
                    return true;
                }
            });
            adapterWidth[i] = getViewWidth(v);
            linearLayout.addView(v);
        }
        //计算adapter 总宽度  int adapterWidths = 0;
        for (int i = 0; i < adapterWidth.length; i++) {
            adapterWidths += adapterWidth[i];
        }
        linearLayout.setLayoutParams(new LayoutParams(adapterWidths, ViewGroup.LayoutParams.WRAP_CONTENT));
        addView(linearLayout);
        linearLayoutWidth = getViewWidth(linearLayout);

        setIndex(mIndex);
    }

    /**  * 根据滑动偏移计算index  * @return  */  private int getUpIndex(int movelenght){
        int index = 0;
        int leftWidth = linearLayoutWidth/2-movelenght;
        if(leftWidth>=linearLayoutWidth){//判断是否划过超过右边  index = adapterWidth.length-1;
        }else{
            int leftValue = 0;
            for (int j = 0; j < adapterWidth.length; j++) {
                leftValue += adapterWidth[j];
                if (leftValue >= leftWidth) {
                    index = j;
                    break;
                }
            }
        }
        return index;
    }
    /**  * 定位到该位置  * @param index  */  private void setIndex(int index){
        if (index>adapterWidth.length-1)
            index = 0;
        int leftValue = 0;
        for (int i = 0; i < index; i++) {
            leftValue += adapterWidth[i];
        }

        mStartX = linearLayoutWidth/2-leftValue-adapterWidth[index]/2;
        smoothScrollTo(-mStartX);
    }

    /**  * 更新adapter  * @param adapter  */  public void updataAdapter(Adapter adapter){
        setAdapter(adapter);
        addView();
    }

    /**  * 初始化  * @param context  */  private void init(Context context) {
        mContext = context;
        mOverScroller = new OverScroller(getContext());
        setOverScrollMode(OVER_SCROLL_ALWAYS);
        setOrientation(LinearLayout.HORIZONTAL);
        setGravity(Gravity.CENTER);
    }
    public void setMyOnListener(LateralSlidingSelectionViewListener onListener){
        this.mOnListener = onListener;
    }
    public void setAdapter(Adapter adapter) {
        this.mAdapter = adapter;
    }
    public void setmIndex(int mIndex) {
        this.mIndex = mIndex;
    }

    //调用此方法滚动到目标位置  public void smoothScrollTo(int fx) {
        int dx = fx - mOverScroller.getFinalX();
        smoothScrollBy(dx, mOverScroller.getFinalY());
    }

    //调用此方法设置滚动的相对偏移  public void smoothScrollBy(int dx, int dy) {
        //设置mScroller的滚动偏移量  mOverScroller.startScroll(mOverScroller.getFinalX(), mOverScroller.getFinalY(), dx, dy);
        invalidate();//这里必须调用invalidate()才能保证computeScroll()会被调用,否则不一定会刷新界面,看不到滚动效果  }

    @Override
    public void computeScroll() {
        //先判断mScroller滚动是否完成  if (mOverScroller.computeScrollOffset()) {
            //这里调用View的scrollTo()完成实际的滚动  scrollTo(mOverScroller.getCurrX(), mOverScroller.getCurrY());
            //必须调用该方法,否则不一定能看到滚动效果  postInvalidate();
        }
        super.computeScroll();
    }
    /**  * 获取控件的宽度  * @param view  * @return  */  public static int getViewWidth(View view) {
        int width = 0;
        width = view.getWidth();
        if (width <= 0) {
            measureView(view);
            width = view.getMeasuredWidth();
        }
        return width;
    }
    /**  * 测量角度  * @param v  */  public static void measureView(View v) {
        int w = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
        int h = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
        v.measure(w, h);
    }

}

public abstract class LateralSlidingSelectionViewListener {
    public abstract void click(int index);
}