viewpager文字渐变指示器

viewpager文字渐变指示器

//ZSG 一、
// 切换fragment 四部曲,一个FragmentManager 三个事物(和GIT的提交很像begin后,add,commit)
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.add(R.id.framelayout, MainFragment.newIntance(), MainFragment.class.getName());
transaction.commit();
    @Directions
    private int mDirection = DIRECTION_LEFT;

//ZSG
// 注解代替枚举,关键是@IntDef
//被注解Directions修饰的属性只能赋值这几个。
@IntDef(flag = true,value = {DIRECTION_LEFT,DIRECTION_RIGHT,DIRECTION_TOP,DIRECTION_BOTTOM})
@Retention(RetentionPolicy.SOURCE)
public @interface Directions {

}


一、与viewpager搭配的文字渐变view,在viewpager滑动的时候设置progress并且重绘view

package com.example.mytextdraw.View;

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

import androidx.annotation.IntDef;
import androidx.annotation.Nullable;

import com.example.mytextdraw.R;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

public class ColorChangeTextView extends View {

    private Paint mPaint;
    private Paint mLinePaint;
    private String mText = "哈哈哈";
    private int mTextSize = sp2px(30);
    private int mTextColor = Color.BLACK;
    private int mTextColorChange = Color.RED;
    private float mProgress;

    public static final int DIRECTION_LEFT = 0;
    public static final int DIRECTION_RIGHT = 1;
    public static final int DIRECTION_TOP = 2;
    public static final int DIRECTION_BOTTOM = 3;
    @Directions
    private int mDirection = DIRECTION_LEFT;
    private Rect mTextBounds = new Rect();
    private float mTextWidth;
    private float mTextStartX;
    private float mTextStartY;

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

