網站首頁 編程語言 正文
所謂游戲,本質就是提供更逼真的、能模擬某種環境的用戶界面,并根據某種規則來響應用戶操作。為了提供更逼真的用戶界面,需要借助于圖形、圖像處理。
從廣義的角度來看,Android應用中的圖片不僅包括*.png、*.jpg、 *.gif等各種格式的位圖,也包括使用XML資源文件定義的各種Drawable對象。
1.使用Drawable對象
為Android應用增加了Drawable資源之后,Android SDK會為這份資源在R清單文件中創建一個索引項:R.drawable.file_name。
獲取方式:
- 在XML資源文件中通過@drawablelfile_name訪問該Drawable對象
- 在Java代碼中通過R.drawable.file_name訪問該Drawable對象。
需要指出的是,R.drawable.file_name是一個int類型的常量,它只代表Drawable對象的ID,如果Java程序中需要獲取實際的Drawable對象,則可調用Resources的getDrawable (int id)方法來實現。
2.Bitmap和BitmapFactory
Bitmap代表一個位圖,BitmapDrawable里封裝的圖片就是一個Bitmap對象。
兩者之間的轉換:
//把一個Bitmap對象包裝成BitmapDrawable對象
BitmapDrawable drawable = new BitmapDrawable (bitmap) ;
如果需要獲取BitmapDrawable所包裝的Bitmap對象,則可調用BitmapDrawable的getBitmap ()方法,如下面的代碼所示:
//獲取BitmapDrawable所包裝的Bitmap 對象
Bitmap bitmap = drawable.getBitmap();
新建Bitmap對象的一些方法:
- createBitmap (Bitmap source,int x, int y,int width,int height):從源位圖source的指定坐標點(給定x、y)開始,從中“挖取"寬width、高height的一塊出來,創建新的Bitmap對象。
- createScaledBitmap (Bitmap src, int dstWidth,int dstHeight,boolean filter) :對源位圖src進行縮放,縮放成寬dstWidth、高dstHeight的新位圖。 filter是過濾器。
- createBitmap (int width,int height,Bitmap.Config config):創建一個寬width、高height的新位圖。
- createBitmap (Bitmap source,int x, int y, int width,int height,Matrixm, boolean filter):從源位圖source 的指定坐標點(給定x、y)開始,從中“挖取"寬 width、高height的一塊出來,創建新的Bitmap對象,并按Matrix指定的規則進行變換。
Bitmap.Config類,在Bitmap類里createBitmap(int width, int height, Bitmap.Config config)方法里會用到,打開個這個類一看 :枚舉變量
public static final Bitmap.Config ALPHA_8
public static final Bitmap.Config ARGB_4444
public static final Bitmap.Config ARGB_8888
public static final Bitmap.Config RGB_565
BitmapFactory是一個工具類,它提供了大量的方法,這些方法可用于從不同的數據源來解析、創建Bitmap對象。BitmapFactory包含了如下方法。
- decodeByteArray (byte[]data,int offset,int length)︰從指定字節數組的offset位置開始,將長度為length的字節數據解析成Bitmap對象。
- decodeFile (String pathName) :從pathName指定的文件中解析、創建Bitmap對象。
- decodeFileDescriptor (FileDescriptor fd):用于從FileDescriptor對應的文件中解析、創建Bitmap對象。
- decodeResource (Resources res,int id) :用于根據給定的資源ID從指定資源中解析、創建Bitmap對象。
- decodeStream (InputStream is):用于從指定輸入流中解析、創建Bitmap對象。
對于創建而言,對應的就是回收了。如果系統不停的去解析、創建Bitmap對象,可能由于創建的Bitmap所占用的內存還沒回收,而導致OOM。
- boolean isRecycled ():返回該Bitmap對象是否已被回收。
- void recycle () :強制一個Bitmap對象立即回收自己。
如果Android應用需要訪問其他存儲路徑(比如SD卡)里的圖片,那么都需要借助于BitmapFactory來解析、創建Bitmap對象。
2.1 例子
下面開發一個查看/assets/目錄下圖片的圖片查看器,當用戶單擊該按鈕時程序會自動去搜尋/assets/目錄下的下—張圖片。此處不再給出界面布局代碼,該程序的代碼如下。
public class Test4Activity extends Activity {
String[] images = null;
AssetManager assets = null;
int currentImg = 0;
private ImageView image;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test4_acitvity);
image = findViewById(R.id.test4_iv);
Button next = findViewById(R.id.test4_bt_next);
try {
assets = getAssets();
//獲取assets目錄目錄下的所有文件
images =assets.list("");
} catch (IOException e) {
e.printStackTrace();
}
//按鈕事件
next.setOnClickListener(view -> {
//如果發生數組越界
if(currentImg >= images.length){
currentImg = 0;
}
//找到下一個圖片文件
while (!images[currentImg].endsWith(".png")&&!images[currentImg].endsWith(".jpg")
&&!images[currentImg].endsWith(".gif")){
currentImg++;
//如果已經發生了數組越界
if(currentImg >= images.length){
currentImg = 0;
}
}
InputStream assetFile = null;
try {
//打開指定資源對應的輸入流
assetFile = assets.open(images[currentImg++]);
} catch (IOException e) {
e.printStackTrace();
}
BitmapDrawable bitmapDrawable = (BitmapDrawable) image.getDrawable();
//如果圖片還未回收,先強制回收該圖片
if(bitmapDrawable != null&&!bitmapDrawable.getBitmap().isRecycled()){
bitmapDrawable.getBitmap().recycle();
}
//改變ImageView顯示圖片
//調用了BitmapFactory從指定輸入流解析并創建Bitmap
image.setImageBitmap(BitmapFactory.decodeStream(assetFile));
});
}
}
2.2 額外知識點(assets)
系統為每一個新設計的程序提供了/assets文件夾,這個文件夾保存的文件能夠打包在程序里。
/res和/assets的不同點是,android不為/assets下的文件生成ID。假設使用/assets下的文件,須要指定文件的路徑和文件名稱。怎樣訪問/assets下的內容?
例如,假設在assets目錄下有一個名稱為filename的文件,那么就可以使用以下代碼來訪問它:
AssetManager assset= getAssets();
InputStream is = assset.open("filename");
2.3 代碼更嚴謹
1.發現這代碼一點黃色都沒有,證明很嚴謹。
注意為什么button放在了里面,而imageView放在了外面。
將button放在外面會有Field can be converted to a local variable的警告,意思是檢測到這個變量可以使用局部變量替換,建議刪除并寫成局部變量。就是其他地方也沒有使用到它,沒有必要聲明成成員變量。
2.設計到數組訪問,一定要防止其數組越界。上面還搞了兩個。
assetFile = assets.open(images[currentImg++]);
此時進入到open的必定是圖片資源的name,用了之后currentImg自加,探索下一個圖片。第一個防止其數組越界的判斷就是防這里的;第二是對應著判斷不是圖片資源的++。但是這個代碼還有問題:假如里面有資源,但是都不是圖片資源。那就會進入死循環
3.在顯示圖片之前,一定要釋放之前的Bitmap,以免OOM
釋放的判斷的條件是使用Bitmap的封裝類。
3.Android9新增的ImageDecoder
Android 9 引入了 ImageDecoder、OnHanderDecodedListener 等API,提供了更強大的圖片解碼支持,可以解碼png、jpeg等靜態圖片和gif、webp等動畫圖片。另外。還新增了支持HEIF格式:
HEIF格式:這種壓縮格式據有超高的壓縮比例,相比JPEG,可以壓縮到其一半大小,而且可以保證其近似的圖片質量。
當使用 ImageDecoder 解碼gif、webp等動畫圖片時,會返回一個AnimatedImageDrawable對象,調用AnimatedImageDrawable對象的start()方法即可開始執行動畫。
ImageDecoder 解碼圖片的方式:
- 調用 ImageDecoder 的重載的 createSource 方法來創建 Source 對象。根據不同的圖片來源, createSource 方法有不同的重載模式。
- 調用ImageDecoder 的 decodeDrawabIe(Source) or decodeBitmap(Source)方法來讀取代表圖片的 Drawable或 Bitmap對象。
在第二步時,可以額外傳入一個OnHanderDecodedListener參數,該參數代表了監聽器,該監聽器要實現一個 onHanderDecoded(ImageDecoder,ImageInfo,Source)方法,可以對ImageDecoder進行額外的設置,也可以通過 ImageInfo 獲取被解碼圖片的信息。
3.1 例子
public class Test5Activity extends AppCompatActivity {
//說白了只有api 28 之后的才進的來
@RequiresApi(api = Build.VERSION_CODES.P)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test5);
//獲取對象
TextView textView = findViewById(R.id.test5_tv);
ImageView imageView = findViewById(R.id.test5_iv);
//創建 imageDecoder.Source對象
//第一步:
ImageDecoder.Source source = ImageDecoder.createSource(getResources(),R.drawable.viewgif);
try {
//第二步:執行decodeDrawable()方法獲取Drawable對象
@SuppressLint({"WrongThread", "SetTextI18n"})
Drawable drawable = ImageDecoder.decodeDrawable(source,(decoder, info, s) ->{
//通過 info 參數獲取被解碼圖片的信息
textView.setText("圖片的原始寬度:"+info.getSize().getWidth()+
"\n"+"圖片原始寬高"+info.getSize().getHeight());
//設置圖片解碼之后的縮放大小
decoder.setTargetSize(600,580);
});
imageView.setImageDrawable(drawable);
//如果drawable 是AnimatedImageDrawable的實例,則執行動畫
if(drawable instanceof AnimatedImageDrawable){
((AnimatedImageDrawable) drawable).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
與傳統的BitmapFactory相比,ImageDecoder 甚至可以解碼包含不完整或錯誤的圖片,如果希望顯示ImageDecoder解碼出錯之前的部分圖片,則可通過為 ImageDecoder沒置OnPartialImageListener監聽器來實現。例如如下代碼片段:
//先用Lambda 表達式作為OnHeaderDecodeListener監聽器
Drawable drawable = ImageDecoder.decodeDrawable(source,(decoder, info, s) ->{
//為ImageDecoder 設置 OnPartialImageListener 監聽器(Lambda 表達式)
decoder.setOnPartialImageListener(e->{
....
//return true 表明即使不能完整地解碼全部圖片也返回Drawable或Bitmap
return true;
});
});
原文鏈接:https://blog.csdn.net/indeedes/article/details/125196956
相關推薦
- 2022-12-12 Android?DataBinding類關系深入探究_Android
- 2022-04-21 python離散建模之感知器學習算法_python
- 2022-08-21 Python命令行庫click的具體使用_python
- 2022-06-19 python繪制餅圖和直方圖的方法_python
- 2022-05-16 C++實現圖書管理系統源碼_C 語言
- 2022-10-05 帶你深度走入C語言取整以及4種函數_C 語言
- 2022-10-21 使用nginx進行負載均衡的搭建全過程_nginx
- 2022-10-22 SQL?Server實現group_concat功能的詳細實例_MsSql
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支