自定義View:02-滑動(dòng)變色的字體

效果圖如下:


滑動(dòng)文字.gif

一、自定義屬性
1.1钳恕、字體要變的顏色
1.2昂芜、字體不變的顏色
二莹规、繼承TextView
2.1、初始化畫筆 兩個(gè)字體畫筆 :變色與不變色
2.2泌神、onDraw() : 通過兩個(gè)畫筆(paint)畫出同一位置的兩次文字良漱,
* 通過canvas.clipRect() (畫布的裁剪方法),裁剪出要顯示文字的指定區(qū)域欢际,
* 通過裁剪方法母市、與Paint(畫筆)定義的顏色,可以實(shí)現(xiàn)同一文字不同顏色效果顯示
三 损趋、實(shí)現(xiàn)文字變色的朝向 :左到右患久、右到左
四、使用
與viewPager 的監(jiān)聽方法結(jié)合,通過加減偏移量 算出字體要顯示的部分區(qū)域蒋失,達(dá)到要實(shí)現(xiàn)的效果

實(shí)現(xiàn)

1返帕、自定義屬性:

沒有attrs.xml 文件就新建一個(gè)


image.png

attrs.xml

 <declare-styleable name="colorTextView">
    <!--1、初始化顏色-->
        <attr name="originColor" format="color"/> 
    <!--1篙挽、變化后的顏色-->
        <attr name="changeColor" format="color"/>
    </declare-styleable>

2荆萤、新建 ColorTextView_02 類,繼承TextView

@SuppressLint("AppCompatCustomView")
public class ColorTextView_02 extends TextView {
    //不變色字體的畫筆
    private Paint mOriginPaint;
    //改變顏色字體的畫筆
    private Paint mChangePaint;

    private float mCurrentProgress = 0f;//中心值

    private Direction mDirection=Direction.LEFT_TO_RIGHT; //方向

    /**
     * 實(shí)現(xiàn)思路
     * 1铣卡、創(chuàng)建自定義屬性:1.1链韭、字體要變的顏色 1.2、字體不變的顏色
     * 2算行、自定義TextView 梧油,繼承相關(guān)的屬性 :獲取文字的大小 、顏色
     * 3州邢、初始化畫筆 兩個(gè)字體畫筆 :變色與不變色
     * 4儡陨、繪制 :通過兩個(gè)畫筆(paint)畫出同一位置的兩次文字,
     *    通過canvas.clipRect() (畫布的裁剪方法)量淌,裁剪出要顯示文字的指定區(qū)域骗村,
     *    通過裁剪方法、與Paint(畫筆)定義的顏色呀枢,可以實(shí)現(xiàn)同一文字不同顏色效果顯示胚股,
     * 5、實(shí)現(xiàn)文字變色的朝向 :左到右裙秋、右到左
     *  6琅拌、與viewPager 的監(jiān)聽方法結(jié)合,通過加減偏移量 算出字體要顯示的部分區(qū)域摘刑,達(dá)到要實(shí)現(xiàn)的效果
     */

    /**
     * 左到右變色
     * 右到左變色
     */
    public enum Direction{
        LEFT_TO_RIGHT,RIGHT_TO_LEFT
    }

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

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

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

    /**
     * 初始化畫筆
     *
     * @param context
     * @param attrs
     */
    private void initPaint(Context context, AttributeSet attrs) {
        //自定義屬性
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.colorTextView);
        int originColor = array.getColor(R.styleable.colorTextView_originColor, getTextColors().getDefaultColor());
        int changeColor = array.getColor(R.styleable.colorTextView_changeColor, getTextColors().getDefaultColor());