    public ColorChangeTextView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    public ColorChangeTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
        initAttr(context,attrs);
    }

    public float getmProgress() {
        return mProgress;
    }

    public void setmProgress(float mProgress) {
        this.mProgress = mProgress;
        invalidate();
    }

    public int getmDirection() {
        return mDirection;
    }

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

    //ZSG
    // 注解代替枚举,关键是@IntDef
    @IntDef(flag = true,value = {DIRECTION_LEFT,DIRECTION_RIGHT,DIRECTION_TOP,DIRECTION_BOTTOM})
    @Retention(RetentionPolicy.SOURCE)
    public @interface Directions {

    }

    private void initAttr(Context context, AttributeSet attrs) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ColorChangeTextView);
        mText = typedArray.getString(R.styleable.ColorChangeTextView_text);
        mTextSize = typedArray.getDimensionPixelSize(
                R.styleable.ColorChangeTextView_text_size,mTextSize);
        mTextColor = typedArray.getColor(R.styleable.ColorChangeTextView_text_color, mTextColor);
        mTextColorChange = typedArray.getColor(R.styleable.ColorChangeTextView_text_color_change,mTextColorChange);
        mProgress = typedArray.getFloat(R.styleable.ColorChangeTextView_progress, 0);
        mDirection = typedArray.getInt(R.styleable.ColorChangeTextView_direction, mDirection);

        typedArray.recycle();
        mPaint.setTextSize(mTextSize);
    }

    private void init() {
        mPaint = new Paint();
        mLinePaint = new Paint();
        mLinePaint.setColor(Color.GREEN);
        mLinePaint.setStyle(Paint.Style.STROKE);
        mLinePaint.setStrokeWidth(dp2px(3));
        mLinePaint.setAntiAlias(true);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        measureText();

        int width = measureWidth(widthMeasureSpec);
        int height = measureHeight(heightMeasureSpec);
        setMeasuredDimension(width,height);

        mTextStartX = getMeasuredWidth() / 2 - mTextWidth / 2;
        mTextStartY = getMeasuredHeight() / 2 - mTextBounds.height() / 2;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        switch (mDirection) {
            //ZSG
            //这里不论向左滑还是向右滑,
            // 都是左边先画黑色然后画红色,
            // 右边总是先画红色后画黑色
            case DIRECTION_LEFT:
                mPaint.setColor(mTextColorChange);
                canvas.save();
                Rect rect = new Rect((int) mTextStartX, 0,
                        (int) (mTextStartX + mProgress * mTextWidth), getMeasuredHeight());
                canvas.clipRect(rect);
                //ZSG
                //注意这里传入的是canvas.getClipBounds() ,当clip为空的时候会返回0,
                // 如果直接传入rect的话为空的时候还有有一个线条、
                canvas.drawRect(canvas.getClipBounds(),mLinePaint);
                //ZSG
                // 注意理解这里drawText里的参数不是上下左右,是起始点和baseline
                canvas.drawText(mText,mTextStartX,
                        getMeasuredHeight()/2 - (mPaint.descent()/2 + mPaint.ascent()/2),
                        mPaint);
                canvas.restore();
                mPaint.setColor(mTextColor);
                canvas.save();
                Rect rect1 = new Rect((int) (mTextStartX + mProgress * mTextWidth), 0, (int) ( mTextStartX + mTextWidth), getMeasuredHeight());
                canvas.clipRect(rect1);
                canvas.drawText(mText,mTextStartX,
                        getMeasuredHeight()/2 - (mPaint.descent()/2 + mPaint.ascent()/2),mPaint);
                canvas.restore();
                break;
            case DIRECTION_RIGHT:
                mPaint.setColor(mTextColor);
                canvas.save();
                Rect rect2 = new Rect((int) mTextStartX, 0, (int) (mTextStartX + mProgress * mTextWidth),  getMeasuredHeight());
                canvas.clipRect(rect2);
                canvas.drawText(mText,mTextStartX,
                        getMeasuredHeight()/2 - (mPaint.descent()/2 + mPaint.ascent()/2),mPaint);
                canvas.restore();

                mPaint.setColor(mTextColorChange);
                canvas.save();
                Rect rect3 = new Rect((int) (mTextStartX + mProgress * mTextWidth), 0, (int) (mTextStartX + mTextWidth), getMeasuredHeight());
                canvas.clipRect(rect3);
                canvas.drawText(mText,mTextStartX,getMeasuredHeight()/2 - (mPaint.descent()/2 + mPaint.ascent()/2),mPaint);
                canvas.restore();

        }
    }

    private int measureHeight(int heightMeasureSpec) {
        int mode = MeasureSpec.getMode(heightMeasureSpec);
        int size = MeasureSpec.getSize(heightMeasureSpec);
        int result = 0;
        switch (mode) {
            case MeasureSpec.EXACTLY:
                result = size;
                break;
            case MeasureSpec.AT_MOST:
                result = (int) ((mTextBounds.height() + 0.5f) + getPaddingTop() + getPaddingBottom());
                if (result > size) {
                    result = size;
                }
                break;
            case MeasureSpec.UNSPECIFIED:
                result = (int) ((mTextBounds.height() + 0.5f) + getPaddingTop() + getPaddingBottom());
                break;
        }
        return result;
    }

    private int measureWidth(int widthMeasureSpec) {
        int mode = MeasureSpec.getMode(widthMeasureSpec);
        int size = MeasureSpec.getSize(widthMeasureSpec);
        int result = 0;
        switch (mode) {
            case MeasureSpec.EXACTLY:
                result = size;
                break;
                case MeasureSpec.AT_MOST:
                    result = (int) ((mTextWidth + .5f) + getPaddingLeft() + getPaddingRight());
                    if (result > size) {
                        result = size;
                    }
                    break;
                case MeasureSpec.UNSPECIFIED:
                        result = (int) ((mTextWidth + .5f) + getPaddingLeft() + getPaddingRight());
                        break;
            }
            return result;
        }

    private void measureText() {
        mPaint.getTextBounds(mText,0,mText.length(),mTextBounds);
        mTextWidth = mPaint.measureText(mText) + .5f;
    }

    private static float dp2px(int dp) {

        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                dp, Resources.getSystem().getDisplayMetrics());
    }

    static int sp2px(float dp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
                dp, Resources.getSystem().getDisplayMetrics());
    }
}

二、文字绘制的基本,baseline

package com.example.mytextdraw.View;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatTextView;

import org.jetbrains.annotations.NotNull;

public class SimpleColorChangeTextView extends AppCompatTextView {
    private String mText = "张三桂桂";

    float percent = 0f;

    public void setPercent(float percent) {
        this.percent = percent;
        invalidate();
    }

    public SimpleColorChangeTextView(@NonNull @NotNull Context context) {
        super(context);
    }

