viewpager文字渐变指示器
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;
@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;
}
@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) {
case DIRECTION_LEFT:
mPaint.setColor(mTextColorChange);
canvas.save();
Rect rect = new Rect((int) mTextStartX, 0,
(int) (mTextStartX + mProgress * mTextWidth), getMeasuredHeight());
canvas.clipRect(rect);
canvas.drawRect(canvas.getClipBounds(),mLinePaint);
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);
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) {
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();
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() {
@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() {
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
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>