效果:
最核心的代码是: canvas.clipRect(startX, 0, endX, getMeasuredHeight());
实际上绘画了2种颜色,然后根据progress来剪切,形成这样的效果。
自定义属性和获取
attr.xml
<resources>
<attr name="text" format="string"></attr>
<attr name="text_size" format="dimension"></attr>
<attr name="text_origin_color" format="color|reference"></attr>
<attr name="text_change_color" format="color|reference"></attr>
<attr name="progress" format="float"></attr>
<attr name="direction">
<enum name="left" value="0"></enum>
<enum name="right" value="1"></enum>
</attr>
<declare-styleable name="ColorTrackView">
<attr name="text"></attr>
<attr name="text_size"></attr>
<attr name="text_origin_color"></attr>
<attr name="text_change_color"></attr>
<attr name="progress"></attr>
<attr name="direction"></attr>
</declare-styleable>
</resources>
自定义View : ColorTrackView.java
package com.example.day0203;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
public class ColorTrackView extends View{
private int mTextStartX = 0;
private Paint mPaint = new Paint();
private String mText;
private int mTextSize = 30;
private int mTextOriginColor = 0xff000000;
private int mTextChangeColor = 0xffff0000;
private Rect mTextBound = new Rect();
private int mTextWidth = 0;
public float mProgress = 0;
public enum Direction
{
LEFT , RIGHT ;
}
private int mDirection = DIRECTION_LEFT;
private static final int DIRECTION_LEFT = 0 ;
private static final int DIRECTION_RIGHT= 1 ;
public ColorTrackView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ColorTrackView);
mText = ta.getString(R.styleable.ColorTrackView_text);
mTextSize = ta.getDimensionPixelSize(R.styleable.ColorTrackView_text_size, mTextSize);
mTextOriginColor = ta.getColor(R.styleable.ColorTrackView_text_origin_color, mTextOriginColor);
mTextChangeColor = ta.getColor(R.styleable.ColorTrackView_text_change_color, mTextChangeColor);
mProgress = ta.getFloat(R.styleable.ColorTrackView_progress, mProgress);
mDirection = ta.getInt(R.styleable.ColorTrackView_direction, mDirection);
ta.recycle();
mPaint.setTextSize(mTextSize);
mPaint.setAntiAlias(true);
measureText();
}
private void measureText()
{
mTextWidth = (int) mPaint.measureText(mText);
mPaint.getTextBounds(mText, 0, mText.length(), mTextBound);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int r = (int) (mProgress * mTextWidth +mTextStartX ); //没用到, 本意是拿来封装的
if(mDirection == DIRECTION_LEFT)
{
drawChangeLeft(canvas, r);
drawOriginLeft(canvas, r);
}else
{
drawOriginRight(canvas, r);
drawChangeRight(canvas, r);
}
}
private void drawChangeRight(Canvas canvas, int r)
{
drawText(canvas, mTextChangeColor, (int) (mTextStartX +(1-mProgress)*mTextWidth), mTextStartX+mTextWidth );
}
private void drawOriginRight(Canvas canvas, int r)
{
drawText(canvas, mTextOriginColor, mTextStartX, (int) (mTextStartX +(1-mProgress)*mTextWidth) );
}
private void drawChangeLeft(Canvas canvas, int r)
{
drawText(canvas, mTextChangeColor, mTextStartX, (int) (mTextStartX + mProgress * mTextWidth) );
}
private void drawOriginLeft(Canvas canvas, int r)
{
drawText(canvas, mTextOriginColor, (int) (mTextStartX + mProgress * mTextWidth), mTextStartX +mTextWidth );
}
private void drawText(Canvas canvas , int color , int startX , int endX)
{
mPaint.setColor(color);
canvas.save(Canvas.CLIP_SAVE_FLAG);
canvas.clipRect(startX, 0, endX, getMeasuredHeight());
canvas.drawText(mText, mTextStartX, getMeasuredHeight() / 2
+ mTextBound.height() / 2, mPaint);
canvas.restore();
}
public int getDirection() {
return mDirection;
}
public void setDirection(int mDirection) {
this.mDirection = mDirection;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = measureWidth(widthMeasureSpec);//得到View的宽
int height = measureHight(heightMeasureSpec);//得到View的高
setMeasuredDimension(width,height);
}
public float getMProgress() {
return mProgress;
}
public void setMProgress(float mProgress) {
this.mProgress = mProgress;
invalidate();
}
private int measureWidth(int widthMeasureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(widthMeasureSpec);
int specSize = MeasureSpec.getSize(widthMeasureSpec);
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
} else {
result = 200;
if (specMode == MeasureSpec.AT_MOST) {
result = Math.min(result, specSize);
}
}
return result;
}
private int measureHight(int heightMeasureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(heightMeasureSpec);
int specSize = MeasureSpec.getSize(heightMeasureSpec);
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
} else {
result = 200;
if (specMode == MeasureSpec.AT_MOST) {
result = Math.min(result, specSize);
}
}
return result;
}
}
xml使用
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.day0203.MainActivity"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app1="http://schemas.android.com/apk/res/com.example.day0203">
<com.example.day0203.ColorTrackView
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/tv"
android:layout_marginBottom="40dp"
app1:text="BOB_海贼王"
/>
<LinearLayout
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/tv">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/bt_left"
android:text="left"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/bt_right"
android:text="right"/>
</LinearLayout>
</RelativeLayout>
MainActivity.java
...
final ColorTrackView mView = (ColorTrackView) findViewById(R.id.tv);
Button bt1 = (Button) findViewById(R.id.bt_left);
bt1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mView.setDirection(0);
ObjectAnimator.ofFloat(mView, "mProgress", 0, 1).setDuration(2000).start();
}
});
Button bt2 = (Button) findViewById(R.id.bt_right);
bt2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mView.setDirection(1);
ObjectAnimator.ofFloat(mView, "mProgress", 0, 1).setDuration(2000).start();
}
});
...
注意事项:
1.canvas.drawText(text,x,y,paint); //这里x,y的点是Text的左下角的位置(T)
2.ObjectAnimator.ofFloat(mView, “mProgress”, 0, 1).setDuration(2000).start(); //Obeject mView 必须包含mProgress的get,set方法,并且方法的名字要是getMProgress(),和setMProgress(),即参数的的第一个字母得大写!(之前写成setmProgress()无效)。并且若是ofFloat,mProgress必须是float类型
和ViewPager搭配使用(今日头条效果)
效果:
xml
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/com.example.day0203">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:orientation="horizontal">
<com.example.day0203.ColorTrackView
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="@+id/ctv_tab_1"
app:text="首页"/>
<com.example.day0203.ColorTrackView
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="@+id/ctv_tab_2"
app:text="内容"/>
<com.example.day0203.ColorTrackView
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="@+id/ctv_tab_3"
app:text="设置"/>
</LinearLayout>
<android.support.v4.view.ViewPager
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/vp"
></android.support.v4.view.ViewPager>
</LinearLayout>
MainActivity
package com.example.day0203;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.Log;
public class MainActivity extends FragmentActivity {
private ViewPager mViewPager;
private List<ColorTrackView> mTabs = new ArrayList<ColorTrackView>();
private String[] mTitles = new String[] { "简介", "评价", "相关" };
private TabFragment[] mFragments = new TabFragment[mTitles.length];
private FragmentPagerAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
initDatas();
initEvents();
}
private void initEvents() {
mViewPager.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int arg0) {
// TODO Auto-generated method stub
}
@Override
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels)
{
if (positionOffset > 0)
{
ColorTrackView left = mTabs.get(position);
ColorTrackView right = mTabs.get(position + 1);
left.setDirection(1);
right.setDirection(0);
left.setMProgress( 1-positionOffset);
right.setMProgress(positionOffset);
}
}
@Override
public void onPageScrollStateChanged(int arg0) {
// TODO Auto-generated method stub
}
});
}
private void initDatas() {
for (int i = 0; i < mTitles.length; i++)
{
mFragments[i] = (TabFragment) TabFragment.newInstance(mTitles[i]);
}
mAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) {
@Override
public int getCount() {
// TODO Auto-generated method stub
return mFragments.length;
}
@Override
public Fragment getItem(int arg0) {
// TODO Auto-generated method stub
return mFragments[arg0];
}
};
mViewPager.setAdapter(mAdapter);
mViewPager.setCurrentItem(0);
}
private void initViews() {
mViewPager = (ViewPager) findViewById(R.id.vp);
mTabs.add((ColorTrackView) findViewById(R.id.ctv_tab_1));
mTabs.add((ColorTrackView) findViewById(R.id.ctv_tab_2));
mTabs.add((ColorTrackView) findViewById(R.id.ctv_tab_3));
}
}
TabFragment
package com.example.day0203;
import java.util.Random;
import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class TabFragment extends Fragment{
public static final String TITLE = "title";
private String mTitle = "Defaut Value";
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mTitle = getArguments().getString(TITLE);
}
}
@Override
@Nullable
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
TextView tv = new TextView(getActivity());
tv.setTextSize(60);
Random r = new Random();
tv.setBackgroundColor(Color.argb(r.nextInt(120), r.nextInt(255),
r.nextInt(255), r.nextInt(255)));
tv.setText(mTitle);
tv.setGravity(Gravity.CENTER);
return tv;
}
public static TabFragment newInstance(String title)
{
TabFragment tabFragment = new TabFragment();
Bundle bundle = new Bundle();
bundle.putString(TITLE, title);
tabFragment.setArguments(bundle);
return tabFragment;
}
}
转载于:http://blog.csdn.net/lmj623565791/article/details/44098729