    public SimpleColorChangeTextView(@NonNull @NotNull Context context, @Nullable @org.jetbrains.annotations.Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public SimpleColorChangeTextView(@NonNull @NotNull Context context, @Nullable @org.jetbrains.annotations.Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        Paint paint = new Paint();
        paint.setTextSize(80);
        float baseLine = 100;
        canvas.drawText(mText,0,baseLine,paint);

        drawCenterLineX(canvas);
        drawCenterLineY(canvas);
        float x = getWidth()/2;
        canvas.drawText(mText,x,baseLine,paint);

        paint.setTextAlign(Paint.Align.CENTER);
        //ZSG 二、1
        // paint.getFontSpacing()
        // 建议的行间距
        canvas.drawText(mText,getWidth()/2,baseLine + paint.getFontSpacing(),paint);

        paint.setTextAlign(Paint.Align.RIGHT);
        canvas.drawText(mText,x,baseLine+paint.getFontSpacing()*2,paint);

        drawCenterText(canvas);
        drawCenterText1(canvas);
    }

    private void drawCenterText(Canvas canvas) {
        //ZSG 二、2
        // 1、设置画笔
        // 2、测量文字,确定抠图
        // 3、draw文字
        canvas.save();
        Paint paint = new Paint();
        paint.setStyle(Paint.Style.FILL);
        paint.setAntiAlias(true);
        paint.setTextSize(80);
        paint.setTextAlign(Paint.Align.LEFT);

        float width = paint.measureText(mText);
        float left = getWidth() / 2 - width / 2;
        float left_x = left + width *percent;
        Rect rect = new Rect((int) left_x, 0, getWidth(), getHeight());
        canvas.clipRect(rect);

        Paint.FontMetrics fontMetrics = paint.getFontMetrics();
        //ZSG 二、3
        //注意baseline的测量
        float baseline = getHeight() / 2 + (fontMetrics.descent - fontMetrics.ascent) / 2 - fontMetrics.descent;
        canvas.drawText(mText,left,baseline,paint);
        canvas.restore();
    }

    private void drawCenterText1(Canvas canvas) {
        canvas.save();
        Paint paint = new Paint();
        paint.setStyle(Paint.Style.FILL);
        paint.setAntiAlias(true);
        paint.setTextSize(80);
        paint.setColor(Color.RED);
        paint.setTextAlign(Paint.Align.LEFT);

        float width = paint.measureText(mText);
        float right = getWidth() / 2 - width / 2;
        float right_x = right + width *percent;
        Rect rect = new Rect( 0, 0, (int) right_x, getHeight());
        canvas.clipRect(rect);

        Paint.FontMetrics fontMetrics = paint.getFontMetrics();
        float baseline = getHeight() / 2 + (fontMetrics.descent - fontMetrics.ascent) / 2 - fontMetrics.descent;
        canvas.drawText(mText,right,baseline,paint);
        canvas.restore();
    }

    private void drawCenterLineY(Canvas canvas) {
        Paint paint = new Paint();
        paint.setColor(Color.BLUE);
        paint.setStyle(Paint.Style.FILL);
        paint.setStrokeWidth(3);
        canvas.drawLine(getWidth()/2,0,getWidth()/2,getHeight(),paint);
    }

    private void drawCenterLineX(Canvas canvas) {
        Paint paint = new Paint();
        paint.setColor(Color.RED);
        paint.setStyle(Paint.Style.FILL);
        paint.setStrokeWidth(3);
        canvas.drawLine(0,getHeight()/2,getWidth(),getHeight()/2,paint);
    }
}

三、viewpager

package com.example.mytextdraw.activities;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentPagerAdapter;
import androidx.viewpager.widget.ViewPager;

import android.os.Bundle;
import android.view.View;

import com.example.mytextdraw.R;
import com.example.mytextdraw.View.ColorChangeTextView;
import com.example.mytextdraw.fragment.TagFragment;

import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.List;

public class ViewPagerActivity extends AppCompatActivity {

    private String[] mTitles = new String[]{"关注", "热点", "推荐", "上海"};
    private ViewPager viewPage;
    private TagFragment[] tagFragments = new TagFragment[mTitles.length];
    List<ColorChangeTextView> tabs = new ArrayList<ColorChangeTextView>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_view_pager);

