Android11.0(R) 手机锁屏炫酷充电动画————自定义View方案

简介: Android11.0(R) 手机锁屏炫酷充电动画————自定义View方案

本片文章的源码和修改思路均来自 Robin-GG

这里只是将其整理出来,实际验证亲测可行。


效果图


6UWXfs.gif


修改文件清单


SystemUI锁屏充电动画.zip

vendor/mediatek/proprietary/packages/apps/SystemUI/res/drawable-xhdpi/
vendor/mediatek/proprietary/packages/apps/SystemUI/res/layout/prize_charge_layout.xml
vendor/mediatek/proprietary/packages/apps/SystemUI/res/layout/super_status_bar.xml
vendor/mediatek/proprietary/packages/apps/SystemUI/res/values/ids.xml
vendor/mediatek/proprietary/packages/apps/SystemUI/res/values/strings.xml
vendor/mediatek/proprietary/packages/apps/SystemUI/res/values-zh-rCN/strings.xml
vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardChargeAnimationView.java
vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/power/PowerUI.java


具体实现


vendor/mediatek/proprietary/packages/apps/SystemUI/res/layout/prize_charge_layout.xml


<?xml version="1.0" encoding="utf-8"?>
<com.android.systemui.statusbar.phone.KeyguardChargeAnimationView 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:aapt="http://schemas.android.com/aapt"
    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
    xmlns:sysui="http://schemas.android.com/apk/res-auto"
    android:id="@id/keyguard_charge_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#e6000000">
    <ImageView
        android:id="@id/dot_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:padding="0dp"
        android:src="@drawable/prize_charge_dot" />
    <ImageView
        android:id="@id/ring_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:padding="0dp"
        android:src="@drawable/prize_charge_ring" />
    <LinearLayout
        android:id="@id/battery_layout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:layout_gravity="center"
        android:gravity="center"
        android:orientation="horizontal">
        <ImageView
            android:id="@id/charge_icon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="1dp"
            android:layout_marginRight="3dp" />
        <TextView
            android:id="@id/battery_level"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:fontFamily="sans-serif-light"
            android:textColor="#ffffff"
            android:textSize="28dp" />
    </LinearLayout>
    <TextView
        android:id="@id/battery_prompt"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/ring_view"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="5dp"
        android:fontFamily="sans-serif-light"
        android:textColor="#ffffff"
        android:textSize="14dp" />
</com.android.systemui.statusbar.phone.KeyguardChargeAnimationView>


vendor/mediatek/proprietary/packages/apps/SystemUI/res/layout/super_status_bar.xml

<!-- This is the status bar window. -->
<com.android.systemui.statusbar.phone.StatusBarWindowView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:sysui="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">
    <!-- cczheng add 16dp for charge animation-->
    <FrameLayout
        android:id="@+id/status_bar_container"
        android:paddingStart="16dp"
        android:paddingEnd="16dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/system_bar_background" />
    <!-- cczheng add for charge animation-->
    <include android:visibility="invisible" 
        android:layout_width="match_parent" 
        android:layout_height="match_parent" 
        layout="@layout/prize_charge_layout"/>
</com.android.systemui.statusbar.phone.StatusBarWindowView>


vendor/mediatek/proprietary/packages/apps/SystemUI/res/values/ids.xml

     <!-- cczheng add for charge animation -->
    <item type="id" name="keyguard_charge_view" />
    <item type="id" name="dot_view" />
    <item type="id" name="ring_view" />
    <item type="id" name="battery_layout" />
    <item type="id" name="charge_icon" />
    <item type="id" name="battery_level" />
    <item type="id" name="battery_prompt" />


vendor/mediatek/proprietary/packages/apps/SystemUI/res/values/strings.xml

vendor/mediatek/proprietary/packages/apps/SystemUI/res/values-zh-rCN/strings.xml

   <!-- cczheng add for charge animation -->
    <string name="fcharge_prompt">Fast charging</string>
    <string name="charge_prompt">Charging</string>

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

