公司有一个这样的需求:
需求描述如下:长按右面的接受按钮,左侧的进度向右增加,进度条覆盖的地方跟没覆盖前的颜色是不一样的,比如进度条覆盖前的文字是黑色,覆盖后的文字是白色。释放按钮进度条会回滚。
一开始想用属性动画来解决,不料没成功,我是用属性动画做不出来,有高手希望指点一下。
我这里是用自定义view来实现,主要思路如下:
1:在draw方法画两份除了颜色都一样的视图,一份是覆盖进度条的,一份是没覆盖进度条的
2:根据进度条的位置,通过切割画布来决定画布的哪一部分显示有进度条的视图,另一部分显示没有进度条的部分。
这边没有美工,实现简单的效果如下:
看懂思路后具体的代码很简单(有兴趣的可以在上面的基础改一下,文子间距,背景什么的弄好看点):
package com.example.chttest;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.graphics.Paint.FontMetrics;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
/**
* @author haitao
*/
public class MyProgressBoard extends View {
private Thread thread;
private Context mContext;
private Paint mPaint;
private Paint mTextPaint;
private Paint mCiclePaint;
private Path path;
private int progress = 10;//進度
private boolean isOver=false;
private Bitmap bitmap;
private volatile boolean isDown = false; //是否按下右边按钮
private int imageWidth; //图片的宽度
private int imageHeight; //图片的高度
private int leftPadding = 20;
private int textTopPadding = 30;
private String titleStr = "免费卷";
private String sencondStr = "免费得到超级乐视电视价值$3888元";
private String thirdStr = "有效期:2016.1.2-2016.2.5";
private String buttonStr = "按下";
private int radio = 60;//圆的半径
public MyProgressBoard(Context context) {
super(context);
}
public MyProgressBoard(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public MyProgressBoard(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
setBackgroundColor(Color.WHITE);
mPaint = new Paint();
mPaint.setColor(Color.GREEN);
mPaint.setStyle(Style.STROKE);
mPaint.setStrokeWidth(10);
path = new Path();
mTextPaint = new Paint();
mTextPaint.setTextSize(20);
mTextPaint.setColor(Color.BLACK);
mTextPaint.setStyle(Style.FILL);
mCiclePaint = new Paint();
mCiclePaint.setColor(Color.RED);
mCiclePaint.setTextSize(20);
mCiclePaint.setStyle(Style.STROKE);
if(thread==null){
thread = new Thread(runbale);
thread.start();
}
}
private Runnable runbale = new Runnable() {
@Override
public void run() {
while(true){
if(isDown && progress<=getWidth()){
progress++;
try {
Thread.sleep(4);
postInvalidate();
if(progress>getWidth()){
isDown = false;
break;//退出while循环
}
} catch (Exception e) {
e.printStackTrace();
}
}else{
if(progress>0){
progress--;
}
try {
Thread.sleep(2);
postInvalidate();
if(progress==0){
continue;//不退出while循环
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
};
private Runnable mLongClick = new Runnable() {
@Override
public void run() {
isDown = true;
}
};
@Override
protected void onDraw(final Canvas cv) {
super.onDraw(cv);
/** 红色区域**/
Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Bitmap bitmapmap = toGrayscale(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher));
imageWidth = bitmapmap.getWidth();
imageHeight = bitmapmap.getHeight();
canvas.drawRGB(255, 0, 0);
canvas.drawBitmap(bitmapmap, DensityUtil.dip2px(mContext, leftPadding), getHeight()/2-imageHeight/2, mTextPaint);
mTextPaint.setColor(Color.WHITE);
canvas.drawText(titleStr, imageWidth+DensityUtil.dip2px(mContext, leftPadding*3/2), DensityUtil.dip2px(mContext, textTopPadding), mTextPaint);
canvas.drawText(sencondStr, imageWidth+DensityUtil.dip2px(mContext, leftPadding*3/2), DensityUtil.dip2px(mContext, 2*textTopPadding), mTextPaint);
canvas.drawText(thirdStr, imageWidth+DensityUtil.dip2px(mContext, leftPadding*3/2), DensityUtil.dip2px(mContext, 3*textTopPadding), mTextPaint);
mCiclePaint.setColor(Color.WHITE);
float textWidth = mCiclePaint.measureText(buttonStr); //测量字体宽度,我们需要根据字体的宽度设置在圆环中间
canvas.drawCircle(getWidth()-radio, getHeight()/2, radio, mCiclePaint);
canvas.drawText(buttonStr, getWidth()-radio - textWidth / 2, getHeight()/2 + 20/2, mCiclePaint); //画出进度百分比
cv.save();
cv.clipRect(0, 0, progress,getHeight());
cv.drawBitmap(bitmap, getLeft(), getTop(), mPaint);
cv.restore();
/** 白色区域**/
Bitmap bitmap1 = Bitmap.createBitmap(getWidth(), getHeight(), Config.ARGB_8888);
Bitmap bitmapmap1 = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
Canvas canvas1 = new Canvas(bitmap1);
// canvas1.translate(getWidth() / 2, getHeight() / 2);
mPaint.setColor(Color.GREEN);
mTextPaint.setColor(Color.BLACK);
canvas1.drawBitmap(bitmapmap1, DensityUtil.dip2px(mContext, leftPadding), getHeight()/2-imageHeight/2, mTextPaint);
canvas1.drawText(titleStr, imageWidth+DensityUtil.dip2px(mContext, leftPadding*3/2), DensityUtil.dip2px(mContext, textTopPadding), mTextPaint);
canvas1.drawText(sencondStr, imageWidth+DensityUtil.dip2px(mContext, leftPadding*3/2), DensityUtil.dip2px(mContext, 2*textTopPadding), mTextPaint);
canvas1.drawText(thirdStr, imageWidth+DensityUtil.dip2px(mContext, leftPadding*3/2), DensityUtil.dip2px(mContext, 3*textTopPadding), mTextPaint);
mCiclePaint.setColor(Color.BLACK);
canvas1.drawCircle(getWidth()-radio, getHeight()/2, radio, mCiclePaint);
canvas1.drawText(buttonStr, getWidth()-radio - textWidth / 2, getHeight()/2 + 20/2, mCiclePaint); //画出进度百分比
cv.save();
cv.clipRect(progress, 0, getWidth(), getHeight());
cv.drawBitmap(bitmap1, getLeft(), getTop(), mPaint);
cv.restore();
}
/***//**
* 图片去色,返回灰度图片
* @param bmpOriginal 传入的图片
* @return 去色后的图片
*/
public static Bitmap toGrayscale(Bitmap bmpOriginal) {
int width, height;
height = bmpOriginal.getHeight();
width = bmpOriginal.getWidth();
Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
Canvas c = new Canvas(bmpGrayscale);
Paint paint = new Paint();
ColorMatrix cm = new ColorMatrix();
cm.setSaturation(0);
ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
paint.setColorFilter(f);
c.drawBitmap(bmpOriginal, 0, 0, paint);
return bmpGrayscale;
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
int x = 0;
int y = 0;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
x = (int)event.getX();
y = (int)event.getY();
if(x<getWidth() && x>getWidth()-radio*2
&& y>getHeight()/2-radio && y<getHeight()/2+radio){
// isDown = true;
postDelayed(mLongClick, 500);
return true;
}
break;
case MotionEvent.ACTION_MOVE:
if (Math.abs(event.getX()- x) > 350
|| Math.abs(event.getY() - y) > 350) {
// 移动超过阈值,则表示移动了
// isDown = false;
// removeCallbacks(mLongClick);
}
break;
case MotionEvent.ACTION_UP:
isDown = false;
removeCallbacks(mLongClick);
break;
default:
break;
}
return super.dispatchTouchEvent(event);
}
}