        initView();
        initData();
        initEvent();
    }

    private void initEvent() {
        viewPage.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            //ZSG
            //这里将几个自定义的view放到集合中通过ViewPager的position去取
            //注意ViewPager的position不管怎么滑动都是最小的位置处
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                if (positionOffset > 0) {
                    ColorChangeTextView left = tabs.get(position);
                    ColorChangeTextView right = tabs.get(position + 1);
                    left.setmDirection(ColorChangeTextView.DIRECTION_RIGHT);
                    right.setmDirection(ColorChangeTextView.DIRECTION_LEFT);
                    left.setmProgress(positionOffset);
                    right.setmProgress(positionOffset);
                }
            }

            @Override
            public void onPageSelected(int position) {

            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });
    }

    private void initData() {
        for (int i = 0; i < mTitles.length; i++) {
            tagFragments[i] = TagFragment.newInstance(mTitles[i]);
        }
        FragmentPagerAdapter pagerAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) {

            @Override
            public int getCount() {
                return tagFragments.length;
            }

            @NonNull
            @NotNull
            @Override
            public Fragment getItem(int position) {
                return tagFragments[position];
            }
        };
        viewPage.setAdapter(pagerAdapter);
        viewPage.setCurrentItem(0);
    }

    private void initView() {
        viewPage = findViewById(R.id.viewpager);
        tabs.add(findViewById(R.id.id_tab_01));
        tabs.add(findViewById(R.id.id_tab_02));
        tabs.add(findViewById(R.id.id_tab_03));
        tabs.add(findViewById(R.id.id_tab_04));
    }
}

四、文字渐变基本,属性动画

handler.postDelayed(new Runnable() {
    @Override
    public void run() {
        //ZSG 三、
        // 这里的percent是在 view 里设置了set方法的 成员属性,属性动画会去反射获取
        ObjectAnimator.ofFloat(view,"percent",0,1).setDuration(5000)
                .start();
    }
}, 2000);

五、fragment的创建以及返回

package com.example.mytextdraw.fragment;

import android.graphics.Color;
import android.os.Bundle;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

import org.jetbrains.annotations.NotNull;

import java.util.Random;

public class TagFragment extends Fragment {

    public static final String TITLE = "title";
    private String mTitle = "Default value";

    @Override
    public void onCreate(@Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mTitle = getArguments().getString(TITLE);
        }
    }

    @Nullable
    @org.jetbrains.annotations.Nullable
    @Override
    //ZSG fragment 中onCreateView 返回的什么view ,fragment就显示什么view
    public View onCreateView(@NonNull @NotNull LayoutInflater inflater, @Nullable @org.jetbrains.annotations.Nullable ViewGroup container, @Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) {
        TextView textView = new TextView(getActivity());
        textView.setTextSize(60);
        Random random = new Random();
        textView.setBackgroundColor(Color.argb(random.nextInt(120),random.nextInt(255)
        ,random.nextInt(255),random.nextInt(255)));
        textView.setText(mTitle);
        textView.setGravity(Gravity.CENTER);

        return textView;
    }

    public static TagFragment newInstance(String title) {
        TagFragment tagFragment = new TagFragment();
        Bundle bundle = new Bundle();
        bundle.putString(TITLE,title);
        tagFragment.setArguments(bundle);
        return tagFragment;
    }
}

六、自定义属性的三角恋、

<?xml version="1.0" encoding="utf-8"?>
<!--ZSG-->
<!--在attr中declare-styleable name设置为自定义view的类名,则在xml里使用的时候studio会自动帮忙生成这句-->
<!--xmlns:app="http://schemas.android.com/apk/res-auto"-->
<!--styleable、XML、view类-->
<!--自定义attr的三角恋,styleable用自定义view Java类的名字,xml用styleable的属性,Java类用xml的设置-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".activities.ViewPagerActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:orientation="horizontal" >

        <com.example.mytextdraw.View.ColorChangeTextView
            android:id="@+id/id_tab_01"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            app:progress="1"
            app:text="关注"
            app:text_color="#ff000000"
            app:text_color_change="#ffff0000"
            app:text_size="18sp" />

        <com.example.mytextdraw.View.ColorChangeTextView
            android:id="@+id/id_tab_02"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            app:text="热点"
            app:text_color="#ff000000"
            app:text_color_change="#ffff0000"
            app:text_size="18sp" />

        <com.example.mytextdraw.View.ColorChangeTextView
            android:id="@+id/id_tab_03"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            app:text="推荐"
            app:text_color="#ff000000"
            app:text_color_change="#ffff0000"
            app:text_size="18sp" />

        <com.example.mytextdraw.View.ColorChangeTextView
            android:id="@+id/id_tab_04"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            app:text="上海"
            app:text_color="#ff000000"
            app:text_color_change="#ffff0000"
            app:text_size="18sp" />
    </LinearLayout>

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

</LinearLayout>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值