Android_字體變色,viewpager指示器

簡介

本篇是來自鴻洋_大神的Android 自定義控件玩轉字體變色 打造炫酷ViewPager指示器這篇博客,剛開始看時覺得不是很好理解,現在自己減去了他的一些代碼,自己寫的一個,也實現了同樣的效果,感覺好理解多了。
先看一下實現後的效果:
1

要實現這樣的文字跟隨viewpager的滑動而逐漸改變顏色的效果,這裏很明顯底色字一直在的,所以我們要考慮的主要是紅色字體的繪製。繪製紅色字體用的是canvas的clipRect()方法。根據要改變的寬度係數,切割要繪製的位置。這裏運用了自定義屬性,方便我們修改一些控件的屬性。

1,自定義屬性

attrs.xml文件

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <attr name="text" format="string"/>
    <attr name="textSize" format="dimension"/>
    <attr name="textOriginColor" format="color"/>
    <attr name="textChangeColor" format="color"/>
    <attr name="progress" format="float"/>
    <attr name="direction" >
        <enum name="left" value="0" />  
        <enum name="right" value="1" />  
    </attr>

    <declare-styleable name = "colortractview">
         <attr name="text" />  
        <attr name="textSize" />  
        <attr name="textOriginColor" />  
        <attr name="textChangeColor" />  
        <attr name="progress" />  
        <attr name="direction" />  
    </declare-styleable>
</resources>

activity_main.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:raise="http://schemas.android.com/apk/res/com.raise.colortrackview"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#fff" >

    <com.raise.colortrackview.ColorTrackView
        android:id="@+id/colortractview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:background="#ddd"
        raise:text="ColorTract測試"
        raise:textChangeColor="#ff0000"
        raise:textSize="30sp" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|center_horizontal" >

        <Button
            android:id="@+id/button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="left" />

        <Button
            android:id="@+id/button2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="rihgt" />
    </LinearLayout>

</FrameLayout>

ColorTrackView.java源碼

package com.raise.colortrackview;

import com.raise.colortrackview.R;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;

public class ColorTrackView extends View {

    //一些默認值
    private static final int DEFAULT_TEXTSIZE = 20;
    private static final int DIRECTION_LEFT = 0;
    private static final int DIRECTION_RIGHT = 1;
    private static final int DEFAULT_ORIGHT_COLOR = Color.BLACK;
    private static final int DEFAULT_CHANGE_COLOR = Color.RED;
/**
 * 設置顏色變化方向值
 * @author raise
 *
 */
    public enum Direction{
        Left,Right
    }
    /**
     * 字體畫筆
     */
    private Paint mPaint;
    /**
     * 要畫出的文字
     */
    private String mText;
    /**
     * 文字大小
     */
    private int mTextSize;
    /**
     * 原文字顏色
     */
    private int mOriginColor;
    /**
     * 拖動後的文字顏色
     */
    private int mChangeColor;
    /**
     * 變化進度
     */
    private float mProgress;
    /**
     * 變化方向
     */
    private int mDirection;
    /**
     * view的寬
     */
    private int mWidth;
    /**
     * view的高
     */
    private int mHeight;

    public ColorTrackView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        mPaint = new Paint();
        //讀取自定義屬性
        initDatas(context, attrs);
        //設置默認標題
        mText = mText == null ? "標題" : mText;
        mPaint.setTextSize(mTextSize);
        //字體的寬度和高度,作爲該控件的寬度和高度
        mWidth = (int) mPaint.measureText(mText);
        mHeight = (int) (mPaint.descent() - mPaint.ascent());

//      setBackgroundColor(Color.parseColor("#f1f1f1"));
    }

    private void initDatas(Context context, AttributeSet attrs) {
        TypedArray ta = context.obtainStyledAttributes(attrs,
                R.styleable.colortractview);
        mText = ta.getString(R.styleable.colortractview_text);
        mTextSize = ta.getDimensionPixelOffset(
                R.styleable.colortractview_textSize, sp2px(DEFAULT_TEXTSIZE));
        mDirection = ta.getInt(R.styleable.colortractview_direction,
                DIRECTION_LEFT);
        mOriginColor = ta.getColor(R.styleable.colortractview_textOriginColor,
                DEFAULT_ORIGHT_COLOR);
        mChangeColor = ta.getColor(R.styleable.colortractview_textChangeColor,
                DEFAULT_CHANGE_COLOR);
        mProgress = ta.getFloat(R.styleable.colortractview_progress, 0f);
        ta.recycle();
    }

    public ColorTrackView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ColorTrackView(Context context) {
        this(context, null);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // view的width,height等於字體的
        widthMeasureSpec = MeasureSpec.makeMeasureSpec(mWidth,
                MeasureSpec.EXACTLY);
        heightMeasureSpec = MeasureSpec.makeMeasureSpec(mHeight,
                MeasureSpec.EXACTLY);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        int startX = (int) (mProgress * mWidth);
        // 第一次繪出原字體
        mPaint.setColor(mOriginColor);
        canvas.drawText(mText, 0, mHeight - mPaint.descent(), mPaint);
        mPaint.setColor(mChangeColor);
        canvas.save();
        //第二次繪出變色字體
        if (mDirection == DIRECTION_LEFT) {
            //變色字出現在左邊,起點當然是(0,0)
            canvas.clipRect(0, 0, startX, mHeight);
        } else if (mDirection == DIRECTION_RIGHT) {
            //變色字出現在右邊,終點當然是(mWidth,mHeight)
            canvas.clipRect(mWidth-startX, 0, mWidth, mHeight);
        }
        //在指定區域繪出變色字
        canvas.drawText(mText, 0, mHeight - mPaint.descent(), mPaint);
        canvas.restore();
    }

    private int dp2px(int value) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                value, getResources().getDisplayMetrics());
    }

    private int sp2px(int value) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
                value, getResources().getDisplayMetrics());
    }
    public int getmDirection() {
        return mDirection;
    }

    public void setDirection(int direction) {
        this.mDirection = direction;
    }

    public void setProgress(float progress) {
        this.mProgress = progress;
        //注意這裏要重繪
        invalidate();
    }

}