import com.android.systemui.statusbar.phone.KeyguardChargeAnimationView;
    private KeyguardChargeAnimationView mKeyguardChargeAnimationView;
    private boolean isScreenOn = true;
    private boolean mDozing;
    public void setIndicationArea(ViewGroup indicationArea) {
        .....
    //cczheng add for charge animation
        mKeyguardChargeAnimationView = indicationArea.getRootView().findViewById(R.id.keyguard_charge_view);
        updateIndication(false /* animate */);
        updateDisclosure();
  public void setScreenOn(boolean isOn) {
        isScreenOn = isOn;
    }
    protected class BaseKeyguardCallback extends KeyguardUpdateMonitorCallback {
        public static final int HIDE_DELAY_MS = 5000;
        @Override
        public void onRefreshBatteryInfo(BatteryStatus status) {
            boolean isChargingOrFull = status.status == BatteryManager.BATTERY_STATUS_CHARGING
                    || status.status == BatteryManager.BATTERY_STATUS_FULL;
            boolean wasPluggedIn = mPowerPluggedIn;
            mPowerPluggedInWired = status.isPluggedInWired() && isChargingOrFull;
            mPowerPluggedIn = status.isPluggedIn() && isChargingOrFull;
            mPowerCharged = status.isCharged();
            mChargingWattage = status.maxChargingWattage;
            mChargingSpeed = status.getChargingSpeed(mContext);
            mBatteryLevel = status.level;
            try {
                mChargingTimeRemaining = mPowerPluggedIn
                        ? mBatteryInfo.computeChargeTimeRemaining() : -1;
            } catch (RemoteException e) {
                Log.e(TAG, "Error calling IBatteryStats: ", e);
                mChargingTimeRemaining = -1;
            }
      android.util.Log.e("Keyguard", "isChargingOrFull="+isChargingOrFull);
            android.util.Log.e("Keyguard", "mVisible="+mVisible+" wasPluggedIn="+wasPluggedIn+" mPowerPluggedInWired="+mPowerPluggedInWired);
            android.util.Log.d("Keyguard", "mPowerPluggedIn="+mPowerPluggedIn+" mPowerCharged="+mPowerCharged+" mBatteryLevel="+mBatteryLevel);
            //cczheng add for charge animation
            if (mKeyguardChargeAnimationView != null) {
                if (mVisible && !wasPluggedIn && mPowerPluggedInWired) {
                    mKeyguardChargeAnimationView.closeByDelay();
                    mKeyguardChargeAnimationView.setBattery(mBatteryLevel);
                    mKeyguardChargeAnimationView.anim2Show(isScreenOn);
                } else if (!status.isPluggedIn()) {
                    mKeyguardChargeAnimationView.anim2hide();
                }
            } 
      updateIndication(!wasPluggedIn && mPowerPluggedInWired);

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

  else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
            if (mNotificationShadeWindowController != null) {
                mNotificationShadeWindowController.setNotTouchable(false);
            }
            if (mBubbleController.isStackExpanded()) {
                mBubbleController.collapseStack();
            }
            //cczheng add for charge animation 
            if (mKeyguardIndicationController != null) {
                mKeyguardIndicationController.setScreenOn(false);
            }
            finishBarAnimations();
            resetUserExpandedStates();
        }

vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/power/PowerUI.java

import android.app.KeyguardManager;
import android.content.pm.ActivityInfo;
import android.graphics.PixelFormat;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.os.Message;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import com.android.systemui.statusbar.phone.KeyguardChargeAnimationView;
static final boolean DEBUG = true || Log.isLoggable(TAG, Log.DEBUG);
        public void init() {
      ...
      filter.addAction(Intent.ACTION_POWER_CONNECTED);
            filter.addAction(Intent.ACTION_POWER_DISCONNECTED);
            filter.addAction(Intent.ACTION_USER_SWITCHED);
     @Override
        public void onReceive(Context context, Intent intent) {
    ....
         } else if (Intent.ACTION_SCREEN_ON.equals(action)) {
                mScreenOffTime = -1;
            } else if (Intent.ACTION_POWER_CONNECTED.equals(action)) {//cczheng add
                KeyguardManager mKeyguardManager = (KeyguardManager)mContext.getSystemService(Context.KEYGUARD_SERVICE);
                boolean lockState = mKeyguardManager.inKeyguardRestrictedInputMode();
                Log.d(TAG,"ACTION_POWER_CONNECTED lockState="+lockState + " mBatteryLevel="+mBatteryLevel);
                if (!lockState ){
                   addChargeWindowView();
                }
            } else if (Intent.ACTION_POWER_DISCONNECTED.equals(action)) {
               Log.d(TAG,"ACTION_POWER_DISCONNECTED");
               removeChargeWindowView();
            } else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
                mWarnings.userSwitched();
            } else {
                Slog.w(TAG, "unknown intent: " + intent);
            }
        }
    }
  //cczheng add for chargeview start
    WindowManager mWindowManager;
    WindowManager.LayoutParams wmParams;
    View mRootView;
    KeyguardChargeAnimationView chargeView;
    boolean isShowChargingView;
    private void addChargeWindowView(){
        wmParams = new WindowManager.LayoutParams();
        mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
        wmParams.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
        wmParams.type = LayoutParams.TYPE_NAVIGATION_BAR_PANEL; 
        wmParams.format = PixelFormat.RGBA_8888;
        wmParams.flags = LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_SHOW_WHEN_LOCKED |
                LayoutParams.FLAG_LAYOUT_NO_LIMITS | LayoutParams.FLAG_FULLSCREEN;
        wmParams.gravity = Gravity.START | Gravity.TOP;
        int statusBarHeight = 0;
        int resourceId = mContext.getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            statusBarHeight = mContext.getResources().getDimensionPixelSize(resourceId);
        }
        wmParams.x = 0;
        wmParams.y = -statusBarHeight;
        wmParams.width = 720;
        wmParams.height = 1560;
        mRootView = LayoutInflater.from(mContext).inflate(R.layout.prize_charge_layout, null, false);
        mWindowManager.addView(mRootView, wmParams);
        isShowChargingView = true;
        chargeView = (KeyguardChargeAnimationView)mRootView.findViewById(R.id.keyguard_charge_view);
        chargeView.setBattery(mBatteryLevel);
        chargeView.anim2Show(true);
        cHandler.removeMessages(100);
        cHandler.sendEmptyMessageDelayed(100, 3000);//3s auto dismiss
        mRootView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (event.getAction() == MotionEvent.ACTION_DOWN) {
                    return true;
                }
                if (event.getAction() == MotionEvent.ACTION_UP) {
                     removeChargeWindowView();
                    return true;
                }
                return true;
            }
        });
    }
    private Handler cHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            removeChargeWindowView();
        }
    };
    private void removeChargeWindowView(){
        cHandler.removeMessages(100);
        if (isShowChargingView && mRootView != null) {
            isShowChargingView = false;
            chargeView.anim2hide();
            mWindowManager.removeViewImmediate(mRootView);
            mRootView = null;
        }
    }
    //cczheng add for chargeview end

