巧用 Drawable 之實現一個最簡單的自定義電池圖示
在 Android 中自定義一個電池圖示,一般是採用自定義 View,在 onDraw 中採用 Canvas 去繪製 Bitmap 或者各種幾何圖形。但是自定義 View 對初學者來說可能會有一點難度,那麼有沒有更簡單的辦法來實現自定義電池圖示呢?
實現電池圖示 Drawable
我們來分析下繪製一個電池圖示我們需要做些什麼?
如圖所示,電池圖示可看成有三種狀態,空的,滿的,介於空和滿的。那我們就可以這麼做,先繪製一個空的,再根據電量繪製一個半滿的。我們知道 Drawable 有很多子類,LayerDrawable 可以用來繪製多個圖層,正好是我們需要的,另外繪製一半的可以採用 ClipDrawable。
ClipDrawable 在 draw 方法中會通過 Canvas#clipRect(Rect rect)
方法去裁剪畫布。ClipDrawable 可以通過 clipOrientation 來指定裁剪的方法為 horizontal 還是 vertical,而且還可以通過 gravity 屬性來指定從哪邊開始裁剪。
瞭解這些之後我們就可以著手寫 drawable 了,在 /res/drawable 下新建一個 battery.xml 如下:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- 空的電池 -->
<item>
<bitmap android:src="@drawable/battery_empty" />
<!-- 裁剪滿的電池圖示 -->
<item android:id="@+id/clip_drawable">
<clip
android:clipOrientation="horizontal"
android:drawable="@drawable/battery_full"
android:gravity="left" />
</item>
</layer-list>
上面兩個圖層最終組成我們想要的電池圖示。當然,我們還需要將 battery.xml 應用到我們的 View 中 。這裡我採用的是 ImageView,直接為 ImageView 指定一個android:src="@drawable/battery"
即可,也可以作為 View 的 background使用。
接下來還需要在 java 程式碼中指定 ClipDrawable 要裁剪的區域。程式碼如下:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ImageView imageBattery = (ImageView) findViewById(R.id.image_battery);
LayerDrawable layerDrawable = (LayerDrawable) imageBattery.getDrawable();
clipDrawable = (ClipDrawable) layerDrawable.findDrawableByLayerId(R.id.clip_drawable);
clipDrawable.setLevel(level);
}
LayerDrawable 中有個 findDrawableByLayerId(int id)
方法,可以找到指定 id 的 Drawable。有點類似於 View 中的 findViewById(int id)
方法。另外 ClipDrawable#setLevel(int level)
,引數 level 的取值範圍是 0-10000,表示要裁剪 Drawable 多大的範圍。
到這裡我們已經基本實現了自定義電池圖示。不過我們還沒有給定真實的電量值。
獲取手機電量
獲取手機電量只需註冊一個廣播即可,當手機電量改變時,我們就能在廣播中收到訊息。直接看程式碼:
public class MainActivity extends Activity {
@Override
protected void onResume() {
super.onResume();
IntentFilter intentFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
registerReceiver(batteryChangedReceiver, intentFilter);
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(batteryChangedReceiver);
}
// 電量變化廣播
private BroadcastReceiver batteryChangedReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
int level = intent.getIntExtra("level", 0);
int scale = intent.getIntExtra("scale", 100);
// 0 - 100
int power = level * 100 / scale;
// setLevel(int level): level 的範圍是 0 -10000
clipDrawable.setLevel(power * 100);
}
}
}
}
至此自定義電池圖示就完成的差不多了。不過細心的童鞋可能會發現,電量還沒滿,比如 90% 的時候電池圖示已經顯示是滿的了。這是因為電量顯示的區域只有中間某一塊,而不是整個圖示,如果要求比較高,我們還需要寫給方法去精確的計算裁剪的區域。
// 根據自己的電池圖示精確計算裁剪區域
private int calculateLevel(int progress) {
int leftOffest = Utils.dip2px(this, 2);
int powerLength = Utils.dip2px(this, 26.5f);// 40 px in hdpi
int totalLength = Utils.dip2px(this, 32.5f);// 49 px in hdpi
int level = (leftOffest + powerLength * progress / 100) * 10000 / totalLength;
return level;
}
結合圖片看程式碼:
這些值我們可以通過ps的標尺或者其他軟體來獲取。同時還要注意圖片放在哪個資料夾,轉換成 mdpi 下畫素值,作為 dp 單位。比如我把圖片放在 hdpi,圖片的實際寬度(totalLength)為 49px,那麼在 mdpi 大約為 32.5px,32.5 即為我們的 dp值。
dp 轉 px 的方法:
public class Utils {
public static int px2dip(Context context, float pxValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
public static int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
}
修改 onReceive 中的clipDrawable.setLevel(power * 100)
為 clipDrawable.setLevel(calculateLevel(power))
到這裡整個自定義電池圖示就全部完成了,如果需要顯示充電狀態,可以通過 Handler 配合屬性動畫去完成。這不是本節的重點,詳見原始碼。
相關推薦
巧用 Drawable 之實現一個最簡單的自定義電池圖示
在 Android 中自定義一個電池圖示,一般是採用自定義 View,在 onDraw 中採用 Canvas 去繪製 Bitmap 或者各種幾何圖形。但是自定義 View 對初學者來說可能會有一點難度,那麼有沒有更簡單的辦法來實現自定義電池圖示呢? 實現電
Android之——史上最簡單自定義開關按鈕的實現
很多時候,我們在很多無論是Android還是IOS的APP中都會遇到這樣的一種效果,有一個按鈕,我們點選一下,便會滑動一下,一會顯示“開”,一會顯示“關”,這便是開關按鈕了,比如:很多Android手機的設定功能裡,就有很多功能是用開關按鈕實現的,那麼這些開關按鈕時如何實
javaWeb之寫一個最簡單的servlet
tran oid w3c write 分享 瀏覽器 servle code mapping 1. 創建一個類servletTest2 繼承HttpServlet類。 public class servletTest2 extends HttpServlet {
300行ABAP代碼實現一個最簡單的區塊鏈原型
指向 repo 方法調用 輸入參數 transacti ui控件 挖礦 太多的 work 不知從什麽時候起,區塊鏈在網上一下子就火了。 這裏Jerry就不班門弄斧了,網上有太多的區塊鏈介紹文章。我的這篇文章沒有任何高大上的術語,就是300行ABAP代碼,實現一個最簡單的區
java實現一個最簡單的tomcat服務
連接數 accep print tex soc ins udp web服務 reply 1.如何啟動? main方法是程序的入口,tomcat也不例外,查看tomcat源碼,發現main是在Bootstrap 類中的; 2.如何建立連接? 要通訊,必須要建議so
python只使用Queue和Thread自己實現一個最簡單的執行緒池
我的思路就是就是寫一個TifCutting類繼承自Thread,這個類裡有個屬性Queue;有一個addTask新增任務的方法,這個方法是把需要執行的函式放到Queue裡;因為繼承自Thread類,一定有一個重寫的run方法,這個方法是從自己的Queue屬性裡
Python實現一個最簡單的MapReduce程式設計模型WordCount
MapReduce程式設計模型: Map:對映過程 Reduce:合併過程 import operator from functools import reduce # 需要處理的資料 lst = [ "Tom", "Jack",
實現一個最簡單的flask應用程式
首先先將flask包匯入,建立flask物件,然後使用flask路由器指定網址和控制器。最後使用程式入口將flask應用啟動,port引數用來調整埠號,flask模組預設埠號為5000 程式碼如下: from flask import Flask app = Flask(_
live555 實現一個最簡單的RTSP伺服器
用live555中的庫寫了一個最簡單的RTSPServer程式,僅用於學習目的。從下例的程式碼中,可以清析的明白RTSPServer的函式呼叫流程。[cpp] view plaincopyprint?#include <BasicUsageEnvironment.h
用java去解析一個最簡單的XML檔案
此處僅僅是去解析最基本的XML檔案,XML檔案如下: <Books> <Book> <Name>Java入門</Name> <Price>30.00</Price>
使用Java實現一個最簡單的Web Server
Hello Web Server Web Server沒有你想象的那麼難實現(當然要實現一個好的Java Web Server還是很有難度的)。你只要明白基本的HTTP協議,TCP程式設計和IO知識。當然,你也要會最簡單的HTML程式碼。 我們先來一個屌絲版
HTML5用audio標籤做一個最簡單的音訊播放器
在做系統的時候,要求做一個音訊播放器,就在網上查找了一些資料,發現這樣的資料還是很千篇一律的,EasyUI框架並沒有給我們一個音訊播放器的功能,在bootstrap上有,但是也是結合html5來寫的,因此,我們在這裡就用純的html5血一個音訊播放器,如何播放本地的音訊。
用spring boot搭建一個最簡單的使用者登入介面,其艱難歷程!
目前的Java專案中,最基本的包括:controller層、service層、dao層,當然還用entity實體層。 controller層,顧名思義,就是控制器,控制各個層面的動作。 service層,其中寫了具體的方法,具體怎樣的實現,就在其中寫著。 dao層
C語言實現一個最簡單的佇列
1、佇列.h #include<stdio.h> #include<stdlib.h> #define N 100 //定義佇列最大多少個 #define datatype char //定義佇列的資料型別 struct
用struct模組實現python socket收發自定義TCP包
最近跳槽到西安一家機器人公司,我們的產品屬於教育機器人的範疇,為了增強客戶吸引力,引進了一個智慧家居公司的產品API介面,讓機器人來操作智慧家居 該公司的智慧家居API是自定義TCP包,即直接在TCP頭後面寫自定義資料結構: 客戶端請求下載 傢俱資料庫 的格式 命令字(4
【Android進階】如何寫一個很屌的動畫(1)---先實現一個簡易的自定義動畫框架
class MyView extends View { public void onDraw(Canvas canvas) { super.onDraw(canvas); invalidate(); } } 這樣一來,View每次繪製都是觸發下一次繪製,不過
巧用Drawable 實現Android UI 元素間距效果
purple 固定 展示 .com otto 技巧 log contain dev 源文地址: 巧用Drawable 實現Android UI 元素間距效果 在大部分的移動UI或者Web UI都是基於網格概念而設計的。這種網格一般都是有一些對其的方塊組成,然後
Behavior Tree 用 Lua 實現一個最簡行為樹
urn ret pri end put true for 行為樹 一個 1 local SELECTOR = 1 2 local SEQUENCE = 2 3 local CONDITION = 3 4 local ACTION = 4 5 6 loca
寫一個Python通過select實現的最簡單的web框架
127.0.0.1 log put lec func select odi block pos 1 #!/usr/bin/env python 2 # -*- coding: utf-8 -*- 3 4 import socket 5 import selec
2018.3.29學習總結之如何運行一個最簡單的Servlet程序
ati get png aid 父類 eclips 網上 自己 nco 1,我編寫了我的第一個Servlet程序。HelloServlet 繼承自HttpServlet。因此需要導入javax.servlet開頭的一系列包,那麽這些包來自哪裏呢?答案是Tomcat安裝目錄下