亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > Android > 正文

Android實現遮罩層(蒙板)效果

2019-10-21 21:36:49
字體:
來源:轉載
供稿:網友

Android的遮罩效果就是把一張圖片蓋在另一張圖片的上面,通過控制任意一張圖片的顯示百分比實現遮罩效果。下面我使用兩張一樣的圖片來實現一個類似于 Android 的progressbar 的填充效果。使用遮罩效果來實現progressbar的效果的好處是,我們可以只改變圖片就可以更改progress的進度填充效果,并且我們可以實現任意形式的填充效果,就比如橫豎填充,扇形逆/順時填充針等。

網上有很多介紹Android 遮罩效果的列子,但是都是橫豎的填充效果,下面我來實現一個扇形填充效果,如下圖:

Android,遮罩層,蒙板

我現在要做的就是用這兩種圖去實現一個progressbar效果.好了原來不解釋了直接上代碼吧:

一.Activity代碼

package com.gplus.mask.test; import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.util.Log;import android.view.ViewGroup.LayoutParams;import android.widget.LinearLayout;import android.widget.RelativeLayout; import com.gplus.mask.widget.MaskProgress;import com.gplus.mask.widget.MaskProgress.AnimateListener;  public class GplusMask extends Activity{  float progressFromCode = 150; float progressFromXml = 150;  MaskProgress maskProgressFromeCode; MaskProgress maskProgressFromeXml;  private boolean isAnimateFinish = true;  @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main);  RelativeLayout parent = (RelativeLayout) findViewById(R.id.parent); maskProgressFromeCode = new MaskProgress(this); initialProgress(maskProgressFromeCode); RelativeLayout.LayoutParams rp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,   RelativeLayout.LayoutParams.MATCH_PARENT); parent.addView(maskProgressFromeCode, rp); maskProgressFromeCode.initial();  maskProgressFromeXml = (MaskProgress) findViewById(R.id.maskView);  }  private void initialProgress(MaskProgress maskProgress){ //設置最大值 maskProgress.setMax(300); //初始填充量為一半 //初始化填充progress時的填充動畫時間,越大越慢 maskProgress.setTotaltime(3); //progress背景圖 maskProgress.setBackgroundResId(R.drawable.untitled1); //progress填充內容圖片 maskProgress.setContentResId(R.drawable.untitled2); //Progress開始的填充的位置360和0為圓最右、90圓最下、180為圓最右、270為圓最上(順時針方向為正) maskProgress.setStartAngle(0); maskProgress.setAnimateListener(animateListener); //初始化時必須在setMax設置之后再設置setProgress maskProgress.setProgress(175); }  Handler handler = new Handler(){  @Override public void handleMessage(Message msg) {  super.handleMessage(msg);   float newProgress = maskProgressFromeCode.getProgress() - 4;  if(newProgress <= 0){//隨機繪制效果    float max = (float) (Math.random() * 900 + 1000);  float progress = (float) (max * Math.random());    maskProgressFromeCode.setMax(max);  maskProgressFromeCode.setProgress(progress);  maskProgressFromeCode.setTotaltime((float) (Math.random()*10));  maskProgressFromeCode.setStartAngle((float) (Math.random()*360));  maskProgressFromeCode.initial();  return;  }  maskProgressFromeCode.setProgress(newProgress);  maskProgressFromeCode.updateProgress();    handler.sendEmptyMessageDelayed(0, 50); } };  AnimateListener animateListener = new AnimateListener() {  @Override public void onAnimateFinish() {  handler.sendEmptyMessageDelayed(0, 500); } };}

二.activity布局文件main.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  xmlns:app="http://schemas.android.com/apk/res/com.gplus.mask.test"  android:layout_width="fill_parent"  android:layout_height="fill_parent"  android:orientation="vertical" >   <RelativeLayout    android:layout_width="match_parent"    android:layout_height="0dp"    android:layout_weight="1"    android:orientation="vertical" >     <com.gplus.mask.widget.MaskProgress      android:id="@+id/maskView"      android:layout_width="200dp"      android:layout_height="200dp"      app:anim_time="20"      app:max="180"      app:progress="135"      app:progress_background="@drawable/untitled1"      app:progress_content="@drawable/untitled2"      app:start_angle="0"       android:layout_centerInParent="true"/>  </RelativeLayout>   <RelativeLayout    android:id="@+id/parent"    android:layout_width="match_parent"    android:layout_height="0dp"    android:layout_weight="1"    android:orientation="vertical" /> </LinearLayout>

三.View的實現效果MaskProgress.java

package com.gplus.mask.widget;    import android.content.Context;import android.content.res.TypedArray;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Matrix;import android.graphics.Paint;import android.graphics.PorterDuffXfermode;import android.graphics.PorterDuff.Mode;import android.graphics.RectF;import android.util.AttributeSet;import android.util.Log;import android.view.Gravity;import android.view.View; /** * @author huangxin */public class MaskProgress extends View{   /** 每次setProgress時進度條前進或者回退到所設的值時都會有一段動畫。 * 該接口用于監聽動畫的完成,你應該設置監聽器監聽到動畫完成后,才再一次調用  * setProgress方法 * */ public static interface AnimateListener{ public void onAnimateFinish(); }  private float totalTime = 5;//s   private final static int REFRESH = 10;//mills  private float step;  private float max = 360;   private float currentProgress;  private float destProgress = 0; private float realProgress = 0; private float oldRealProgress = 0; private int backgroundResId; private int contentResId;  private float startAngle = 270;  private Bitmap bg; private Bitmap ct;  private Paint paint;  private int radius;  private int beginX; private int beginY;  private int centerX; private int centerY;  private RectF rectF;  private PorterDuffXfermode srcIn;  private double rate;  boolean initialing = false;  AnimateListener animateListener;  public MaskProgress(Context context) { this(context, null); }  public MaskProgress(Context context, AttributeSet attrs) { this(context, attrs, R.attr.maskProgressStyle); }  public MaskProgress(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context, attrs, defStyle); }   public void setAnimateListener(AnimateListener animateListener) { this.animateListener = animateListener; }  public void setProgress(float destProgress) { if(destProgress > max)  try {  throw new Exception("progress can biger than max");  } catch (Exception e) {  e.printStackTrace();  }  this.destProgress = destProgress; oldRealProgress = realProgress; realProgress = (float) (destProgress * rate); }  public float getProgress(){ return destProgress; }  public void setTotaltime(float totalTime) { this.totalTime = totalTime; step = 360 / (totalTime * 1000 / REFRESH); }  public static int getRefresh() { return REFRESH; }  public void setMax(float max) { this.max = max; rate = 360 / max; }  public void setStartAngle(float startAngle) { this.startAngle = startAngle; }   public void setBackgroundResId(int backgroundResId) { this.backgroundResId = backgroundResId; bg = BitmapFactory.decodeResource(getResources(), backgroundResId); }  public void setContentResId(int contentResId) { this.contentResId = contentResId; ct = BitmapFactory.decodeResource(getResources(), contentResId); }  public void updateProgress(){ invalidate(); }  /** 初始化,第一次給MaskProgress設值時,從沒有填充到,填充到給定的值時 * 有一段動畫 * */ public void initial(){ initialing = true; new CirculateUpdateThread().start(); }  public float getMax() { return max; }  private void init(Context context, AttributeSet attrs, int defStyle){  TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.maskProgressBar, defStyle, 0);  if (typedArray != null) {      try {        setMax(typedArray.getFloat(R.styleable.maskProgressBar_max, max));        setProgress(typedArray.getFloat(R.styleable.maskProgressBar_progress, destProgress));        setTotaltime(typedArray.getFloat(R.styleable.maskProgressBar_anim_time, totalTime));        setStartAngle(typedArray.getFloat(R.styleable.maskProgressBar_start_angle, startAngle));        setContentResId(typedArray.getResourceId(R.styleable.maskProgressBar_progress_content, R.drawable.untitled2));        setBackgroundResId(typedArray.getResourceId(R.styleable.maskProgressBar_progress_background, R.drawable.untitled1));      } finally {       typedArray.recycle();      }      }   paint = new Paint(); paint.setDither(true); paint.setAntiAlias(true);  rate = 360 / max; currentProgress = 0; realProgress = (float) (destProgress * rate); srcIn = new PorterDuffXfermode(Mode.SRC_IN); step = 360 / (totalTime * 1000 / REFRESH);  bg = BitmapFactory.decodeResource(getResources(), backgroundResId); ct = BitmapFactory.decodeResource(getResources(), contentResId);  Log.w("init", "max: " + max + "/n" + "destProgress: " + destProgress +"/n"+"totalTime: "+ totalTime+"/n"+"startAngle: "+ startAngle);  initialing = true; new CirculateUpdateThread().start(); }  @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas);  canvas.drawBitmap(bg, 0, (getHeight() - bg.getHeight()) / 2, paint); int rc = canvas.saveLayer(0, (getHeight() - bg.getHeight()) / 2, bg.getWidth(), (getHeight() + bg.getHeight()) / 2, null, Canvas.ALL_SAVE_FLAG);  paint.setFilterBitmap(false); if(initialing){  canvas.drawArc(rectF, startAngle, currentProgress, true, paint); }else{  canvas.drawArc(rectF, startAngle, realProgress, true, paint); } paint.setXfermode(srcIn); canvas.drawBitmap(ct, 0, (getHeight() - ct.getHeight()) / 2, paint);  paint.setXfermode(null); canvas.restoreToCount(rc); }  public int[] getRectPosition(int progress){ int[] rect = new int[4];   rect[0] = beginX; rect[1] = beginY; rect[2] = (int)(centerX + radius * Math.cos(progress * Math.PI /180)); rect[3] = (int)(centerY + radius * Math.sin(progress * Math.PI /180));  Log.w("getRectPosition", "30: " + Math.sin(30 * Math.PI /180));  Log.w("getRectPosition", "X: " + rect[2] + " " + "Y: " + rect[3]);  return rect; }  @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); setMeasuredDimension(widthMeasureSpec, heightMeasureSpec); }  @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh);  int tmp = w >= h ? h : w;  radius = tmp / 2; beginX = w / 2; beginY = 0; centerX = tmp / 2; centerY = tmp / 2;  Bitmap bg_ = resizeBitmap(bg, tmp, tmp); Bitmap ct_ = resizeBitmap(ct, tmp, tmp);  rectF = new RectF(0, (getHeight() - bg_.getHeight()) / 2, bg_.getWidth(), (getHeight() + bg_.getHeight()) / 2);  bg.recycle(); ct.recycle();  bg = bg_; ct = ct_; }  private Bitmap resizeBitmap(Bitmap src, int w, int h){  int width = src.getWidth(); int height = src.getHeight(); int scaleWidht = w / width; int scaleHeight = h / height;  Matrix matrix = new Matrix(); matrix.postScale(scaleWidht, scaleHeight);  Bitmap result = Bitmap.createScaledBitmap(src, w, h, true); src = null;  return result; }  class CirculateUpdateThread extends Thread{  @Override public void run() {  while(initialing){  postInvalidate();  if(currentProgress < realProgress){   currentProgress += step * rate;   if(currentProgress > realProgress)   currentProgress = realProgress;  }else{     // new Thread(new Runnable() {   //   // @Override   // public void run() {   // while (true) {   // postInvalidate();   // if (currentProgress > 0) {   // currentProgress -= step * rate;   // } else {   // currentProgress = 0;   // new CirculateUpdateThread().start();   // break;   // }   // try {   // Thread.sleep(REFRESH);   // } catch (Exception e) {   // e.printStackTrace();   // }   // }   // }   // }).start();   currentProgress = 0;   initialing = false;   if(animateListener != null)   animateListener.onAnimateFinish();  }  try{   Thread.sleep(REFRESH);  }catch(Exception e){   e.printStackTrace();  }  } }  } }

四.該Veiw自定義的屬性文件attrs.xml

<?xml version="1.0" encoding="utf-8"?><resources>   <declare-styleable name="maskProgressBar">    <attr name="max" format="float" />    <attr name="progress" format="float" />    <attr name="start_angle" format="float" />    <attr name="progress_background" format="reference" />    <attr name="progress_content" format="reference" />    <attr name="anim_time" format="float" />  </declare-styleable>     <attr name="maskProgressStyle" format="reference" />  </resources>

效果圖如下,上面小的是定義xml的,下面大的是從代碼中添加的

Android,遮罩層,蒙板

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产日韩欧美中文| 亚洲丝袜av一区| 欧美一区二区三区艳史| 精品久久久在线观看| 欧美日韩午夜剧场| 国色天香2019中文字幕在线观看| 精品国产区一区二区三区在线观看| 久久在精品线影院精品国产| 亚洲欧美三级在线| 精品国产一区二区三区久久狼黑人| 久久久久久久国产精品视频| 人人澡人人澡人人看欧美| 欧美在线观看网站| 国内精品久久久| 亚洲成人动漫在线播放| 久久久精品在线观看| 亚洲国产天堂久久国产91| 国产在线高清精品| 久久精品电影网站| 日产精品久久久一区二区福利| 欧美极品在线播放| 亚洲免费成人av电影| 欧美精品videosex极品1| 亚洲精品一区二三区不卡| 精品久久香蕉国产线看观看亚洲| 亚洲欧美综合区自拍另类| 亲爱的老师9免费观看全集电视剧| 91综合免费在线| 久热爱精品视频线路一| 欧美肥臀大乳一区二区免费视频| 日韩高清电影好看的电视剧电影| 日韩中文字幕av| 国产一区二区丝袜| 久久99久国产精品黄毛片入口| 美乳少妇欧美精品| 色综合久久久888| 国产精品视频久久久久| 国产精品高潮呻吟久久av黑人| 日韩av在线精品| 日本精品一区二区三区在线| 欧美成人免费一级人片100| 欧洲亚洲免费在线| 国产美女久久精品香蕉69| 亚洲一区二区精品| 国产精品高清免费在线观看| 久久在精品线影院精品国产| 欧美精品久久久久久久久| 国产视频综合在线| 一区二区三区四区在线观看视频| 日韩电影中文字幕av| 动漫精品一区二区| 国产精品爽爽ⅴa在线观看| 性视频1819p久久| 亚洲精品视频中文字幕| 日韩精品中文字幕在线播放| 国产精品久久视频| 欧美国产视频一区二区| 国产成人在线播放| 精品视频—区二区三区免费| 久久欧美在线电影| 欧美丰满少妇xxxxx| 成人福利网站在线观看11| 亚洲欧美在线一区| www.欧美三级电影.com| 亚洲精品之草原avav久久| 91在线观看免费| 中文欧美在线视频| 国产在线视频欧美| 黑人巨大精品欧美一区二区一视频| 国内精品国产三级国产在线专| 日韩精品小视频| 久久天天躁狠狠躁夜夜爽蜜月| 久久久久久久一区二区三区| 日韩精品极品在线观看播放免费视频| 成人网在线免费看| 国产精品久久久久久久久久久久| 不卡av在线播放| 国产欧美久久一区二区| 欧美日本亚洲视频| 26uuu国产精品视频| 欧美在线国产精品| 97久久精品国产| 亚洲va欧美va国产综合久久| 久久久成人精品视频| 这里只有精品视频| 久久久久久久久久久久av| 中文字幕日韩欧美精品在线观看| 国产成人短视频| 97在线视频国产| www国产亚洲精品久久网站| 久久久久久久影视| 亚洲黄色有码视频| 欧美在线一区二区三区四| 97视频在线观看免费高清完整版在线观看| 国产精品一区专区欧美日韩| 国产精品狼人色视频一区| 亚洲成年网站在线观看| 欧美日韩美女在线观看| 亚洲色图50p| 国产日产欧美a一级在线| 亚洲大胆人体av| 久久这里有精品视频| 色先锋久久影院av| 亚洲最大中文字幕| 欧美性在线观看| 一区二区欧美激情| 日韩免费在线免费观看| 国产精品久久久av久久久| 国产精品爱久久久久久久| 韩国欧美亚洲国产| 亚洲大胆人体av| 91香蕉国产在线观看| 91视频国产一区| 日本免费在线精品| 岛国av在线不卡| 成人精品在线视频| 国产狼人综合免费视频| 国产suv精品一区二区| 欧美午夜宅男影院在线观看| 亚洲欧美日本另类| 亚洲福利视频二区| 中文字幕亚洲国产| 伊人伊成久久人综合网站| 这里只有视频精品| 欧美日韩美女在线观看| 国产成人精品亚洲精品| 国产精品对白刺激| 日韩成人久久久| 日韩在线不卡视频| 亚洲精品中文字| 国产精品电影观看| 国产日韩欧美另类| 日本a级片电影一区二区| 久久免费视频观看| 日韩欧美亚洲成人| 亚洲电影av在线| 一区二区中文字幕| 欧美怡红院视频一区二区三区| 欧美一区二区.| 久久九九免费视频| 亚洲r级在线观看| 国产精品成人观看视频国产奇米| 精品视频在线播放色网色视频| 国模视频一区二区三区| 日韩电影在线观看中文字幕| 精品久久在线播放| 国产小视频91| 亚洲精品videossex少妇| 国产精品久久久久久影视| 久久精品电影网| 国内精品400部情侣激情| 日韩精品亚洲元码| 午夜精品在线观看| 色与欲影视天天看综合网| 中文字幕在线看视频国产欧美在线看完整| 日韩免费视频在线观看| 欧美激情一区二区三级高清视频| 国产日韩欧美在线播放| 自拍亚洲一区欧美另类| 欧美多人乱p欧美4p久久| 狠狠躁夜夜躁人人躁婷婷91| 国产这里只有精品| 精品中文字幕久久久久久| 亚洲男人天堂2023|