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);
            }
        });

效果圖如下:

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章