
1. 自定義電池視圖 (BatteryView.java)
1 package com.example.agvmonitor.view; 2 3 import android.content.Context; 4 import android.content.res.TypedArray; 5 import android.graphics.Canvas; 6 import android.graphics.Color; 7 import android.graphics.Paint; 8 import android.graphics.RectF; 9 import android.util.AttributeSet; 10 import android.view.View; 11 import com.example.agvmonitor.R; 12 13 public class BatteryView extends View { 14 private Paint batteryPaint; 15 private Paint textPaint; 16 private Paint levelPaint; 17 18 private int batteryLevel = 85; // 默認(rèn)電量 19 private int batteryColor = Color.GREEN; 20 private int borderColor = Color.BLACK; 21 private int textColor = Color.GREEN; 22 23 private float borderWidth = 3f; 24 private float textSize = 24f; 25 26 public BatteryView(Context context) { 27 super(context); 28 init(null); 29 } 30 31 public BatteryView(Context context, AttributeSet attrs) { 32 super(context, attrs); 33 init(attrs); 34 } 35 36 public BatteryView(Context context, AttributeSet attrs, int defStyleAttr) { 37 super(context, attrs, defStyleAttr); 38 init(attrs); 39 } 40 41 private void init(AttributeSet attrs) { 42 // 讀取自定義屬性 43 if (attrs != null) { 44 TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.BatteryView); 45 batteryLevel = a.getInt(R.styleable.BatteryView_batteryLevel, 85); 46 batteryColor = a.getColor(R.styleable.BatteryView_batteryColor, Color.GREEN); 47 borderColor = a.getColor(R.styleable.BatteryView_borderColor, Color.BLACK); 48 textColor = a.getColor(R.styleable.BatteryView_textColor, Color.GREEN); 49 textSize = a.getDimension(R.styleable.BatteryView_textSize, 24f); 50 a.recycle(); 51 } 52 53 // 初始化電池邊框畫(huà)筆 54 batteryPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 55 batteryPaint.setStyle(Paint.Style.STROKE); 56 batteryPaint.setStrokeWidth(borderWidth); 57 batteryPaint.setColor(borderColor); 58 59 // 初始化電量填充畫(huà)筆 60 levelPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 61 levelPaint.setStyle(Paint.Style.FILL); 62 levelPaint.setColor(batteryColor); 63 64 // 初始化文字畫(huà)筆 65 textPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 66 textPaint.setStyle(Paint.Style.FILL); 67 textPaint.setColor(textColor); 68 textPaint.setTextSize(textSize); 69 textPaint.setTextAlign(Paint.Align.CENTER); 70 } 71 72 @Override 73 protected void onDraw(Canvas canvas) { 74 super.onDraw(canvas); 75 76 int width = getWidth(); 77 int height = getHeight(); 78 int padding = 10; 79 80 // 計(jì)算電池各部分尺寸 81 float batteryWidth = width * 0.3f; 82 float batteryHeight = batteryWidth * 0.6f; 83 float batteryTop = (height - batteryHeight) / 2; 84 float batteryLeft = (width - batteryWidth) / 2; 85 float batteryRight = batteryLeft + batteryWidth; 86 float batteryBottom = batteryTop + batteryHeight; 87 88 // 電池頭部(正極)尺寸 89 float headWidth = batteryWidth * 0.15f; 90 float headHeight = batteryHeight * 0.3f; 91 float headLeft = batteryRight; 92 float headTop = batteryTop + (batteryHeight - headHeight) / 2; 93 float headRight = headLeft + headWidth; 94 float headBottom = headTop + headHeight; 95 96 // 繪制電池主體 97 RectF batteryBody = new RectF(batteryLeft, batteryTop, batteryRight, batteryBottom); 98 canvas.drawRect(batteryBody, batteryPaint); 99 100 // 繪制電池頭部 101 RectF batteryHead = new RectF(headLeft, headTop, headRight, headBottom); 102 canvas.drawRect(batteryHead, levelPaint); 103 104 // 繪制電量填充 105 float levelWidth = (batteryWidth - 2 * borderWidth) * batteryLevel / 100f; 106 float levelLeft = batteryLeft + borderWidth; 107 float levelTop = batteryTop + borderWidth; 108 float levelRight = levelLeft + levelWidth; 109 float levelBottom = batteryBottom - borderWidth; 110 111 RectF batteryLevelRect = new RectF(levelLeft, levelTop, levelRight, levelBottom); 112 canvas.drawRect(batteryLevelRect, levelPaint); 113 114 // 繪制百分比文字 115 String percentage = batteryLevel + "%"; 116 float textX = batteryRight + (width - batteryRight) / 2 + headWidth; 117 float textY = height / 2f - (textPaint.descent() + textPaint.ascent()) / 2; 118 119 canvas.drawText(percentage, textX, textY, textPaint); 120 } 121 122 @Override 123 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 124 int desiredWidth = 200; 125 int desiredHeight = 100; 126 127 int widthMode = MeasureSpec.getMode(widthMeasureSpec); 128 int widthSize = MeasureSpec.getSize(widthMeasureSpec); 129 int heightMode = MeasureSpec.getMode(heightMeasureSpec); 130 int heightSize = MeasureSpec.getSize(heightMeasureSpec); 131 132 int width, height; 133 134 if (widthMode == MeasureSpec.EXACTLY) { 135 width = widthSize; 136 } else if (widthMode == MeasureSpec.AT_MOST) { 137 width = Math.min(desiredWidth, widthSize); 138 } else { 139 width = desiredWidth; 140 } 141 142 if (heightMode == MeasureSpec.EXACTLY) { 143 height = heightSize; 144 } else if (heightMode == MeasureSpec.AT_MOST) { 145 height = Math.min(desiredHeight, heightSize); 146 } else { 147 height = desiredHeight; 148 } 149 150 setMeasuredDimension(width, height); 151 } 152 153 // 設(shè)置電量百分比 154 public void setBatteryLevel(int level) { 155 if (level < 0) level = 0; 156 if (level > 100) level = 100; 157 158 this.batteryLevel = level; 159 160 // 根據(jù)電量改變顏色 161 if (level > 70) { 162 batteryColor = Color.GREEN; 163 textColor = Color.GREEN; 164 } else if (level > 20) { 165 batteryColor = Color.YELLOW; 166 textColor = Color.YELLOW; 167 } else { 168 batteryColor = Color.RED; 169 textColor = Color.RED; 170 } 171 172 levelPaint.setColor(batteryColor); 173 textPaint.setColor(textColor); 174 175 invalidate(); // 重繪視圖 176 } 177 178 public int getBatteryLevel() { 179 return batteryLevel; 180 } 181 }
2. 自定義屬性定義 (res/values/attrs.xml)
1 <?xml version="1.0" encoding="utf-8"?> 2 <resources> 3 <declare-styleable name="BatteryView"> 4 <attr name="batteryLevel" format="integer" /> 5 <attr name="batteryColor" format="color" /> 6 <attr name="borderColor" format="color" /> 7 <attr name="textColor" format="color" /> 8 <attr name="textSize" format="dimension" /> 9 </declare-styleable> 10 </resources>
3. 布局文件使用示例
單獨(dú)電池顯示 (activity_battery.xml)
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:app="http://schemas.android.com/apk/res/android" 4 xmlns:tools="http://schemas.android.com/tools" 5 android:layout_width="match_parent" 6 android:layout_height="match_parent" 7 android:orientation="vertical" 8 android:gravity="center" 9 android:padding="20dp" 10 android:background="#FFFFFF" 11 tools:context=".BatteryActivity"> 12 13 <!-- 自定義電池視圖 --> 14 <com.example.agvmonitor.view.BatteryView 15 android:id="@+id/batteryView" 16 android:layout_width="200dp" 17 android:layout_height="100dp" 18 app:batteryLevel="85" 19 app:batteryColor="#4CAF50" 20 app:borderColor="#333333" 21 app:textColor="#4CAF50" 22 app:textSize="24sp" /> 23 24 <!-- 控制按鈕 --> 25 <LinearLayout 26 android:layout_width="wrap_content" 27 android:layout_height="wrap_content" 28 android:orientation="horizontal" 29 android:layout_marginTop="30dp"> 30 31 <Button 32 android:id="@+id/btnDecrease" 33 android:layout_width="wrap_content" 34 android:layout_height="wrap_content" 35 android:text="-10%" 36 android:layout_marginEnd="10dp" /> 37 38 <Button 39 android:id="@+id/btnIncrease" 40 android:layout_width="wrap_content" 41 android:layout_height="wrap_content" 42 android:text="+10%" /> 43 </LinearLayout> 44 45 <!-- 當(dāng)前電量顯示 --> 46 <TextView 47 android:id="@+id/tvBatteryInfo" 48 android:layout_width="wrap_content" 49 android:layout_height="wrap_content" 50 android:layout_marginTop="20dp" 51 android:text="當(dāng)前電量: 85%" 52 android:textSize="18sp" 53 android:textStyle="bold" /> 54 55 </LinearLayout>
集成到監(jiān)控界面
在監(jiān)控界面中替換電量顯示部分:
1 <LinearLayout 2 android:layout_width="match_parent" 3 android:layout_height="wrap_content" 4 android:orientation="horizontal" 5 android:gravity="center_vertical" 6 android:layout_marginTop="16dp" 7 android:paddingTop="16dp" 8 android:background="@drawable/section_divider"> 9 10 <TextView 11 android:layout_width="wrap_content" 12 android:layout_height="wrap_content" 13 android:text="電量:" 14 android:textColor="#666" 15 android:textSize="16sp" /> 16 17 <!-- 使用自定義電池視圖 --> 18 <com.example.agvmonitor.view.BatteryView 19 android:id="@+id/batteryView" 20 android:layout_width="120dp" 21 android:layout_height="60dp" 22 android:layout_marginStart="8dp" 23 app:batteryLevel="85" 24 app:batteryColor="#4CAF50" 25 app:borderColor="#666666" 26 app:textColor="#4CAF50" 27 app:textSize="16sp" /> 28 29 <TextView 30 android:layout_width="0dp" 31 android:layout_height="wrap_content" 32 android:layout_weight="1" 33 android:text="更新:" 34 android:textColor="#666" 35 android:gravity="end" /> 36 37 <TextView 38 android:id="@+id/tv_update_time" 39 android:layout_width="wrap_content" 40 android:layout_height="wrap_content" 41 android:text="0秒前" 42 android:textStyle="bold" /> 43 </LinearLayout>
4. Activity代碼 (BatteryActivity.java)
1 package com.example.agvmonitor; 2 3 import android.os.Bundle; 4 import android.widget.Button; 5 import android.widget.TextView; 6 import androidx.appcompat.app.AppCompatActivity; 7 import com.example.agvmonitor.view.BatteryView; 8 9 public class BatteryActivity extends AppCompatActivity { 10 11 private BatteryView batteryView; 12 private TextView tvBatteryInfo; 13 private Button btnDecrease, btnIncrease; 14 15 @Override 16 protected void onCreate(Bundle savedInstanceState) { 17 super.onCreate(savedInstanceState); 18 setContentView(R.layout.activity_battery); 19 20 initViews(); 21 setupClickListeners(); 22 } 23 24 private void initViews() { 25 batteryView = findViewById(R.id.batteryView); 26 tvBatteryInfo = findViewById(R.id.tvBatteryInfo); 27 btnDecrease = findViewById(R.id.btnDecrease); 28 btnIncrease = findViewById(R.id.btnIncrease); 29 30 updateBatteryInfo(); 31 } 32 33 private void setupClickListeners() { 34 btnDecrease.setOnClickListener(v -> { 35 int currentLevel = batteryView.getBatteryLevel(); 36 int newLevel = Math.max(0, currentLevel - 10); 37 batteryView.setBatteryLevel(newLevel); 38 updateBatteryInfo(); 39 }); 40 41 btnIncrease.setOnClickListener(v -> { 42 int currentLevel = batteryView.getBatteryLevel(); 43 int newLevel = Math.min(100, currentLevel + 10); 44 batteryView.setBatteryLevel(newLevel); 45 updateBatteryInfo(); 46 }); 47 } 48 49 private void updateBatteryInfo() { 50 int level = batteryView.getBatteryLevel(); 51 String status; 52 53 if (level > 70) { 54 status = "電量充足"; 55 } else if (level > 20) { 56 status = "電量適中"; 57 } else { 58 status = "電量不足"; 59 } 60 61 tvBatteryInfo.setText(String.format("當(dāng)前電量: %d%% (%s)", level, status)); 62 } 63 }
5. 在監(jiān)控主界面中使用
在您的監(jiān)控主Activity中集成電池視圖:
1 public class MainActivity extends AppCompatActivity { 2 private BatteryView batteryView; 3 // ... 其他變量 4 5 @Override 6 protected void onCreate(Bundle savedInstanceState) { 7 super.onCreate(savedInstanceState); 8 setContentView(R.layout.activity_main); 9 10 initViews(); 11 // ... 其他初始化代碼 12 } 13 14 private void initViews() { 15 batteryView = findViewById(R.id.batteryView); 16 // ... 其他視圖初始化 17 18 // 模擬從后端獲取電量數(shù)據(jù) 19 updateBatteryFromServer(); 20 } 21 22 private void updateBatteryFromServer() { 23 // 這里替換為實(shí)際的后端API調(diào)用 24 int batteryLevel = 85; // 從后端獲取的實(shí)際電量 25 batteryView.setBatteryLevel(batteryLevel); 26 } 27 28 // 刷新電量數(shù)據(jù) 29 private void refreshBatteryData() { 30 // 調(diào)用后端API獲取最新電量 31 new Thread(() -> { 32 // 模擬網(wǎng)絡(luò)請(qǐng)求 33 try { 34 Thread.sleep(1000); 35 int newLevel = (int) (Math.random() * 100); // 模擬數(shù)據(jù)變化 36 37 runOnUiThread(() -> { 38 batteryView.setBatteryLevel(newLevel); 39 Toast.makeText(this, "電量數(shù)據(jù)已更新", Toast.LENGTH_SHORT).show(); 40 }); 41 } catch (InterruptedException e) { 42 e.printStackTrace(); 43 } 44 }).start(); 45 } 46 }
6. 樣式和顏色定義 (res/values/colors.xml)
1 <?xml version="1.0" encoding="utf-8"?> 2 <resources> 3 <!-- 電池顏色 --> 4 <color name="battery_high">#4CAF50</color> <!-- 綠色,電量充足 --> 5 <color name="battery_medium">#FFC107</color> <!-- 黃色,電量適中 --> 6 <color name="battery_low">#F44336</color> <!-- 紅色,電量不足 --> 7 8 <!-- 文字顏色 --> 9 <color name="text_primary">#333333</color> 10 <color name="text_secondary">#666666</color> 11 12 <!-- 背景色 --> 13 <color name="background_white">#FFFFFF</color> 14 </resources>
浙公網(wǎng)安備 33010602011771號(hào)