android开发分享Android Studio实现华为手机的充电动画效果

目录根据系统原有的无线充电动画流程,新增有线充电气泡动画。效果图修改文件清单vendor/mediatek/proprietary/packages/apps/systemui/src/com/and

目录

根据系统原有的无线充电动画流程,新增有线充电气泡动画。

效果图

Android Studio实现华为手机的充电动画效果

修改文件清单

  	vendor/mediatek/proprietary/packages/apps/systemui/src/com/android/systemui/statusbar/phone/statusbar.java  	vendor/mediatek/proprietary/packages/apps/systemui/res/layout/wired_charging_layout.xml  	vendor/mediatek/proprietary/packages/apps/systemui/src/com/android/systemui/charging/bubblebean.java  	vendor/mediatek/proprietary/packages/apps/systemui/src/com/android/systemui/charging/bubbleviscosity.java  	vendor/mediatek/proprietary/packages/apps/systemui/src/com/android/systemui/charging/wiredcharginganimation.java  

具体实现

新增布局
vendor/mediatek/proprietary/packages/apps/systemui/res/layout/wired_charging_layout.xml

  <framelayout      xmlns:android="https://schemas.android.com/apk/res/android"      android:id="@+id/shcy_charge_view"      android:layout_width="match_parent"      android:layout_height="match_parent"      android:background="#99000000">        <com.android.systemui.charging.bubbleviscosity          android:id="@+id/shcy_bubble_view"          android:layout_width="match_parent"          android:layout_height="match_parent"/>  </framelayout>  

新增气泡 bean
vendor/mediatek/proprietary/packages/apps/systemui/src/com/android/systemui/charging/bubblebean.java

  package com.android.systemui.charging;    public class bubblebean {    	private float randomy = 3;  	private float x;  	private float y;  	private int index;    	public bubblebean(float x, float y, float randomy, int index) {  		this.x = x;  		this.y = y;  		this.randomy = randomy;  		this.index = index;  	}    	public void set(float x, float y, float randomy, int index) {  		this.x = x;  		this.y = y;  		this.randomy = randomy;  		this.index = index;  	}    	public void setmove(int screenheight, int maxdistance) {  		if (y - maxdistance < 110) {  			this.y -= 2;  			return;  		}    		if (maxdistance <= y && screenheight - y > 110) {  			this.y -= randomy;  		} else {  			this.y -= 0.6;  		}    		if (index == 0) {  			this.x -= 0.4;  		} else if (index == 2) {  			this.x += 0.4;  		}  	}    	public int getindex() {  		return index;  	}    	public float getx() {  		return x;  	}    	public void setx(float x) {  		this.x = x;  	}    	public float gety() {  		return y;  	}    	public void sety(float y) {  		this.y = y;  	}  }  