        mOriginPaint = getPaintByColor(originColor);
        mChangePaint = getPaintByColor(changeColor);
    }

    /**
     * 根據(jù)顏色獲取畫筆
     */
    private Paint getPaintByColor(int color) {
        Paint paint = new Paint();
        paint.setColor(color);
        paint.setAntiAlias(true);
        paint.setDither(true);
        paint.setTextSize(getTextSize());
        return paint;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        //中心值
        int middle = (int) (mCurrentProgress * getWidth());

        if (mDirection==Direction.LEFT_TO_RIGHT){
            //不變色的字體
            drawText(canvas,mChangePaint , 0, middle);
            //變色的字體
            drawText(canvas,mOriginPaint , middle, getWidth());
        }else {
            //不變色的字體
            drawText(canvas, mChangePaint, getWidth()-middle, getWidth());
            //變色的字體
            drawText(canvas, mOriginPaint, 0, getWidth()-middle);
        }

    }

    /**
     * 繪制Text
     *
     * @param canvas
     * @param paint
     * @param start
     * @param end
     */
    public void drawText(Canvas canvas, Paint paint, int start, int end) {
        canvas.save(); //保存

        String text = getText().toString();//文字

        //裁剪
        Rect rect = new Rect(start, 0, end, getHeight());
        canvas.clipRect(rect);

        //獲取字體的寬度
        Rect bounds = new Rect();
        paint.getTextBounds(text, 0, text.length(), bounds);

        //獲取字體橫線中心的位置
        int x = getWidth() / 2 - bounds.width() / 2;

        //基線baseLine
        Paint.FontMetricsInt fontMetricsInt = paint.getFontMetricsInt();
        int dy = (fontMetricsInt.bottom - fontMetricsInt.top) / 2 - fontMetricsInt.bottom;//基線到底部的距離
        int baseLine = getHeight() / 2 + dy; //獲取基線

        //繪制文字
        canvas.drawText(text, x, baseLine, paint);

        canvas.restore();

    }

    //進(jìn)度
    public void setCurrentProgress(float progress) {
        mCurrentProgress = progress;
        invalidate();
    }

    //朝向
    public void setDirection(Direction direction){
        this.mDirection=direction;
    }

    //設(shè)置不變色的字體
    public void setOriginColor(int originColor){
        this.mOriginPaint.setColor(originColor);
    }

    //設(shè)置要變色的字體
    public void setChangeColor(int changeColor){
        this.mChangePaint.setColor(changeColor);
    }
}


3进宝、使用

view_text_02.xml

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

    android:padding="16dp">

    <com.example.view_day01.View.ColorTextView_02
        android:id="@+id/text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="自定義"
        android:textSize="20sp"
        app:changeColor="@color/colorAccent" />

    <Button
        android:id="@+id/left_ToRight"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        android:text="左到右" />

    <Button
        android:id="@+id/right_ToLeft"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="右到左" />

    <LinearLayout
        android:id="@+id/colorView_linear"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:orientation="horizontal"/>

    <androidx.viewpager.widget.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginTop="10dp"
        android:layout_weight="1" />
</LinearLayout>

fragment:

