Android 菜单箭头切换控件

在android 的材料设计上有一种菜单按钮和箭头之间互相切换的效果十分吸引人。

前两天看到一个应用使用了这个效果特地把这个控件拿出来学习一下

  1 package com.example.drawablearrow;
  2 
  3 
  4 import android.content.Context;
  5 import android.graphics.Canvas;
  6 import android.graphics.ColorFilter;
  7 import android.graphics.Paint;
  8 import android.graphics.Path;
  9 import android.graphics.PixelFormat;
 10 import android.graphics.Rect;
 11 import android.graphics.drawable.Drawable;
 12 
 13 
 14 //这个类就是用来实现 菜单编程箭头效果的类
 15 public abstract class DrawerArrowDrawable extends Drawable {
 16     private static final float ARROW_HEAD_ANGLE = (float) Math.toRadians(45.0D); //箭头的角度
 17     protected float mBarGap;  //菜单 按钮两条线之间的间隔
 18     protected float mBarSize; //菜单 按钮线的长度
 19     protected float mBarThickness; //菜单按钮 线的宽度
 20     protected float mMiddleArrowSize; //箭头按钮 中间那条线的长度
 21     protected final Paint mPaint = new Paint();
 22     protected final Path mPath = new Path();
 23     protected float mProgress;
 24     protected int mSize;
 25     protected float mVerticalMirror = 1f;
 26     protected float mTopBottomArrowSize;//箭头 按钮的上下部分的长度
 27     protected Context context;
 28 
 29     public DrawerArrowDrawable(Context context) {
 30         this.context = context;
 31         this.mPaint.setAntiAlias(true);//设置抗锯齿
 32         this.mPaint.setColor(context.getResources().getColor(R.color.ldrawer_color)); //设置画笔的颜色为白色
 33         this.mSize = context.getResources().getDimensionPixelSize(R.dimen.ldrawer_drawableSize);
 34         this.mBarSize = context.getResources().getDimensionPixelSize(R.dimen.ldrawer_barSize);
 35         this.mTopBottomArrowSize = context.getResources().getDimensionPixelSize(R.dimen.ldrawer_topBottomBarArrowSize);
 36         this.mBarThickness = context.getResources().getDimensionPixelSize(R.dimen.ldrawer_thickness);
 37         this.mBarGap = context.getResources().getDimensionPixelSize(R.dimen.ldrawer_gapBetweenBars);
 38         this.mMiddleArrowSize = context.getResources().getDimensionPixelSize(R.dimen.ldrawer_middleBarArrowSize);
 39         this.mPaint.setStyle(Paint.Style.STROKE);
 40         //设置两条线相交时候 相交部分的处理
 41         this.mPaint.setStrokeJoin(Paint.Join.ROUND);
 42         this.mPaint.setStrokeCap(Paint.Cap.SQUARE);
 43         //设置画笔线的宽度
 44         this.mPaint.setStrokeWidth(this.mBarThickness);
 45     }
 46     //此方法是用来进行动画转换的时候差值的 第三个参数是进度
 47     protected float lerp(float paramFloat1, float paramFloat2, float paramFloat3) {
 48         return paramFloat1 + paramFloat3 * (paramFloat2 - paramFloat1);
 49     }
 50 
 51     public void draw(Canvas canvas) {
 52         Rect localRect = getBounds();
 53         float f1 = lerp(this.mBarSize, this.mTopBottomArrowSize, this.mProgress);
 54         float f2 = lerp(this.mBarSize, this.mMiddleArrowSize, this.mProgress);
 55         float f3 = lerp(0.0F, this.mBarThickness / 2.0F, this.mProgress);
 56         float f4 = lerp(0.0F, ARROW_HEAD_ANGLE, this.mProgress);
 57         float f5 = 0.0F;
 58         float f6 = 180.0F;
 59         float f7 = lerp(f5, f6, this.mProgress);
 60         float f8 = lerp(this.mBarGap + this.mBarThickness, 0.0F, this.mProgress);
 61         this.mPath.rewind();
 62         float f9 = -f2 / 2.0F;
 63         this.mPath.moveTo(f9 + f3, 0.0F);
 64         this.mPath.rLineTo(f2 - f3, 0.0F);
 65         float f10 = (float) Math.round(f1 * Math.cos(f4));
 66         float f11 = (float) Math.round(f1 * Math.sin(f4));
 67         this.mPath.moveTo(f9, f8);
 68         this.mPath.rLineTo(f10, f11);
 69         this.mPath.moveTo(f9, -f8);
 70         this.mPath.rLineTo(f10, -f11);
 71         this.mPath.moveTo(0.0F, 0.0F);
 72         this.mPath.close();
 73         canvas.save();
 74         if (!isLayoutRtl())
 75             canvas.rotate(180.0F, localRect.centerX(), localRect.centerY());
 76         canvas.rotate(f7 * mVerticalMirror, localRect.centerX(), localRect.centerY());
 77         canvas.translate(localRect.centerX(), localRect.centerY());
 78         canvas.drawPath(this.mPath, this.mPaint);
 79         canvas.restore();
 80     }
 81 
 82     public int getIntrinsicHeight() {
 83         return this.mSize;
 84     }
 85 
 86     public int getIntrinsicWidth() {
 87         return this.mSize;
 88     }
 89 
 90     public void setAlpha(int alpha) {
 91         this.mPaint.setAlpha(alpha);
 92     }
 93 
 94     @Override
 95     public int getOpacity() {
 96         return PixelFormat.TRANSLUCENT;
 97     }
 98 
 99     public abstract boolean isLayoutRtl();
100 
101     public void setColorFilter(ColorFilter colorFilter) {
102         this.mPaint.setColorFilter(colorFilter);
103     }
104 
105     public void setVerticalMirror(boolean mVerticalMirror) {
106         this.mVerticalMirror = mVerticalMirror ? 1 : -1;
107     }
108 
109     public void setProgress(float paramFloat) {
110         this.mProgress = paramFloat;
111         invalidateSelf();
112     }
113 
114     public void setColor(int resourceId) {
115         this.mPaint.setColor(context.getResources().getColor(resourceId));
116     }
117 }

使用这个类主要是调用他的两个方法 setProgress 和setverticalMirror 第一个方法是用来设置进度的 通过不断的修改进度来实现动画效果。第二个方法使用来设置旋转方向的。

 

posted @ 2015-03-20 11:42  jiashu.ge  阅读(2331)  评论(0编辑  收藏  举报