新增充电动画自定义 view
vendor/mediatek/proprietary/packages/apps/systemui/src/com/android/systemui/charging/bubbleviscosity.java

  package com.android.systemui.charging;    import java.util.arraylist;  import java.util.list;  import java.util.random;  import java.util.concurrent.executors;  import java.util.concurrent.scheduledexecutorservice;  import java.util.concurrent.timeunit;    import android.annotation.suppresslint;  import android.content.context;  import android.graphics.canvas;  import android.graphics.color;  import android.graphics.paint;  import android.graphics.path;  import android.graphics.pixelformat;  import android.graphics.pointf;  import android.graphics.porterduff;  import android.graphics.porterduffxfermode;  import android.graphics.rect;  import android.util.attributeset;  import android.util.displaymetrics;  import android.util.log;  import android.util.typedvalue;  import android.view.surfaceholder;  import android.view.surfaceview;    public class bubbleviscosity extends surfaceview implements  		surfaceholder.callback, runnable {  	private static scheduledexecutorservice scheduledthreadpool;  	private context context;  	private string paintcolor = "#25da29";  	private string centrecolor = "#00000000";  	private string mincentrecolor = "#9025da29";  	private int screenheight;  	private int screenwidth;    	private float lastradius;  	private float rate = 0.32f;  	private float rate2 = 0.45f;  	private pointf lastcurvestrat = new pointf();  	private pointf lastcurveend = new pointf();  	private pointf centrecirclepoint = new pointf();  	private float centreradius;  	private float bubbleradius;    	private pointf[] arcpointstrat = new pointf[8];  	private pointf[] arcpointend = new pointf[8];  	private pointf[] control = new pointf[8];  	private pointf arcstrat = new pointf();  	private pointf arcend = new pointf();  	private pointf controlp = new pointf();    	list<pointf> bubblelist = new arraylist<>();  	list<bubblebean> bubblebeans = new arraylist<>();    	private int rotateangle = 0;  	private float controlrate = 1.66f;  	private float controlrates = 1.3f;  	private int i = 0;  	private surfaceholder mholder;  	private float scale = 0;    	private paint arcpaint;  	private paint mincentrepaint;  	private paint bubblepaint;  	private paint centrepaint;  	private paint lastpaint;  	private path lastpath;  	private random random;  	private paint textpaint;  	private string text = "78 %";  	private rect rect;    	public bubbleviscosity(context context) {  		this(context, null);  	}    	public bubbleviscosity(context context, attributeset attrs) {  		this(context, attrs, 0);  	}    	public bubbleviscosity(context context, attributeset attrs,  			int defstyleattr) {  		super(context, attrs, defstyleattr);  		this.context = context;  		inittool();  	}    	@override  	protected void onmeasure(int widthmeasurespec, int heightmeasurespec) {  		super.onmeasure(widthmeasurespec, heightmeasurespec);  		screenheight = getmeasuredheight();  		screenwidth = getmeasuredwidth();  	}    	private void inittool() {  		rect = new rect();  		mholder = getholder();  		mholder.addcallback(this);  		setfocusable(true);  		mholder.setformat(pixelformat.transparent);  		setzorderontop(true);  		lastradius = dip2dimension(40f, context);  		centreradius = dip2dimension(100f, context);  		bubbleradius = dip2dimension(15f, context);  		random = new random();  		lastpaint = new paint();  		lastpaint.setantialias(true);  		lastpaint.setstyle(paint.style.fill);  		lastpaint.setcolor(color.parsecolor(paintcolor));  		lastpaint.setstrokewidth(2);    		lastpath = new path();    		centrepaint = new paint();  		centrepaint.setantialias(true);  		centrepaint.setstyle(paint.style.fill);  		centrepaint.setstrokewidth(2);  		centrepaint  				.setxfermode(new porterduffxfermode(porterduff.mode.src_out));  		centrepaint.setcolor(color.parsecolor(centrecolor));  		arcpaint = new paint();  		arcpaint.setantialias(true);  		arcpaint.setstyle(paint.style.fill);  		arcpaint.setcolor(color.parsecolor(paintcolor));  		arcpaint.setstrokewidth(2);  		mincentrepaint = new paint();  		mincentrepaint.setantialias(true);  		mincentrepaint.setstyle(paint.style.fill);  		mincentrepaint.setcolor(color.parsecolor(mincentrecolor));  		mincentrepaint.setstrokewidth(2);  		bubblepaint = new paint();  		bubblepaint.setantialias(true);  		bubblepaint.setstyle(paint.style.fill);  		bubblepaint.setcolor(color.parsecolor(mincentrecolor));  		bubblepaint.setstrokewidth(2);  		textpaint = new paint();  		textpaint.setantialias(true);  		textpaint.setstyle(paint.style.fill);  		textpaint.setcolor(color.parsecolor("#ffffff"));  		textpaint.setstrokewidth(2);  		textpaint.settextsize(dip2dimension(40f, context));    	}    	private void onmdraw() {  		canvas canvas = mholder.lockcanvas();  		canvas.drawcolor(color.transparent, porterduff.mode.clear);  		bubbledraw(canvas);  		lastcircledraw(canvas);  		centrecircledraw(canvas);  		textpaint.gettextbounds(text, 0, text.length(), rect);  		canvas.drawtext(text, centrecirclepoint.x - rect.width() / 2,  				centrecirclepoint.y + rect.height() / 2, textpaint);  		mholder.unlockcanvasandpost(canvas);  	}    	public void setbatterylevel(string level){  		this.text=level+"%";  		postinvalidate();  	}  	private void centrecircledraw(canvas canvas) {  		centrecirclepoint.set(screenwidth / 2, screenheight / 2);  		circleincoordinatedraw(canvas);  		canvas.drawcircle(centrecirclepoint.x, centrecirclepoint.y,  				centreradius, centrepaint);    	}    	private void lastcircledraw(canvas canvas) {  		lastcurvestrat.set(screenwidth / 2 - lastradius, screenheight);  		lastcurveend.set((screenwidth / 2), screenheight);    		float k = (lastradius / 2) / lastradius;    		float ax = lastradius - lastradius * rate2;  		float ay = lastcurvestrat.y - ax * k;  		float bx = lastradius - lastradius * rate;  		float by = lastcurveend.y - bx * k;    		lastpath.rewind();  		lastpath.moveto(lastcurvestrat.x, lastcurvestrat.y);  		lastpath.cubicto(lastcurvestrat.x + ax, ay, lastcurveend.x - bx, by,  				lastcurveend.x, lastcurveend.y - lastradius / 2);  		lastpath.cubicto(lastcurveend.x + bx, by, lastcurveend.x + lastradius  				- ax, ay, lastcurveend.x + lastradius, lastcurveend.y);    		lastpath.lineto(lastcurvestrat.x, lastcurvestrat.y);  		canvas.drawpath(lastpath, lastpaint);    	}    	private int bubbleindex = 0;    	private void bubbledraw(canvas canvas) {  		  		for (int i = 0; i < bubblebeans.size(); i++) {  			if (bubblebeans.get(i).gety() <= (int) (screenheight / 2 + centreradius)) {  				bubblepaint.setalpha(000);  				canvas.drawcircle(bubblebeans.get(i).getx(), bubblebeans.get(i)  						.gety(), bubbleradius, bubblepaint);  			} else {  				bubblepaint.setalpha(150);  				canvas.drawcircle(bubblebeans.get(i).getx(), bubblebeans.get(i)  						.gety(), bubbleradius, bubblepaint);  			}  		}    	}    	/**  	 * @param dip  	 * @param context  	 * @return  	 */  	public float dip2dimension(float dip, context context) {  		displaymetrics displaymetrics = context.getresources()  				.getdisplaymetrics();  		return typedvalue.applydimension(typedvalue.complex_unit_dip, dip,  				displaymetrics);  	}    	/**  	 * @param canvas  	 */  	public void circleincoordinatedraw(canvas canvas) {  		int angle;  		for (int i = 0; i < arcpointstrat.length; i++) {  			if (i > 3 && i < 6) {  				if (i == 4) {  					angle = rotateangle + i * 60;    				} else {  					angle = rotateangle + i * 64;  				}  			} else if (i > 5) {  				if (i == 6) {  					angle = rotateangle + i * 25;  				} else {  					angle = rotateangle + i * 48;  				}    			} else {  				angle = rotateangle + i * 90;  			}    			float radian = (float) math.toradians(angle);  			float adjacent = (float) math.cos(radian) * centreradius;  			float right = (float) math.sin(radian) * centreradius;  			float radiancontrol = (float) math.toradians(90 - (45 + angle));  			float xstrat = (float) math.cos(radiancontrol) * centreradius;  			float yend = (float) math.sin(radiancontrol) * centreradius;  			if (i == 0 || i == 1) {  				if (i == 1) {  					arcstrat.set(centrecirclepoint.x + adjacent - scale,  							centrecirclepoint.y + right + scale);  					arcend.set(centrecirclepoint.x - right, centrecirclepoint.y  							+ adjacent);    				} else {  					arcstrat.set(centrecirclepoint.x + adjacent,  							centrecirclepoint.y + right);  					arcend.set(centrecirclepoint.x - right - scale,  							centrecirclepoint.y + adjacent + scale);    				}  				controlp.set(centrecirclepoint.x + yend * controlrate,  						centrecirclepoint.y + xstrat * controlrate);  			} else {  				arcstrat.set(centrecirclepoint.x + adjacent,  						centrecirclepoint.y + right);  				arcend.set(centrecirclepoint.x - right, centrecirclepoint.y  						+ adjacent);  				if (i > 5) {  					controlp.set(centrecirclepoint.x + yend * controlrates,  							centrecirclepoint.y + xstrat * controlrates);  				} else {  					controlp.set(centrecirclepoint.x + yend * controlrate,  							centrecirclepoint.y + xstrat * controlrate);  				}  			}  			arcpointstrat[i] = arcstrat;  			arcpointend[i] = arcend;  			control[i] = controlp;    			lastpath.rewind();  			lastpath.moveto(arcpointstrat[i].x, arcpointstrat[i].y);  			lastpath.quadto(control[i].x, control[i].y, arcpointend[i].x,  					arcpointend[i].y);    			if (i > 3 && i < 6) {  				canvas.drawpath(lastpath, mincentrepaint);  			} else {  				canvas.drawpath(lastpath, arcpaint);  			}  			lastpath.rewind();  		}  	}    	private void setanimation() {  		setschedulewithfixeddelay(this, 0, 5);  		setschedulewithfixeddelay(new runnable() {  			@override  			public void run() {  				if (bubbleindex > 2)  					bubbleindex = 0;  				if (bubblebeans.size() < 8) {  					bubblebeans.add(new bubblebean(  							bubblelist.get(bubbleindex).x, bubblelist  									.get(bubbleindex).y, random.nextint(4) + 2,  							bubbleindex));  				} else {  					for (int i = 0; i < bubblebeans.size(); i++) {  						if (bubblebeans.get(i).gety() <= (int) (screenheight / 2 + centreradius)) {  							bubblebeans.get(i).set(  									bubblelist.get(bubbleindex).x,  									bubblelist.get(bubbleindex).y,  									random.nextint(4) + 2, bubbleindex);  							if (random.nextint(bubblebeans.size()) + 3 == 3 ? true  									: false) {  							} else {  								break;  							}  						}  					}  				}  				bubbleindex++;  			}  		}, 0, 300);  	}    	private static scheduledexecutorservice getinstence() {  		if (scheduledthreadpool == null) {  			synchronized (bubbleviscosity.class) {  				if (scheduledthreadpool == null) {  					scheduledthreadpool = executors  							.newsinglethreadscheduledexecutor();  				}  			}  		}  		return scheduledthreadpool;  	}    	private static void setschedulewithfixeddelay(runnable var1, long var2,  			long var4) {  		getinstence().schedulewithfixeddelay(var1, var2, var4,  				timeunit.milliseconds);    	}    	public static void ondestroythread() {  		getinstence().shutdownnow();  		if (scheduledthreadpool != null) {  			scheduledthreadpool = null;  		}  	}    	@override  	public void surfacecreated(surfaceholder holder) {  		bubblelist.clear();  		setbubblelist();  		startbubblerunnable();  		setanimation();  	}    	@override  	public void surfacechanged(surfaceholder holder, int format, int width,  			int height) {    	}    	@override  	public void surfacedestroyed(surfaceholder holder) {  		ondestroythread();  	}    	@override  	public void run() {  		i++;  		rotateangle = i;  		if (i > 90 && i < 180) {  			scale += 0.25;  			if (controlrates < 1.66)  				controlrates += 0.005;  		} else if (i >= 180) {  			scale -= 0.12;  			if (i > 300)  				controlrates -= 0.01;  		}  		onmdraw();  		if (i == 360) {  			i = 0;  			rotateangle = 0;  			controlrate = 1.66f;  			controlrates = 1.3f;  			scale = 0;  		}    	}    	public void setbubblelist() {  		float radian = (float) math.toradians(35);  		float adjacent = (float) math.cos(radian) * lastradius / 3;  		float right = (float) math.sin(radian) * lastradius / 3;  		if (!bubblelist.isempty())  			return;  		bubblelist.add(new pointf(screenwidth / 2 - adjacent, screenheight  				- right));  		bubblelist.add(new pointf(screenwidth / 2, screenheight - lastradius  				/ 4));  		bubblelist.add(new pointf(screenwidth / 2 + adjacent, screenheight  				- right));  		startbubblerunnable();  	}  	  	public void startbubblerunnable(){  		setschedulewithfixeddelay(new runnable() {  			@override  			public void run() {  				for (int i = 0; i < bubblebeans.size(); i++) {  					bubblebeans.get(i).setmove(screenheight,  							(int) (screenheight / 2 + centreradius));  				}  			}  		}, 0, 4);  	}  }  