public class TextFragment_02 extends Fragment {
    private Button toRight, toLeft;
    private ColorTextView_02 colorView;
    private static final String TAG = "TextFragment_02";
    private ViewPager viewPager;
    private List<Fragment> fragmentList;
    private ViewPagerAdapter pagerAdapter;
    private List<ColorTextView_02> colorTextViewList;
    private LinearLayout colorView_linear;
    private String[] item = {"段子", "視頻", "漫畫", "小說", "軍事"};

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.view_text_02, container, false);
        init(view);
        initIndicator();
        setViewPager();
        return view;
    }

    private void init(View view) {
        colorView = view.findViewById(R.id.text_view);
        toRight = view.findViewById(R.id.left_ToRight);
        toLeft = view.findViewById(R.id.right_ToLeft);
        viewPager = view.findViewById(R.id.viewPager);
        colorView_linear = view.findViewById(R.id.colorView_linear);
        colorTextViewList = new ArrayList<>();
        fragmentList = new ArrayList<>();
        click();
    }

    /**
     * 初始化TabLayout
     */
    private void initIndicator() {
        for (int i = 0; i < item.length; i++) {
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            params.weight = 1;
            ColorTextView_02 view = new ColorTextView_02(getContext());
            view.setTextSize(20);
            view.setChangeColor(Color.RED);
            view.setText(item[i]);
            view.setLayoutParams(params);

            colorView_linear.addView(view);
            colorTextViewList.add(view);
            fragmentList.add(new PageFragment(item[i]));
        }
    }

    /**
     * 監(jiān)聽ViewPager的滑動(dòng)
     */
    private void setViewPager() {
        FragmentManager fragmentPagerAdapter = getActivity().getSupportFragmentManager();
        pagerAdapter = new ViewPagerAdapter(fragmentPagerAdapter);
        viewPager.setAdapter(pagerAdapter);
        viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            //操作前面的字體
                ColorTextView_02 view_02 = colorTextViewList.get(position);
                view_02.setDirection(ColorTextView_02.Direction.RIGHT_TO_LEFT);
                view_02.setCurrentProgress(1 - positionOffset);

                //操作后面的字體
                try {
                    ColorTextView_02 view = colorTextViewList.get(position+1);
                    view.setDirection(ColorTextView_02.Direction.LEFT_TO_RIGHT);
                    view.setCurrentProgress(positionOffset);
                }catch (Exception ignored){

                }

            }

            @Override
            public void onPageSelected(int position) {
                Log.d(TAG, "onPageSelected: " + position);
            }

            @Override
            public void onPageScrollStateChanged(int state) {
                Log.d(TAG, "onPageScrollStateChanged: " + state);
            }
        });
    }

    /**
     * 點(diǎn)擊事件
     */
    private void click() {
        toRight.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                leftToRight();
            }
        });
        toLeft.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                rightToLeft();
            }
        });
    }

    //從左到右變色
    private void leftToRight() {
        colorView.setDirection(ColorTextView_02.Direction.LEFT_TO_RIGHT);
        ValueAnimator animator = ObjectAnimator.ofFloat(0, 1);
        animator.setDuration(2000);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                Log.d(TAG, "onAnimationUpdate: " + (float) animation.getAnimatedValue());
                colorView.setCurrentProgress((float) animation.getAnimatedValue());
            }
        });
        animator.start();
    }

    //從右到左變色
    private void rightToLeft() {
        colorView.setDirection(ColorTextView_02.Direction.RIGHT_TO_LEFT);
        ValueAnimator animator = ObjectAnimator.ofFloat(0, 1);
        animator.setDuration(2000);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                colorView.setCurrentProgress((float) animation.getAnimatedValue());
            }
        });
        animator.start();
    }

    /**
     * ViewPager 適配器
     */
    class ViewPagerAdapter extends FragmentPagerAdapter {

        public ViewPagerAdapter(@NonNull FragmentManager fm) {
            super(fm);
        }

        @NonNull
        @Override
        public Fragment getItem(int position) {
            return fragmentList.get(position);
        }

        @Override
        public int getCount() {
            return fragmentList.size();
        }
    }
}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市枷恕,隨后出現(xiàn)的幾起案子党晋,更是在濱河造成了極大的恐慌,老刑警劉巖徐块,帶你破解...
    沈念sama閱讀 216,997評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件未玻,死亡現(xiàn)場離奇詭異,居然都是意外死亡胡控,警方通過查閱死者的電腦和手機(jī)扳剿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來铜犬,“玉大人舞终,你說我怎么就攤上這事轻庆。” “怎么了敛劝?”我有些...
    開封第一講書人閱讀 163,359評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵余爆,是天一觀的道長。 經(jīng)常有香客問我夸盟,道長蛾方,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,309評(píng)論 1 292
  • 正文 為了忘掉前任上陕,我火速辦了婚禮桩砰,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘释簿。我一直安慰自己亚隅,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,346評(píng)論 6 390
  • 文/花漫 我一把揭開白布庶溶。 她就那樣靜靜地躺著煮纵,像睡著了一般。 火紅的嫁衣襯著肌膚如雪偏螺。 梳的紋絲不亂的頭發(fā)上行疏,一...
    開封第一講書人閱讀 51,258評(píng)論 1 300
  • 那天,我揣著相機(jī)與錄音套像,去河邊找鬼酿联。 笑死,一個(gè)胖子當(dāng)著我的面吹牛夺巩,可吹牛的內(nèi)容都是我干的贞让。 我是一名探鬼主播,決...
    沈念sama閱讀 40,122評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼柳譬,長吁一口氣:“原來是場噩夢啊……” “哼震桶!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起征绎,我...
    開封第一講書人閱讀 38,970評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎磨取,沒想到半個(gè)月后人柿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,403評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡忙厌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,596評(píng)論 3 334
  • 正文 我和宋清朗相戀三年凫岖,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片逢净。...
    茶點(diǎn)故事閱讀 39,769評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡哥放,死狀恐怖歼指,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情甥雕,我是刑警寧澤踩身,帶...
    沈念sama閱讀 35,464評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站社露,受9級(jí)特大地震影響挟阻,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜峭弟,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,075評(píng)論 3 327
  • 文/蒙蒙 一附鸽、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧瞒瘸,春花似錦坷备、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至谎柄,卻和暖如春丁侄,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背朝巫。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評(píng)論 1 269
  • 我被黑心中介騙來泰國打工鸿摇, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人劈猿。 一個(gè)月前我還...
    沈念sama閱讀 47,831評(píng)論 2 370
  • 正文 我出身青樓拙吉,卻偏偏與公主長得像,于是被迫代替她去往敵國和親揪荣。 傳聞我的和親對(duì)象是個(gè)殘疾皇子筷黔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,678評(píng)論 2 354