AndroidカスタムView-バッテリ

73741 ワード

AndroidカスタムView-バッテリ
概要
最近の仕事の中で1つの需要があって、电量を表示する必要があって、制品は前の开発がすでにしたと言って、别のプロジェクトの中で、コピーしてくれればいいです.はい、それではコピーしましょう.結果を見ると、本当に驚きました.layer-listのdrawableを使っています.中には11種類の状態があります.0から100%です.11%を表示するにはどうすればいいですか?はい、この穴はもうおかしくありません.他の穴に比べて、これは問題ではありません.穴を埋めましょう.
バッテリビューの要件
  • 図は1%から100%の電力量を示している.
  • デジタル表示1-100、構成可能;
  • 電池は低電力で、電力量が十分で、充電時に異なる色を表示します.
  • は、バッテリの外枠の色とstrokeサイズを設定することができる.
  • は、横方向表示または縦方向表示のいずれかを選択することができる
  • .
    カスタムビュー
    このバッテリViewの要件は、Viewを継承してBatteryViewをカスタマイズすることによって実現されます.カスタムビューのコンセプトはこのブログを参考にすることができ、よく書かれています.カスタムビューには、次の4つのカテゴリがあります.
  • カスタムコンビネーションコントロール、例えばカスタム共通ActionBar;
  • は、TextView、LinearLayoutなどのシステムが提供する特定のView、View Groupを継承する.
  • はandroidを継承する.view.Viewは独自のView
  • を実現
  • はandroidを継承する.view.ViewGroupは自分のViewGroupを実現します.

  • カスタムViewの知識については、ここでは詳しく説明するが、カスタムバッテリViewのニーズを実現するには、3つ目を選択してandroidを継承することができる.view.Viewは、onDrawを書き換え、この方法でバッテリーのニーズを描きます.
    BatteryView実装
    効率を高めるため、このブログAndroidカスタムバッテリーコントロールに基づいて修正します(paddingといくつかの属性を追加しました).実装手順は次のとおりです.
  • 新規attrs.xmlはプロパティファイルを定義し、BatteryViewのプロパティを追加します.
  • はViewを継承し、BatteryViewを実現する.
  • は、構造関数において各属性を解析する.
  • onDrawを書き換え、プロパティに基づいてバッテリのアウトライン、バッテリ電力、バッテリキャップ、および電力パーセントを描画します.

  • 比較的簡単で、直接コードを貼り付けます.
  • attrs.xml
  •     <declare-styleable name="Battery">
            <attr name="batteryOrientation">
                <enum name="horizontal" value="0"/>
                <enum name="vertical" value="1"/>
            attr>
            <attr name="batteryColor" format="color"/> 
            <attr name="batteryStrokeWidth" format="dimension" /> 
            <attr name="batteryLowBatteryColor" format="color" /> 
            <attr name="batteryHealthBatteryColor" format="color" /> 
            <attr name="batteryHappyBatteryColor" format="color" />  
            <attr name="batteryChargingColor" format="color" /> 
            <attr name="batteryPower" format="integer"/>
            <attr name="batteryShowPercent" format="boolean" />  
            <attr name="batteryPercentColor" format="color"/> 
            <attr name="batteryPercentSize" format="dimension" /> 
    
        declare-styleable>
    
  • BatteryView.java
  • import android.content.Context;
    import android.content.res.TypedArray;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.RectF;
    import android.util.AttributeSet;
    import android.view.View;
    
    import androidx.annotation.ColorInt;
    import androidx.annotation.ColorRes;
    import androidx.annotation.Dimension;
    import androidx.annotation.IntDef;
    
    import com.bottle.app.R;
    import com.bottle.app.device.DisplayUtil;
    
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    
    /**
     *      \      
     */
    public class BatteryView extends View {
    
        public static final int HORIZONTAL = 0;
        public static final int VERTICAL = 1;
    
        @Retention(RetentionPolicy.SOURCE)
        @IntDef({HORIZONTAL, VERTICAL})
        @interface Orientation {
        }
    
        private int mPower = 100;          //   
        private int orientation;           //   
        private int mStrokeColor;          //        
        private int mStrokeWidth;           //        
        private int mLowBatteryColor;      //          
        private int mHealthBatteryColor;   //         
        private int mHappyBatteryColor;    //         
        private boolean mCharging;         //      
        private int mChargingColor;        //       
        private boolean mShowPercent;      //        
        private int mPercentColor;         //         
        private float mPercentSize;        //        
    
        private int width;
        private int height;
        private int headWidth;             //       
        private int headHeight;             //       
        private int mLowBattery = 20;      //      
        private int mHealthBattery = 50;   //       
    
        private Paint mPaint = new Paint();
    
        public void setPower(int power) {
            this.mPower = power;
            if (mPower < 0) {
                mPower = 0;
            } else if (mPower > 100) {
                mPower = 100;
            }
            invalidate();
        }
    
        public void setColor(@ColorRes int color) {
            this.mStrokeColor = color;
        }
    
        public void setOrientation(@Orientation int orientation) {
            this.orientation = orientation;
        }
    
        public void setStrokeColor(@ColorInt int strokeColor) {
            mStrokeColor = strokeColor;
        }
    
        public void setStrokeWith(@Dimension int strokeWidth) {
            mStrokeWidth = strokeWidth;
        }
    
        public void setLowBatteryColor(@ColorInt int lowBatteryColor) {
            mLowBatteryColor = lowBatteryColor;
        }
    
        public void setHealthBatteryColor(@ColorInt int healthBatteryColor) {
            mHealthBatteryColor = healthBatteryColor;
        }
    
        public void setHappyBatteryColor(@ColorInt int happyBatteryColor) {
            mHappyBatteryColor = happyBatteryColor;
        }
    
        public void setCharging(boolean charging) {
            mCharging = charging;
        }
    
        public void setChargingColor(@ColorInt int chargingColor) {
            mChargingColor = chargingColor;
        }
    
        public void setLowBattery(int lowBattery) {
            mLowBattery = lowBattery;
        }
    
        public void setHealthBattery(int healthBattery) {
            mHealthBattery = healthBattery;
        }
    
        public void setShowPercent(boolean showPercent) {
            mShowPercent = showPercent;
        }
    
        public void setPercentColor(@ColorInt int percentColor) {
            mPercentColor = percentColor;
        }
    
        public void setPercentSize(@Dimension int percentSize) {
            mPercentSize = percentSize;
        }
    
        public BatteryView(Context context) {
            super(context);
        }
    
        public BatteryView(Context context, AttributeSet attrs) {
            super(context, attrs);
            TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.Battery);
            mStrokeColor = typedArray.getColor(R.styleable.Battery_batteryColor, Color.BLACK);
            mStrokeWidth = typedArray.getDimensionPixelOffset(
                    R.styleable.Battery_batteryStrokeWidth, DisplayUtil.dip2px(context, 1));
            mLowBatteryColor = typedArray.getColor(R.styleable.Battery_batteryLowBatteryColor, Color.RED);
            mHealthBatteryColor = typedArray.getColor(R.styleable.Battery_batteryHealthBatteryColor, Color.parseColor("#76AE00"));
            mHappyBatteryColor = typedArray.getColor(R.styleable.Battery_batteryHappyBatteryColor, Color.GREEN);
            mChargingColor = typedArray.getColor(R.styleable.Battery_batteryColor, Color.YELLOW);
            orientation = typedArray.getInt(R.styleable.Battery_batteryOrientation, 0);
            mPower = typedArray.getInt(R.styleable.Battery_batteryPower, 100);
            mShowPercent = typedArray.getBoolean(R.styleable.Battery_batteryShowPercent, false);
            mPercentColor = typedArray.getColor(R.styleable.Battery_batteryPercentColor, Color.BLACK);
            mPercentSize = typedArray.getDimensionPixelOffset(
                    R.styleable.Battery_batteryPercentSize, DisplayUtil.sp2px(context, 11));
            typedArray.recycle();
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            width = getMeasuredWidth();
            height = getMeasuredHeight();
            if (orientation == HORIZONTAL) {
                headWidth = (height - getPaddingTop() - getPaddingBottom() - mStrokeWidth * 2) / 2;
            } else {
                headWidth = (width - getPaddingStart() - getPaddingEnd() - mStrokeWidth * 2) / 2;
            }
            headHeight = headWidth / 2;
            int max = DisplayUtil.dip2px(getContext(), 8);
            if (headHeight > max) {
                //            
                headHeight = max;
            }
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            if (orientation == HORIZONTAL) {
                drawHorizontalBattery(canvas);
            } else {
                drawVerticalBattery(canvas);
            }
        }
    
        private void drawHorizontalBattery(Canvas canvas) {
            float strokeWithHalf = mStrokeWidth / 2f;
            // 1.       
            mPaint.setColor(mStrokeColor);
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setStrokeWidth(mStrokeWidth);
            RectF r1 = new RectF(getPaddingStart() + strokeWithHalf,
                    getPaddingTop()  + strokeWithHalf,
                    width - getPaddingEnd() - headHeight,
                    height - getPaddingBottom() - strokeWithHalf);
            canvas.drawRect(r1, mPaint);
    
            // 2.      
            mPaint.setStyle(Paint.Style.FILL);
            float offset = (width - getPaddingStart() - getPaddingEnd() - mStrokeWidth * 2 - headHeight) * mPower / 100.f;
            RectF r2 = new RectF(getPaddingStart() + mStrokeWidth,
                    getPaddingTop() + mStrokeWidth,
                    getPaddingStart() + mStrokeWidth + offset + strokeWithHalf, // padding +     +    +       (       )
                    height - getPaddingBottom() - mStrokeWidth);
            if (mCharging) {
                mPaint.setColor(mChargingColor);
            } else if (mPower < mLowBattery) {
                mPaint.setColor(mLowBatteryColor);
            } else if (mPower < mHealthBattery) {
                mPaint.setColor(mHealthBatteryColor);
            } else {
                mPaint.setColor(mHappyBatteryColor);
            }
            canvas.drawRect(r2, mPaint);
    
            // 3.    
            RectF r3 = new RectF(width - getPaddingEnd() - headHeight,
                    height / 2f - headWidth / 2f,
                    width - getPaddingEnd(),
                    height / 2f + headWidth / 2f);
            mPaint.setColor(mStrokeColor);
            canvas.drawRect(r3, mPaint);
    
            // 4.       
            if (mShowPercent) {
                mPaint.setAntiAlias(true);
                mPaint.setStyle(Paint.Style.FILL);
                mPaint.setTextAlign(Paint.Align.CENTER);
                mPaint.setTextSize(mPercentSize);
                mPaint.setColor(mPercentColor);
                mPaint.setStrokeWidth(1);
                String text = String.valueOf(mPower);
                canvas.drawText(text,
                        width / 2f - mPaint.measureText(text) / 2,
                        height / 2f + (mPaint.getFontMetrics().bottom - mPaint.getFontMetrics().top) / 2 - mPaint.getFontMetrics().bottom,
                        mPaint);
            }
        }
    
        private void drawVerticalBattery(Canvas canvas) {
            float strokeWithHalf = mStrokeWidth / 2f;
            // 1.       
            mPaint.setColor(mStrokeColor);
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setStrokeWidth(mStrokeWidth);
            RectF r1 = new RectF(getPaddingStart() + strokeWithHalf,
                    getPaddingTop() + headHeight,
                    width - getPaddingEnd(),
                    height - getPaddingBottom() - strokeWithHalf);
            canvas.drawRect(r1, mPaint);
    
            // 2.      
            mPaint.setStyle(Paint.Style.FILL);
            float offset = (height - getPaddingTop() - getPaddingBottom() - mStrokeWidth * 2 - headHeight) * mPower / 100.f;
            RectF r2 = new RectF(getPaddingStart() + mStrokeWidth,
                    height - getPaddingTop() - mStrokeWidth - offset - strokeWithHalf ,
                    width - getPaddingEnd()  - strokeWithHalf,
                    height - getPaddingBottom() - mStrokeWidth);
            if (mCharging) {
                mPaint.setColor(mChargingColor);
            } else if (mPower < mLowBattery) {
                mPaint.setColor(mLowBatteryColor);
            } else if (mPower < mHealthBattery) {
                mPaint.setColor(mHealthBatteryColor);
            } else {
                mPaint.setColor(mHappyBatteryColor);
            }
            canvas.drawRect(r2, mPaint);
    
            // 3.    
            RectF r3 = new RectF(width / 2f - headWidth / 2f,
                    getPaddingTop(),
                    width / 2f + headWidth / 2f,
                    getPaddingTop() + headHeight);
            mPaint.setColor(mStrokeColor);
            canvas.drawRect(r3, mPaint);
    
            // 4.       
            if (mShowPercent) {
                mPaint.setAntiAlias(true);
                mPaint.setStyle(Paint.Style.FILL);
                mPaint.setTextAlign(Paint.Align.CENTER);
                mPaint.setTextSize(mPercentSize);
                mPaint.setColor(mPercentColor);
                mPaint.setStrokeWidth(1);
                String text = String.valueOf(mPower);
                canvas.drawText(text,
                        width / 2f,
                        height / 2f + (mPaint.getFontMetrics().bottom - mPaint.getFontMetrics().top) / 2 - mPaint.getFontMetrics().bottom,
                        mPaint);
            }
        }
    
    }
    

    テスト
  • レイアウトファイルにコード
  • を追加する
        <com.bottle.app.widget.BatteryView
            android:id="@+id/batteryView3"
            android:layout_width="@dimen/dp_49"
            android:layout_height="@dimen/dp_80"
            android:padding="@dimen/dp_2"
            app:batteryShowPercent="true"
            app:batteryPower="100"
            app:batteryColor="@android:color/black"
            app:batteryOrientation="vertical" />
    
  • は、Activityにおいてインスタンス化された後、電力量変更時にメソッドを呼び出して電力量値
  • を変更する.
    private Runnable mAction = new Runnable() {
            @Override
            public void run() {
                int pow = power++ % 100;
                mBatteryView.setPower(pow);
                mBatteryView.postDelayed(mAction, 100);
            }
        };
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mBatteryView = findViewById(R.id.batteryView);
            mBatteryView.post(mAction);
        }
    
    

    総括と思考
    実装中に注意すべき点は次のとおりです.
  • paddingを考慮しなければならない.そうしないと、ユーザーがpaddingを設定すると左上隅にしか表示されない.
  • 文字を描くときはペイントで文字の幅を計算します.そうしないと劇中にはできません.
  • 必要に応じて、どのような属性が必要かを考慮し、外観をよりよくカスタマイズするには、より多くのことを考慮します.

  • 不足:
  • はフィレットを実現していない.
  • は充電中のアニメーションを提供していません.呼び出し者が自分でアニメーションを書く必要があります.

  • リファレンス
    AndroidカスタムバッテリーコントロールAndroidカスタムView全解