android自定义控件基础--绘制可以左右滑动的线

在分析Magic源码的时候,深受启发,发现了很多有用的点,要一步一步的剖析才能理解的更深,这里就在title的下滑线的基础上进行详细分析,

一、 基于HorizontalScrollView可以滚动的TextView

我们定义一个LinearLayout,然后在LinearLayou中添加自定义的TextView,这时我们会发现,它并不能滚动,只是显示为了一行,代码和效果如下,在这里是循环了10次,添加了10个textview,并且要求textview是单行的和缩略的。

  for(int i=0;i<10;i++){
            LinearLayout.LayoutParams lp=new LinearLayout.LayoutParams(
                    ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT
            );

            TextView textView =new TextView(this);
            textView.setText("文字测试"+i);
            lp.weight=i;
            textView.setLayoutParams(lp);
            textView.setSingleLine();
            textView.setEllipsize(TextUtils.TruncateAt.END);
            ll_title.addView(textView);

        }

在手机上显示的效果如下,可以看得到这个textview并不是滚动的,而是铺满屏幕的。

这时候我们只用在布局上使用HorizontalScrollView,包裹住我们的LinearLayout即可实现LinearLayout的滚动,这是一个非常简单的基础点。效果如下图,可以看到明显的下划线,是可以滚动的,并且文字的也可以显示完整了。

二、绘制一条可以滑动的线

           2.1 首先我们要在屏幕绘制一条粗线条,这个可以在onDraw方法中实现,我们定义一个RectF,定义他的上下左右四个边距,然后再定义画笔和就可以实现了,代码如下       

  private void init(){
        paint.setColor(Color.BLUE);
        rectF.left=30;
        rectF.right=60;
        rectF.top=90;
        rectF.bottom=120;
    }
    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawRoundRect(rectF,8,8,paint);
    }

           2.2 实现线的水平滑动,这主要是利用重绘的原理实现的,我们需要不断的修改线的left和right的值,来实现滚动

,这其实是一个难点,这里只是提一下,后面会当做难点来讲解,因为这里涉及到了偏移量的问题,还有回调效果。这两个难点,是需要计算。

        //移动到固定位置    
        rectF.left=30;
        rectF.right=60;

   三、实现所画的线随着ViewPager的滑动而滑动

            1.1 在这里使用的ViewPager为基础来实现的,在这里也要介绍一下ViewPager的OnPageScrolled方法,在这里主要就是利用了positionOffset来实现,这是一个ViewPager的偏移量,是一个小于1的小数。

public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) 

{
        //position表示滚动的位置
        //positionOffset表示滚动的偏移量,这个是重点
        //positionOffsetPixels 表示偏移的像素
}

         我们要控制线滑动的边距和速度,在这里使用rectF.left控制移动,用getInterpolation控制速度,当向右移动的距离超过屏幕的宽度时则停止移动。

虽然是控制rectF.left来实现移动,但是这个移动的位置应该事先确定好,这样子,才能移动到想要移动的位置,所以

        rectF.left=rectF.left+(50)*mStartInterpolator.getInterpolation(positionOffset);
        rectF.right= rectF.right+50*mEndInterpolator.getInterpolation(positionOffset);

这种写法是不对的,recfF.left应该换成固定的坐标,具体的写法如下,这样子就实现了线的平滑移动。

            rectF.left =100 + 500*mStartInterpolator.getInterpolation(v);
            rectF.right = 130 +500* mEndInterpolator.getInterpolation(v);

四、实现所画的线随着HorizontalScrollView的滑动而滑动

这个实现的原理,主要是利用了HorizontalScrollView的onScrollChanged方法

首先我们自定义HorizontalScrollView

public class MyHorizontalScrollView extends HorizontalScrollView {


    public interface ScrollViewListener {

        void onScrollChanged(HorizontalScrollView scrollView, int x, int y, int oldx, int oldy);

    }

    private ScrollViewListener scrollViewListener = null;

    public MyHorizontalScrollView(Context context) {
        super(context);
    }


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

    public MyHorizontalScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public MyHorizontalScrollView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }


    public void setScrollViewListener(ScrollViewListener scrollViewListener) {
        this.scrollViewListener = scrollViewListener;
    }

    @Override
    protected void onScrollChanged(int x, int y, int oldx, int oldy) {
        super.onScrollChanged(x, y, oldx, oldy);
        if (scrollViewListener != null) {
            scrollViewListener.onScrollChanged(this, x, y, oldx, oldy);
        }
    }
}

定义一个新的线可以滑动的线的控件

public class ScrollLineIndicator extends View {


    RectF rectF =new RectF();
    Paint mPaint;

    public ScrollLineIndicator(Context context) {
        super(context);
    }

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

    public ScrollLineIndicator(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    public ScrollLineIndicator(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }

    private void init() {
        rectF.left=50;
        rectF.right=100;
        rectF.top=50;
        rectF.bottom=100;
        mPaint=new Paint();
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawRoundRect(rectF,0,0,mPaint);
    }

    public  void onScrollChanged(int x, int y, int oldx, int oldy) {
        rectF.left=x;
        rectF.right=x+50;

        invalidate();
    }

实现滚动

       scrollView.setScrollViewListener(new MyHorizontalScrollView.ScrollViewListener() {
            @Override
            public void onScrollChanged(HorizontalScrollView scrollView, int x, int y, int oldx, int oldy) {
                scrollLineIndicator.onScrollChanged(x,y,oldx,oldy);
            }
        });

效果图如下:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值