与ViewPager合用的MyTitleLayout,可以设置滚动指示器

来源:互联网 发布:It 门槛 编辑:程序博客网 时间:2024/06/15 21:20

项目经理突然要求做一个有切换指向的标题头,开始想使用TabLayout,TabLayout的指示器只可以设置颜色,因此我就自己写了一个Layout,话不多说,先说下思路

  1. 可以设置多个、线性的标题,因此可以继承LinearLayout
  2. 指示图标可以使用onDraw绘制上去
  3. 根据ViewPager滑动进行设置指示图标的位置
  4. 可以手指滑动标题,进行切换ViewPager界面

思路就是这样,好了,话不多说,直接上代码

public class MyTitleLayout extends LinearLayout {    private int mCount;    private int mWidth;    private int mHeight;    private Paint mPaint;    private int mStartWidth;    private int mChildWidth;    private Bitmap mBitmap;    private int mStartX;    private int mTouchSlop;    //判断标题是否可以滑动,false:不可以    private boolean mCanScroll;    //标题滑动监听    private OnTitleScroll mOnTitleScroll;    private int mBitmapWidth;    private int mBitmapHeight;    public MyTitleLayout(Context context) {        super(context);        initData();    }    public MyTitleLayout(Context context, AttributeSet attrs) {        super(context, attrs);        initData();    }    public MyTitleLayout(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        initData();    }    private void initData() {        //不调用该方法不能进行绘制        setWillNotDraw(false);        mPaint = new Paint();        mPaint.setColor(Color.RED);        mPaint.setAntiAlias(true);        //初始化默认图标        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.mark);        mBitmap = Bitmap.createScaledBitmap(bitmap, bitmap.getWidth(), bitmap.getHeight(), true);    }    @Override    protected void onDraw(Canvas canvas) {        canvas.drawBitmap(mBitmap, mStartWidth + mChildWidth / 2 - mBitmapWidth / 2, mHeight - mBitmapHeight, mPaint);        super.onDraw(canvas);    }    public interface OnTitleScroll {        void onTitleScroll(int position);    }    /**     * 设置标题是否可以滑动,设置标题滑动监听     *     * @param onTitleScroll     * @param canScroll     */    public void setOnTitleScroll(OnTitleScroll onTitleScroll, boolean canScroll) {        mCanScroll = canScroll;        if (mCanScroll && onTitleScroll == null) {            mCanScroll = false;        }        mOnTitleScroll = onTitleScroll;    }    /**     * 滑动时调用该方法,参数为将要滑动到的position     *     * @param px     */    public void onScrollTo(int px) {        //viewPager会在position变化时突然传过来一个0,如果不进行判断,会重置        if (mStartWidth - px / 2 >= mWidth / (mCount + 1)) {            return;        }        mStartWidth = px / 2;        invalidate();    }    /**     * 滑动时调用该方法,参数为将要滑动的距离     *     * @param px     */    public void onScrollFor(int px) {        //边界判定        if ((mStartWidth + px) > 0 && (mStartWidth + px) < mChildWidth * (mCount - 1)) {            mStartWidth += px;            invalidate();        }    }    /**     * 滑动结束后调用,count为判定图标显示在第几个     *     * @param count     */    public void onFinishScroll(int count) {        mStartWidth = mChildWidth * count;        invalidate();    }    /**     * 滑动标题结束后调用该方法     */    private void onFinishScroll() {        mStartWidth += mChildWidth / 2 - mBitmapWidth / 2;        for (int i = 0; i < mCount; i++) {            int startPosition = mChildWidth * i;            int endPosition = mChildWidth * (i + 1);            if (mStartWidth >= startPosition && mStartWidth < endPosition) {                onFinishScroll(i);                if (mOnTitleScroll != null) {                    mOnTitleScroll.onTitleScroll(i);                }                break;            }        }    }    /**     * 使用外部拦截法     *     * @param event     * @return     */    @Override    public boolean onInterceptTouchEvent(MotionEvent event) {        if (!mCanScroll) {            return false;        }        boolean intercept = false;        int x = (int) getX();        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                intercept = false;                break;            case MotionEvent.ACTION_MOVE:                int moveX = (int) event.getX();                if (Math.abs(moveX - x) > mTouchSlop) {                    intercept = true;                } else {                    intercept = false;                }                break;            case MotionEvent.ACTION_UP:                intercept = false;                break;        }        return intercept;    }    @Override    public boolean onTouchEvent(MotionEvent event) {        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                mStartX = (int) event.getX();                break;            case MotionEvent.ACTION_MOVE:                int moveX = (int) event.getX();                onScrollFor(moveX - mStartX);                mStartX = moveX;                break;            case MotionEvent.ACTION_UP:                onFinishScroll();                break;        }        return true;    }    @Override    protected void onFinishInflate() {        super.onFinishInflate();        mCount = getChildCount();    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);    }    @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(w, h, oldw, oldh);        mWidth = getMeasuredWidth();        mHeight = getMeasuredHeight();        mChildWidth = mWidth / mCount;        mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();        mBitmapWidth = mBitmap.getWidth();        mBitmapHeight = mBitmap.getHeight();    }

控件虽然很简单,但是提供更换指示图标,可以根据ViewPager滑动,或者根据手势滑动。事件分发采用外部拦截法进行,比较简单。

控件项目地址:https://git.oschina.net/qiangshen/commentview.git
这是我开始维护的一个控件地址,这里面的控件都是我自己学习时或工作时写的,可能控件还有各种bug,可能我的做法太复杂或代码规范有问题,我希望大家可以帮我提出并改正。

0 0
原创粉丝点击