自定义充电 KeyguardChargeAnimationView


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

package com.android.systemui.statusbar.phone;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.MotionEvent;
import android.view.WindowManager;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.android.systemui.R;
import java.util.ArrayList;
import java.util.List;
public class KeyguardChargeAnimationView extends RelativeLayout {
    public final static boolean isInFastCharger = false;
    private final int BORN_STAR_WIDTH = 300;
    private final int CREATE_STAR_MSG = 10002;
    private final int STARS_INTERVAL = 350;
    private int battery;
    private TextView batteryLevelTxt;
    private TextView batteryPromptTxt;
    private Bitmap batterySourceBmp;
    private Bitmap[] batteryStar;
    private final int chargeColor = -1;
    private ImageView chargeIcon;
    private ImageView dotView;
    private final int fastChargeColor = -12910685;
    private int height;
    private boolean isPause = false;
    private boolean isScreenOn = true;
    Handler mHandler = new Handler() {
        public void handleMessage(Message message) {
            super.handleMessage(message);
            if (message.what == 10002) {
                createOneStar();
            }
        }
    };
    private AnimationListener onAnimationListener;
    private Paint paint;
    private ImageView ringView;
    private int speedUpFactor = 3;
    private List<Star> starList;
    private long updateTime = 0;
    private int width;
    public abstract class AnimationListener {
        public abstract void onAnimationEnd();
        public abstract void onAnimationStart();
    }
    private Runnable hideKeyguardChargeAnimationView = new Runnable() {
        @Override
        public void run() {
            anim2hide();
        }
    };
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            return true;
        }
        if (ev.getAction() == MotionEvent.ACTION_UP) {
            anim2hide();
            return true;
        }
        return super.dispatchTouchEvent(ev);
    }
    public void closeByDelay() {
        removeCallbacks(hideKeyguardChargeAnimationView);
        postDelayed(hideKeyguardChargeAnimationView, 5 * 1000);
    }
    public class Star {
        public Bitmap bitmap;
        public float horSpeed;
        public boolean isLeft;
        public float offx;
        public int swingDistance;
        public float verSpeed;
        public int x;
        public int y;
        public Star() {
        }
    }
    public void anim2Show(boolean screen_on) {
        if (battery < 100) {
            start();
        } else {
            stop();
        }
        if (!screen_on) {
            this.setAlpha(1.0f);
            setVisibility(VISIBLE);
            return;
        }
        if (getVisibility() == VISIBLE) {
            return;
        }
        this.setAlpha(0);
        this.setVisibility(VISIBLE);
        chargeViewHideAnimator = ValueAnimator.ofFloat(new float[]{0.0f, 1.0f});
        chargeViewHideAnimator.setDuration(500);
        chargeViewHideAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                setAlpha(((Float) valueAnimator.getAnimatedValue()).floatValue());
            }
        });
        chargeViewHideAnimator.addListener(new AnimatorListenerAdapter() {
            public void onAnimationEnd(Animator animator) {
                super.onAnimationEnd(animator);
                chargeViewHideAnimator = null;
                setAlpha(1.0f);
                setVisibility(VISIBLE);
            }
        });
        chargeViewHideAnimator.start();
    }
    private ValueAnimator chargeViewHideAnimator;
    public void anim2hide() {
        removeCallbacks(hideKeyguardChargeAnimationView);
        if (getVisibility() != VISIBLE) {
            return;
        }
        chargeViewHideAnimator = ValueAnimator.ofFloat(new float[]{1.0f, 0.0f});
        chargeViewHideAnimator.setDuration(500);
        chargeViewHideAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                setAlpha(((Float) valueAnimator.getAnimatedValue()).floatValue());
            }
        });
        chargeViewHideAnimator.addListener(new AnimatorListenerAdapter() {
            public void onAnimationEnd(Animator animator) {
                super.onAnimationEnd(animator);
                chargeViewHideAnimator = null;
                setAlpha(0.0f);
                setVisibility(INVISIBLE);
                stop();
            }
        });
        chargeViewHideAnimator.start();
    }
    public KeyguardChargeAnimationView(Context context) {
        super(context);
        init();
    }
    public KeyguardChargeAnimationView(Context context, AttributeSet attributeSet) {
        super(context, attributeSet);
        init();
    }
    public KeyguardChargeAnimationView(Context context, AttributeSet attributeSet, int i) {
        super(context, attributeSet, i);
        init();
    }
    public KeyguardChargeAnimationView(Context context, AttributeSet attributeSet, int i, int i2) {
        super(context, attributeSet, i, i2);
        init();
    }
    private void init() {
        this.starList = new ArrayList();
        this.paint = new Paint(1);
        this.paint.setAntiAlias(true);
        this.paint.setFilterBitmap(true);
        this.paint.setDither(true);
        this.batterySourceBmp = BitmapFactory.decodeResource(getResources(), R.drawable.prize_charge_batterysource);
        this.batteryStar = new Bitmap[]{BitmapFactory.decodeResource(getResources(), R.drawable.prize_charge_star_s), 
        BitmapFactory.decodeResource(getResources(), R.drawable.prize_charge_star_m),
        BitmapFactory.decodeResource(getResources(), R.drawable.prize_charge_star_b)};
    }
    /* access modifiers changed from: protected */
    public void onFinishInflate() {
        super.onFinishInflate();
        this.ringView = (ImageView) findViewById(R.id.ring_view);
        this.dotView = (ImageView) findViewById(R.id.dot_view);
        startViewRingAnimation(this.ringView, 30000);
        startViewRingAnimation(this.dotView, 60000);
        this.chargeIcon = (ImageView) findViewById(R.id.charge_icon);
        this.batteryLevelTxt = (TextView) findViewById(R.id.battery_level);
        this.batteryPromptTxt = (TextView) findViewById(R.id.battery_prompt);
    }
    private void startViewRingAnimation(ImageView imageView, long j) {
        if (imageView != null) {
            RotateAnimation rotateAnimation = new RotateAnimation(0.0f, 360.0f, 1, 0.5f, 1, 0.5f);
            rotateAnimation.setInterpolator(new LinearInterpolator());
            rotateAnimation.setDuration(j);
            rotateAnimation.setRepeatCount(-1);
            rotateAnimation.setFillAfter(true);
            imageView.startAnimation(rotateAnimation);
        }
    }
    private void updateChargeIcon() {
        ImageView imageView = this.chargeIcon;
        if (imageView != null) {
            if (isInFastCharger) {
                imageView.setImageResource(R.drawable.prize_charge_fast_icon);
                this.chargeIcon.setColorFilter(-12910685);
            } else {
                imageView.setImageResource(R.drawable.prize_charge_icon);
                this.chargeIcon.setColorFilter(-1);
            }
        }
    }
    private void updateBatteryLevel() {
        TextView textView = this.batteryLevelTxt;
        if (textView != null) {
            StringBuilder sb = new StringBuilder();
            sb.append(this.battery);
            sb.append("%");
            textView.setText(sb.toString());
            if (isInFastCharger) {
                this.batteryLevelTxt.setTextColor(-12910685);
                this.batteryPromptTxt.setText(getContext().getString(R.string.fcharge_prompt));
            } else {
                this.batteryLevelTxt.setTextColor(-1);
                this.batteryPromptTxt.setText(getContext().getString(R.string.charge_prompt));
            }
        }
    }
    public void start() {
        if ((this.isPause || this.speedUpFactor != 1) && this.isScreenOn) {
            this.isPause = false;
            this.speedUpFactor = 1;
            this.mHandler.removeMessages(10002);
            createOneStar();
            AnimationListener animationListener = this.onAnimationListener;
            if (animationListener != null) {
                animationListener.onAnimationStart();
            }
        }
    }
    public void stop() {
        this.isPause = true;
        this.speedUpFactor = 3;
        this.mHandler.removeMessages(10002);
        synchronized (this.starList) {
            this.starList.clear();
        }
    }
    /* access modifiers changed from: private */
    public void createOneStar() {
        synchronized (this.starList) {
            Star star = new Star();
            star.bitmap = this.batteryStar[(int) (Math.random() * ((double) this.batteryStar.length))];
            star.x = (int) (((double) ((this.width - 300) / 2)) + (Math.random() * ((double) (300 - star.bitmap.getWidth()))));
            star.y = this.height;
            star.verSpeed = (float) (isInFastCharger ? 4.5d : 2.5d + (Math.random() * 2.0d));
            star.horSpeed = (float) (Math.random() + 0.5d);
            star.isLeft = Math.random() <= 0.5d;
            double d = (double) 100;
            star.swingDistance = (int) (d + (Math.random() * d));
            if (getVisibility() == 0) {
                this.starList.add(star);
            }
            if (!this.isPause) {
                this.mHandler.removeMessages(10002);
                this.mHandler.sendEmptyMessageDelayed(10002, 350);
                if (this.starList.size() == 1) {
                    invalidate();
                }
            }
        }
    }
    /* access modifiers changed from: protected */
    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (this.width == 0 || this.height == 0) {
            Display defaultDisplay = ((WindowManager) getContext().getSystemService("window")).getDefaultDisplay();
            DisplayMetrics displayMetrics = new DisplayMetrics();
            defaultDisplay.getRealMetrics(displayMetrics);
            this.width = displayMetrics.widthPixels;
            this.height = displayMetrics.heightPixels;
        }
        int i = this.width;
        int i2 = this.height;
        if (i > i2) {
            this.width = i2;
            this.height = i;
        }
        if (this.width != 0 && this.height != 0) {
            synchronized (this.starList) {
                drawBatterySourceBmp(canvas);
                drawStars(canvas);
                updateChargeIcon();
                updateBatteryLevel();
                invalidate();
            }
        }
    }
    private void drawStars(Canvas canvas) {
        if (this.battery != 100) {
            List<Star> list = this.starList;
            if (!(list == null || list.size() == 0)) {
                if (this.updateTime == 0) {
                    this.updateTime = System.currentTimeMillis();
                }
                long currentTimeMillis = System.currentTimeMillis();
                int i = 0;
                boolean z = currentTimeMillis - this.updateTime >= 15;
                while (i < this.starList.size()) {
                    Star star = (Star) this.starList.get(i);
                    Bitmap bitmap = star.bitmap;
                    if (bitmap != null && !bitmap.isRecycled()) {
                        canvas.drawBitmap(star.bitmap, ((float) star.x) + star.offx, (float) star.y, this.paint);
                        if (z) {
                            this.updateTime = currentTimeMillis;
                            if (updateStar(star)) {
                                this.starList.remove(star);
                                if (this.starList.size() == 0) {
                                    AnimationListener animationListener = this.onAnimationListener;
                                    if (animationListener != null) {
                                        animationListener.onAnimationEnd();
                                    }
                                }
                                i--;
                            }
                        }
                    }
                    i++;
                }
            }
        }
    }
    private boolean updateStar(Star star) {
        if (star.isLeft) {
            star.offx -= star.horSpeed * ((float) this.speedUpFactor);
            if (star.offx <= ((float) (-star.swingDistance))) {
                star.isLeft = false;
            }
            if (((float) star.x) + star.offx <= ((float) ((this.width - 300) / 2))) {
                star.isLeft = false;
            }
        } else {
            star.offx += star.horSpeed * ((float) this.speedUpFactor);
            if (star.offx >= ((float) star.swingDistance)) {
                star.isLeft = true;
            }
            if (((float) star.x) + star.offx >= ((float) (((this.width + 300) / 2) - star.bitmap.getWidth()))) {
                star.isLeft = true;
            }
        }
        star.y = (int) (((float) star.y) - (star.verSpeed * ((float) this.speedUpFactor)));
        ImageView imageView = this.ringView;
        return star.y <= (imageView != null ? imageView.getBottom() - ((int) (((float) this.ringView.getHeight()) * 0.1f)) : 0);
    }
    private void drawBatterySourceBmp(Canvas canvas) {
        if (this.battery != 100) {
            Bitmap bitmap = this.batterySourceBmp;
            if (bitmap != null && !bitmap.isRecycled()) {
                canvas.drawBitmap(this.batterySourceBmp, (float) ((this.width - this.batterySourceBmp.getWidth()) / 2),
                 (float) (this.height - this.batterySourceBmp.getHeight()), this.paint);
            }
        }
    }
    /* access modifiers changed from: protected */
    public void onDetachedFromWindow() {
        super.onDetachedFromWindow();
    }
    public void setBattery(int i) {
        this.battery = i;
    }
}


