自定义View通过PorterDuffXfermode实现图片遮罩效果

来源:互联网 发布:apache 进程 编辑:程序博客网 时间:2024/04/28 06:23

要实现如下效果


想用android自带的控件来实现这效果非常困难,所以就自定义了一个View来实现

MyView.java的代码如下:

public class MyView extends View{// 屏幕每次刷新,progressBar应减去的长度private int progress = 0;Bitmap background;Bitmap mask;public MyView(Context context) {        super(context);    }    public MyView(Context context, AttributeSet attrs) {        this(context, attrs, 0);        setWillNotDraw(false);        initBitmap();    }    public MyView(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);    }    private void initBitmap(){    //背景部分,也就是上面的图形  background = BitmapFactory.decodeResource(getResources(),                  R.drawable.icon_rank_none);          //遮罩,就是提取来部分          mask = BitmapFactory.decodeResource(getResources(),                  R.drawable.icon_rank);     }@Overrideprotected void onDraw(Canvas canvas) {                   canvas.drawColor(Color.WHITE);          canvas.drawBitmap(background, 0, 0, null);          Paint paint = new Paint();          paint.setFilterBitmap(false);            int x = 0;          int y = 0;            int sc = canvas.saveLayer(x, y, x + background.getWidth(), y + background.getHeight(), null,                  Canvas.MATRIX_SAVE_FLAG | Canvas.CLIP_SAVE_FLAG                          | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG                          | Canvas.FULL_COLOR_LAYER_SAVE_FLAG                          | Canvas.CLIP_TO_LAYER_SAVE_FLAG);          canvas.drawRect(0, background                  .getHeight() * (100-progress)/100, background.getWidth(), background                  .getHeight() , paint);          paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));          canvas.drawBitmap(mask, 0f, 0f, paint);          paint.setXfermode(null);          canvas.restoreToCount(sc);}public void setProgress(int progress){this.progress = progress >= 100 ? 100 : progress;invalidate();}}

main.xml代码如下:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:orientation="vertical"     android:background="#ffffff">    <com.example.demo.widget.MyView android:id="@+id/progressView"        android:layout_width="wrap_content"        android:layout_height="wrap_content"/></LinearLayout>

MainActivity.java代码如下:

public class MainActivity extends Activity {@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);MyView view = (MyView) findViewById(R.id.progressView);view.setProgress(80);//这个值可以自己定义(1-100)}}

就以上代码足以实现了,就在这样一个简单的demo中是实现了,但是我需要在一个ScrollView里嵌套实现这个,最开始把这代码挪过去就想直接用,挪过去了,但是发现不显示呀,onDraw()根本都没有调用,后来在网上查了些资料,最后发现只要在MyView里实现如下方法即可解决。


所以完整的MyView.java代码是:

public class MyView extends View{// 屏幕每次刷新,progressBar应减去的长度private int progress = 0;Bitmap background;Bitmap mask;public MyView(Context context) {        super(context);    }    public MyView(Context context, AttributeSet attrs) {        this(context, attrs, 0);        setWillNotDraw(false);        initBitmap();    }    public MyView(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);    }    private void initBitmap(){    //背景部分,也就是上面的图形  background = BitmapFactory.decodeResource(getResources(),                  R.drawable.icon_rank_none);          //遮罩,就是提取来部分          mask = BitmapFactory.decodeResource(getResources(),                  R.drawable.icon_rank);     }@Overrideprotected void onDraw(Canvas canvas) {                   canvas.drawColor(Color.WHITE);          canvas.drawBitmap(background, 0, 0, null);          Paint paint = new Paint();          paint.setFilterBitmap(false);            int x = 0;          int y = 0;            int sc = canvas.saveLayer(x, y, x + background.getWidth(), y + background.getHeight(), null,                  Canvas.MATRIX_SAVE_FLAG | Canvas.CLIP_SAVE_FLAG                          | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG                          | Canvas.FULL_COLOR_LAYER_SAVE_FLAG                          | Canvas.CLIP_TO_LAYER_SAVE_FLAG);          canvas.drawRect(0, background                  .getHeight() * (100-progress)/100, background.getWidth(), background                  .getHeight() , paint);          paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));          canvas.drawBitmap(mask, 0f, 0f, paint);          paint.setXfermode(null);          canvas.restoreToCount(sc);}public void setProgress(int progress){this.progress = progress >= 100 ? 100 : progress;invalidate();}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {// TODO Auto-generated method stubsetMeasuredDimension(background.getWidth(), background.getHeight());}}

MyView里需要两图片

icon_rank.png为蓝色的人 

icon_rank_none.png为灰色的人


根据自己的需求也可以再上面继续优化


0 0
原创粉丝点击