新增动画管理类
vendor/mediatek/proprietary/packages/apps/systemui/src/com/android/systemui/charging/wiredcharginganimation.java

  package com.android.systemui.charging;    import android.annotation.nonnull;  import android.annotation.nullable;  import android.content.context;  import android.graphics.pixelformat;  import android.os.handler;  import android.os.looper;  import android.os.message;  import android.util.log;  import android.util.slog;  import android.view.gravity;  import android.view.view;  import android.view.windowmanager;  import android.view.layoutinflater;  import com.android.systemui.r;    public class wiredcharginganimation {        public static final long duration = 3333;      private static final string tag = "wiredcharginganimation";      private static final boolean debug = true || log.isloggable(tag, log.debug);        private final wiredchargingview mcurrentwirelesschargingview;      private static wiredchargingview mpreviouswirelesschargingview;      private static boolean mshowingwiredcharginganimation;        public static boolean isshowingwiredcharginganimation(){          return mshowingwiredcharginganimation;      }        public wiredcharginganimation(@nonnull context context, @nullable looper looper, int              batterylevel,  boolean isdozing) {          mcurrentwirelesschargingview = new wiredchargingview(context, looper,                  batterylevel, isdozing);      }        public static wiredcharginganimation makewiredcharginganimation(@nonnull context context,              @nullable looper looper, int batterylevel, boolean isdozing) {          mshowingwiredcharginganimation = true;          android.util.log.d(tag,"makewiredcharginganimation batterylevel="+batterylevel);          return new wiredcharginganimation(context, looper, batterylevel, isdozing);      }        /**       * show the view for the specified duration.       */      public void show() {          if (mcurrentwirelesschargingview == null ||                  mcurrentwirelesschargingview.mnextview == null) {              throw new runtimeexception("setview must have been called");          }            /*if (mpreviouswirelesschargingview != null) {              mpreviouswirelesschargingview.hide(0);          }*/            mpreviouswirelesschargingview = mcurrentwirelesschargingview;          mcurrentwirelesschargingview.show();          mcurrentwirelesschargingview.hide(duration);      }        private static class wiredchargingview {          private static final int show = 0;          private static final int hide = 1;            private final windowmanager.layoutparams mparams = new windowmanager.layoutparams();          private final handler mhandler;            private int mgravity;          private view mview;          private view mnextview;          private windowmanager mwm;            public wiredchargingview(context context, @nullable looper looper, int batterylevel, boolean isdozing) {              //mnextview = new wirelesscharginglayout(context, batterylevel, isdozing);              mnextview = layoutinflater.from(context).inflate(r.layout.wired_charging_layout, null, false);              bubbleviscosity shcybubbleviscosity = mnextview.findviewbyid(r.id.shcy_bubble_view);              shcybubbleviscosity.setbatterylevel(batterylevel+"");                mgravity = gravity.center_horizontal | gravity.center;                final windowmanager.layoutparams params = mparams;              params.height = windowmanager.layoutparams.match_parent;              params.width = windowmanager.layoutparams.match_parent;              params.format = pixelformat.translucent;                params.type = windowmanager.layoutparams.type_keyguard_dialog;              params.settitle("charging animation");              params.flags = windowmanager.layoutparams.flag_not_focusable                      | windowmanager.layoutparams.flag_not_touchable                      | windowmanager.layoutparams.flag_dim_behind;                params.dimamount = .3f;                if (looper == null) {                  // use looper.mylooper() if looper is not specified.                  looper = looper.mylooper();                  if (looper == null) {                      throw new runtimeexception(                              "can't display wireless animation on a thread that has not called "                                      + "looper.prepare()");                  }              }                mhandler = new handler(looper, null) {                  @override                  public void handlemessage(message msg) {                      switch (msg.what) {                          case show: {                              handleshow();                              break;                          }                          case hide: {                              handlehide();                              // don't do this in handlehide() because it is also invoked by                              // handleshow()                              mnextview = null;                              mshowingwiredcharginganimation = false;                              break;                          }                      }                  }              };          }            public void show() {              if (debug) slog.d(tag, "show: " + this);              mhandler.obtainmessage(show).sendtotarget();          }            public void hide(long duration) {              mhandler.removemessages(hide);                if (debug) slog.d(tag, "hide: " + this);              mhandler.sendmessagedelayed(message.obtain(mhandler, hide), duration);          }            private void handleshow() {              if (debug) {                  slog.d(tag, "handle show: " + this + " mview=" + mview + " mnextview="                          + mnextview);              }                if (mview != mnextview) {                  // remove the old view if necessary                  handlehide();                  mview = mnextview;                  context context = mview.getcontext().getapplicationcontext();                  string packagename = mview.getcontext().getoppackagename();                  if (context == null) {                      context = mview.getcontext();                  }                  mwm = (windowmanager) context.getsystemservice(context.window_service);                  mparams.packagename = packagename;                  mparams.hidetimeoutmilliseconds = duration;                    if (mview.getparent() != null) {                      if (debug) slog.d(tag, "remove! " + mview + " in " + this);                      mwm.removeview(mview);                  }                  if (debug) slog.d(tag, "add! " + mview + " in " + this);                    try {                      mwm.addview(mview, mparams);                  } catch (windowmanager.badtokenexception e) {                      slog.d(tag, "unable to add wireless charging view. " + e);                  }              }          }            private void handlehide() {              if (debug) slog.d(tag, "handle hide: " + this + " mview=" + mview);              if (mview != null) {                  if (mview.getparent() != null) {                      if (debug) slog.d(tag, "remove! " + mview + " in " + this);                      mwm.removeviewimmediate(mview);                  }                    mview = null;              }          }      }  }    

电源插入时且在锁屏下显示气泡动画

vendor/mediatek/proprietary/packages/apps/systemui/src/com/android/systemui/statusbar/phone/statusbar.java

  //cczheng add for hw charge start   import com.android.systemui.charging.wiredcharginganimation;  //cczheng add for hw charge end    		mbatterycontroller.addcallback(new batterystatechangecallback() {              @override              public void onpowersavechanged(boolean ispowersave) {                  mhandler.post(mcheckbarmodes);                  if (mdozeservicehost != null) {                      mdozeservicehost.firepowersavechanged(ispowersave);                  }              }                @override              public void onbatterylevelchanged(int level, boolean pluggedin, boolean charging) {                  // noop                   //cczheng add for hw charge start                      boolean isshowing = wiredcharginganimation.isshowingwiredcharginganimation();                  android.util.log.d("wiredcharginganimation","level="+level+" charging="+charging+" isshowing="+isshowing);                  if (!isshowing && charging && mstate == statusbarstate.keyguard) {                      wiredcharginganimation.makewiredcharginganimation(mcontext, null,                              level, false).show();                  }                  //cczheng add for hw charge end              }          });  

到此这篇关于android studio实现华为手机的充电动画效果的文章就介绍到这了,更多相关android 充电动画内容请搜索<计算机技术网(www.ctvol.com)!!>以前的文章或继续浏览下面的相关文章希望大家以后多多支持<计算机技术网(www.ctvol.com)!!>!

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/addevelopment/888988.html

(0)
上一篇 2021年10月19日
下一篇 2021年10月19日

精彩推荐