目录
相关文章
|
12天前
|
搜索推荐 前端开发 Android开发
安卓应用开发中的自定义视图实现
【10月更文挑战第30天】在安卓开发的海洋中,自定义视图是那抹不可或缺的亮色,它为应用界面的个性化和交互体验的提升提供了无限可能。本文将深入探讨如何在安卓平台创建自定义视图,并展示如何通过代码实现这一过程。我们将从基础出发,逐步引导你理解自定义视图的核心概念,然后通过一个实际的代码示例,详细讲解如何将理论应用于实践,最终实现一个美观且具有良好用户体验的自定义控件。无论你是想提高自己的开发技能,还是仅仅出于对安卓开发的兴趣,这篇文章都将为你提供价值。
|
14天前
|
Android开发 开发者 UED
安卓开发中自定义View的实现与性能优化
【10月更文挑战第28天】在安卓开发领域,自定义View是提升应用界面独特性和用户体验的重要手段。本文将深入探讨如何高效地创建和管理自定义View,以及如何通过代码和性能调优来确保流畅的交互体验。我们将一起学习自定义View的生命周期、绘图基础和事件处理,进而探索内存和布局优化技巧,最终实现既美观又高效的安卓界面。
27 5
|
15天前
|
Web App开发 定位技术 iOS开发
Playwright 是一个强大的工具,用于在各种浏览器上测试应用,并模拟真实设备如手机和平板。通过配置 `playwright.devices`,可以轻松模拟不同设备的用户代理、屏幕尺寸、视口等特性。此外,Playwright 还支持模拟地理位置、区域设置、时区、权限(如通知)和配色方案,使测试更加全面和真实。例如,可以在配置文件中设置全局的区域设置和时区,然后在特定测试中进行覆盖。同时,还可以动态更改地理位置和媒体类型,以适应不同的测试需求。
Playwright 是一个强大的工具,用于在各种浏览器上测试应用,并模拟真实设备如手机和平板。通过配置 `playwright.devices`,可以轻松模拟不同设备的用户代理、屏幕尺寸、视口等特性。此外,Playwright 还支持模拟地理位置、区域设置、时区、权限(如通知)和配色方案,使测试更加全面和真实。例如,可以在配置文件中设置全局的区域设置和时区,然后在特定测试中进行覆盖。同时,还可以动态更改地理位置和媒体类型,以适应不同的测试需求。
17 1
|
21天前
|
缓存 数据处理 Android开发
在 Android 中使用 RxJava 更新 View
【10月更文挑战第20天】使用 RxJava 来更新 View 可以提供更优雅、更高效的解决方案。通过合理地运用操作符和订阅机制,我们能够轻松地处理异步数据并在主线程中进行 View 的更新。在实际应用中,需要根据具体情况进行灵活运用,并注意相关的注意事项和性能优化,以确保应用的稳定性和流畅性。可以通过不断的实践和探索,进一步掌握在 Android 中使用 RxJava 更新 View 的技巧和方法,为开发高质量的 Android 应用提供有力支持。
|
21天前
|
缓存 调度 Android开发
Android 在子线程更新 View
【10月更文挑战第21天】在 Android 开发中,虽然不能直接在子线程更新 View,但通过使用 Handler、AsyncTask 或 RxJava 等方法,可以实现子线程操作并在主线程更新 View 的目的。在实际应用中,需要根据具体情况选择合适的方法,并注意相关的注意事项和性能优化,以确保应用的稳定性和流畅性。可以通过不断的实践和探索,进一步掌握在子线程更新 View 的技巧和方法,为开发高质量的 Android 应用提供支持。
30 2
|
22天前
|
XML 前端开发 Android开发
Android面试高频知识点(3) 详解Android View的绘制流程
Android面试高频知识点(3) 详解Android View的绘制流程
Android面试高频知识点(3) 详解Android View的绘制流程
|
26天前
|
XML 前端开发 Android开发
Android面试高频知识点(3) 详解Android View的绘制流程
Android面试高频知识点(3) 详解Android View的绘制流程
23 2
|
3月前
|
存储 Shell Android开发
基于Android P,自定义Android开机动画的方法
本文详细介绍了基于Android P系统自定义开机动画的步骤,包括动画文件结构、脚本编写、ZIP打包方法以及如何将自定义动画集成到AOSP源码中。
76 2
基于Android P,自定义Android开机动画的方法
|
Android开发
Android自定义View,制作饼状图带动画效果
一个简单的自定义view饼状图,加入了动画效果
152 0
Android自定义View,制作饼状图带动画效果