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;
    }
}


目录
相关文章
|
5月前
|
Android开发 开发者
Android利用SVG实现动画效果
本文介绍了如何在Android中利用SVG实现动画效果。首先通过定义`pathData`参数(如M、L、Z等)绘制一个简单的三角形SVG图形,然后借助`objectAnimator`实现动态的线条绘制动画。文章详细讲解了从配置`build.gradle`支持VectorDrawable,到创建动画文件、关联SVG与动画,最后在Activity中启动动画的完整流程。此外,还提供了SVG绘制原理及工具推荐,帮助开发者更好地理解和应用SVG动画技术。
250 30
|
5月前
|
API Android开发 开发者
Android颜色渐变动画效果的实现
本文介绍了在Android中实现颜色渐变动画效果的方法,重点讲解了插值器(TypeEvaluator)的使用与自定义。通过Android自带的颜色插值器ArgbEvaluator,可以轻松实现背景色的渐变动画。文章详细分析了ArgbEvaluator的核心代码,并演示了如何利用Color.colorToHSV和Color.HSVToColor方法自定义颜色插值器MyColorEvaluator。最后提供了完整的源码示例,包括ColorGradient视图类和MyColorEvaluator类,帮助开发者更好地理解和应用颜色渐变动画技术。
167 3
|
5月前
|
XML Java Android开发
Android自定义view之网易云推荐歌单界面
本文详细介绍了如何通过自定义View实现网易云音乐推荐歌单界面的效果。首先,作者自定义了一个圆角图片控件`MellowImageView`,用于绘制圆角矩形图片。接着,通过将布局放入`HorizontalScrollView`中,实现了左右滑动功能,并使用`ViewFlipper`添加图片切换动画效果。文章提供了完整的代码示例,包括XML布局、动画文件和Java代码,最终展示了实现效果。此教程适合想了解自定义View和动画效果的开发者。
266 65
Android自定义view之网易云推荐歌单界面
|
5月前
|
XML 前端开发 Android开发
一篇文章带你走近Android自定义view
这是一篇关于Android自定义View的全面教程,涵盖从基础到进阶的知识点。文章首先讲解了自定义View的必要性及简单实现(如通过三个构造函数解决焦点问题),接着深入探讨Canvas绘图、自定义属性设置、动画实现等内容。还提供了具体案例,如跑马灯、折线图、太极图等。此外,文章详细解析了View绘制流程(measure、layout、draw)和事件分发机制。最后延伸至SurfaceView、GLSurfaceView、SVG动画等高级主题,并附带GitHub案例供实践。适合希望深入理解Android自定义View的开发者学习参考。
595 84
|
5月前
|
Android开发 开发者
Android SVG动画详细例子
本文详细讲解了在Android中利用SVG实现动画效果的方法,通过具体例子帮助开发者更好地理解和应用SVG动画。文章首先展示了动画的实现效果,接着回顾了之前的文章链接及常见问题(如属性名大小写错误)。核心内容包括:1) 使用阿里图库获取SVG图形;2) 借助工具将SVG转换为VectorDrawable;3) 为每个路径添加动画绑定属性;4) 创建动画文件并关联SVG;5) 在ImageView中引用动画文件;6) 在Activity中启动动画。文末还提供了完整的代码示例和源码下载链接,方便读者实践操作。
308 65
|
5月前
|
XML Java Maven
Android线条等待动画JMWorkProgress(可添加依赖直接使用)
这是一篇关于Android线条等待动画JMWorkProgress的教程文章,作者计蒙将其代码开源至GitHub,提升可读性。文章介绍了如何通过添加依赖库使用该动画,并详细讲解了XML与Java中的配置方法,包括改变线条颜色、宽度、添加文字等自定义属性。项目已支持直接依赖集成(`implementation &#39;com.github.Yufseven:JMWorkProgress:v1.0&#39;`),开发者可以快速上手实现炫酷的等待动画效果。文末附有GitHub项目地址,欢迎访问并点赞支持!
157 26
|
5月前
|
前端开发 Android开发 UED
讲讲Android为自定义view提供的SurfaceView
本文详细介绍了Android中自定义View时使用SurfaceView的必要性和实现方式。首先分析了在复杂绘制逻辑和高频界面更新场景下,传统View可能引发卡顿的问题,进而引出SurfaceView作为解决方案。文章通过Android官方Demo展示了SurfaceView的基本用法,包括实现`SurfaceHolder.Callback2`接口、与Activity生命周期绑定、子线程中使用`lockCanvas()`和`unlockCanvasAndPost()`方法完成绘图操作。
136 3
|
12月前
|
XML 前端开发 Android开发
Android面试高频知识点(3) 详解Android View的绘制流程
Android面试高频知识点(3) 详解Android View的绘制流程
Android面试高频知识点(3) 详解Android View的绘制流程
|
XML 前端开发 Android开发
Android面试高频知识点(3) 详解Android View的绘制流程
Android面试高频知识点(3) 详解Android View的绘制流程
126 2
|
XML 前端开发 Android开发
Android View的绘制流程和原理详细解说
Android View的绘制流程和原理详细解说
308 3

热门文章

最新文章