和大神區別在於,我使用了字體的大小,做爲該View的大小,這樣理解起來簡單了許多,在使用的時候,只要在外部多加一層Linearlayout就可以了。
MainActivity.java源碼:

public class MainActivity extends Activity implements OnClickListener {

    ColorTrackView view ;
    Button leftbButton;
    Button rightButton;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        view = (ColorTrackView) findViewById(R.id.colortractview);
        leftbButton = (Button) findViewById(R.id.button1);
        rightButton = (Button) findViewById(R.id.button2);

        leftbButton.setOnClickListener(this);
        rightButton.setOnClickListener(this);

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public void onClick(View v) {
        if (v == leftbButton) {
            view.setDirection(0);
            Toast.makeText(MainActivity.this, "left", 1).show();
            ObjectAnimator.ofFloat(view, "progress", 0f,1f).setDuration(2000).start();
        }else if (v == rightButton) {
            Toast.makeText(MainActivity.this, "right", 1).show();
            view.setDirection(1);
            ObjectAnimator.ofFloat(view, "progress", 0f,1f).setDuration(2000).start();

        }

    }

}

效果圖:
1
和預想的一樣,看來簡化後沒問題。
下面看下將其使用到viewpager上。
TabFragment.java

public class TabFragment extends Fragment {

    private static final String TITLE = "title";

    private String mTitle = "default title";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        Bundle bundle = getArguments();
        if (bundle!=null) {
            mTitle = bundle.getString(TITLE);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        TextView view = new TextView(getActivity());
        view.setTextSize(30);
        Random r = new Random();
        view.setBackgroundColor(Color.argb(r.nextInt(120), r.nextInt(255),
                r.nextInt(255), r.nextInt(255)));
        view.setGravity(Gravity.CENTER);
        view.setText(mTitle);
        return view;
    }

    public static Fragment newInstance(String title) {
        TabFragment fragment = new TabFragment();
        Bundle bundle = new Bundle();
        bundle.putString(TITLE, title);
        fragment.setArguments(bundle);
        return fragment;

    }

}

TestActivity.java

public class TestActivity extends FragmentActivity implements
        OnPageChangeListener {

    private String[] mTitles = { "生活", "科技", "體育" };
    private ViewPager viewPager;
    //裝載指示器的list
    private List<ColorTrackView> viewList = new ArrayList<ColorTrackView>();
    private ColorTrackView colorView1;
    private ColorTrackView colorView2;
    private ColorTrackView colorView3;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test);
        initView();
        viewPager.setAdapter(adapter);
        viewPager.setOnPageChangeListener(this);
        viewList.add(colorView1);
        viewList.add(colorView2);
        viewList.add(colorView3);

        viewList.get(0).setProgress(1);
    }

    private void initView() {
        viewPager = (ViewPager) findViewById(R.id.viewpage);
        colorView1 = (ColorTrackView) findViewById(R.id.view_color1);
        colorView2 = (ColorTrackView) findViewById(R.id.view_color2);
        colorView3 = (ColorTrackView) findViewById(R.id.view_color3);
    }

    FragmentPagerAdapter adapter = new FragmentPagerAdapter(
            getSupportFragmentManager()) {
        @Override
        public int getCount() {
            return mTitles.length;
        }
        @Override
        public Fragment getItem(int arg0) {
            return TabFragment.newInstance(mTitles[arg0]);
        }
    };

    @Override
    public void onPageScrollStateChanged(int arg0) {
    }
    /*
     * arg0是左邊的fragment座標,arg1,0-1滑動係數,arg2隱藏的寬度
     */
    @Override
    public void onPageScrolled(int arg0, float arg1, int arg2) {
        // 不可滑動時退出
        if (arg1 == 0f) {
            return;
        }
        // 得到左邊的view
        ColorTrackView leftView = viewList.get(arg0);
        // 得到右邊的view
        ColorTrackView rightView = viewList.get(arg0 + 1);
        // 設置左邊view指示器狀態
        leftView.setDirection(1);
        leftView.setProgress(1 - arg1);
        // 設置右邊view指示器狀態
        rightView.setDirection(0);
        rightView.setProgress(arg1);
    }

    @Override
    public void onPageSelected(int arg0) {
    }
}

activity_test.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:raise="http://schemas.android.com/apk/res/com.raise.colortrackview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:background="#f1f1f1"
        android:gravity="center_vertical"
        android:orientation="horizontal"
        android:weightSum="3" >

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center"
            android:orientation="horizontal" >

            <com.raise.colortrackview.ColorTrackView
                android:id="@+id/view_color1"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                raise:text="生活"
                raise:textChangeColor="#c96666" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center"
            android:orientation="horizontal" >

            <com.raise.colortrackview.ColorTrackView
                android:id="@+id/view_color2"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                raise:text="科技"
                raise:textChangeColor="#c96666" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center"
            android:orientation="horizontal" >

            <com.raise.colortrackview.ColorTrackView
                android:id="@+id/view_color3"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                raise:text="體育"
                raise:textChangeColor="#c96666" />
        </LinearLayout>
    </LinearLayout>

    <android.support.v4.view.ViewPager
        android:id="@+id/viewpage"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

源碼:點我下載

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