cbd93c42-45e2-4d50-89b0-6f764a3e5b68

 

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; // 默认电量
 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         // 初始化电池边框画笔
 54         batteryPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
 55         batteryPaint.setStyle(Paint.Style.STROKE);
 56         batteryPaint.setStrokeWidth(borderWidth);
 57         batteryPaint.setColor(borderColor);
 58         
 59         // 初始化电量填充画笔
 60         levelPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
 61         levelPaint.setStyle(Paint.Style.FILL);
 62         levelPaint.setColor(batteryColor);
 63         
 64         // 初始化文字画笔
 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         // 计算电池各部分尺寸
 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     // 设置电量百分比
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         // 根据电量改变颜色
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 }
View Code

 

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>
View Code

 

3. 布局文件使用示例

单独电池显示 (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     <!-- 当前电量显示 -->
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="当前电量: 85%"
52         android:textSize="18sp"
53         android:textStyle="bold" />
54 
55 </LinearLayout>
View Code

 

集成到监控界面

在监控界面中替换电量显示部分:

 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>
View Code

 

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%% (%s)", level, status));
62     }
63 }
View Code

 

5. 在监控主界面中使用

在您的监控主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         // 模拟从后端获取电量数据
19         updateBatteryFromServer();
20     }
21     
22     private void updateBatteryFromServer() {
23         // 这里替换为实际的后端API调用
24         int batteryLevel = 85; // 从后端获取的实际电量
25         batteryView.setBatteryLevel(batteryLevel);
26     }
27     
28     // 刷新电量数据
29     private void refreshBatteryData() {
30         // 调用后端API获取最新电量
31         new Thread(() -> {
32             // 模拟网络请求
33             try {
34                 Thread.sleep(1000);
35                 int newLevel = (int) (Math.random() * 100); // 模拟数据变化
36                 
37                 runOnUiThread(() -> {
38                     batteryView.setBatteryLevel(newLevel);
39                     Toast.makeText(this, "电量数据已更新", Toast.LENGTH_SHORT).show();
40                 });
41             } catch (InterruptedException e) {
42                 e.printStackTrace();
43             }
44         }).start();
45     }
46 }
View Code

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>
View Code
posted on 2025-11-03 10:35  江渔湖  阅读(5)  评论(0)    收藏  举报