? ? ? ?使用相機(jī)intent,我們就可以成功拍攝現(xiàn)場(chǎng)照片并保存了。
? ? ? ?有了照片,接下來就是找到并加載它,然后展示給用戶看。在南昌APP開發(fā)的技術(shù)實(shí)現(xiàn)上,這需要加載照片到大小合適的Bitmap對(duì)象中。要從文件生成Bitmap對(duì)象,我們需要BitmapFactory類:
? ? ? ?Bitmap bitmap = BitmapFactory.decodeFile(mPhotoFile.getPath());
? ? ? ?看到這里,有沒有感覺不對(duì)勁?肯定有的。問題在于:介紹Bitmap時(shí),我們提到“大小合適”。Bitmap是個(gè)簡(jiǎn)單對(duì)象,它只存儲(chǔ)實(shí)際像素?cái)?shù)據(jù)。也就是說,即使原始照片已壓縮過,但存入Bitmap對(duì)象時(shí),文件并不會(huì)同樣壓縮。因此,16萬像素24位已壓縮為5Mb大小的JPG照片文件,一旦載入Bitmap對(duì)象,就會(huì)立即膨脹至48Mb大?。?/span>
? ? ? ?這其實(shí)個(gè)問題是可以設(shè)法解決的,但需要手工縮放位圖照片。具體做法就是,首先確認(rèn)文件到底有多大,然后考慮按照給定區(qū)域大小合理縮放文件。最后,重新讀取縮放后的文件,創(chuàng)建Bitmap對(duì)象。
? ? ? ?創(chuàng)建名為PictureUtils.java的新類,并在其中添加getScaledBitmap(String, int, int)縮放方法,如下代碼清單所示。
? ? ? ?創(chuàng)建getScaledBitmap(...)方法(PictureUtils.java)
? ? ? ?public class PictureUtils {
? ? ? ?public static Bitmap getScaledBitmap(String path, int destWidth, int destHeight) {
? ? ? ?// Read in the dimensions of the image on disk
? ? ? ?BitmapFactory.Options options = new BitmapFactory.Options();
? ? ? ?options.inJustDecodeBounds = true;
? ? ? ?BitmapFactory.decodeFile(path, options);
? ? ? ?float srcWidth = options.outWidth;
? ? ? ?float srcHeight = options.outHeight;
?
? ? ? ?// Figure out how much to scale down by
? ? ? ?int inSampleSize = 1;
? ? ? ?if (srcHeight > destHeight || srcWidth > destWidth) {
? ? ? ?if (srcWidth > srcHeight) {
? ? ? ?inSampleSize = Math.round(srcHeight / destHeight);
? ? ? ?} else {
? ? ? ?inSampleSize = Math.round(srcWidth / destWidth);
? ? ? ?}
? ? ? ?}
? ? ? ?options = new BitmapFactory.Options();
? ? ? ?options.inSampleSize = inSampleSize;
? ? ? ?// Read in and create final bitmap
? ? ? ?return BitmapFactory.decodeFile(path, options);
? ? ? ?}
? ? ? ?}?
? ? ? ?上述方法中,inSampleSize值很關(guān)鍵。它決定著縮略圖像素的大小。假設(shè)這個(gè)值是1的話,就表明縮略圖和原始照片的水平像素大小一樣。如果是2的話,它們的水平像素比就是1∶2。因此,inSampleSize值為2時(shí),縮略圖的像素?cái)?shù)就是原始文件的四分之一。
? ? ? ?問題總是接踵而來,解決了縮放問題,又冒出了新問題:fragment剛啟動(dòng)時(shí),PhotoView
? ? ? ?究竟有多大無人知道。onCreate(...)、onStart()和onResume()方法啟動(dòng)后,才會(huì)有實(shí)例化布局出現(xiàn)。也就在此時(shí),顯示在屏幕上的視圖才會(huì)有大小尺寸。這也是出現(xiàn)新問題的原因。
? ? ? ?解決方案有兩個(gè):要么等布局實(shí)例化完成并顯示,要么干脆使用保守估算值。特定條件下,盡管估算比較主觀,但確實(shí)是一個(gè)切實(shí)可行的辦法。再添加一個(gè)getScaledBitmap(String,Activity)靜態(tài)Bitmap估算方法,如下代碼所示。
? ? ? ?編寫合理的縮放方法(PictureUtils.java)
? ? ? ?public class PictureUtils {
? ? ? ?public static Bitmap getScaledBitmap(String path, Activity activity) {
? ? ? ?Point size = new Point();
? ? ? ?activity.getWindowManager().getDefaultDisplay()
? ? ? ?.getSize(size);
? ? ? ?return getScaledBitmap(path, size.x, size.y);
? ? ? ?}
? ? ? ?...?
? ? ? ?該方法先確認(rèn)屏幕的尺寸,然后按此縮放圖像。這樣,就能保證載入的ImageView永遠(yuǎn)不會(huì)過大。看到?jīng)]有,無論如何,這是一個(gè)比較保守的估算有時(shí)就是能解決問題。
? ? ? ?接下來,為把Bitmap載入ImageView。在CrimeFragment.java中,添加刷新mPhotoView的方法,如下代碼清單所示。
? ? ? ?更新mPhotoView(CrimeFragment.java)
? ? ? ?...
? ? ? ?private String getCrimeReport() {
? ? ? ?...
? ? ? ?}
? ? ? ?private void updatePhotoView() {
? ? ? ?if (mPhotoFile == null || !mPhotoFile.exists()) {
? ? ? ?mPhotoView.setImageDrawable(null);
? ? ? ?} else {
? ? ? ?Bitmap bitmap = PictureUtils.getScaledBitmap(
? ? ? ?mPhotoFile.getPath(), getActivity());
? ? ? ?mPhotoView.setImageBitmap(bitmap);
? ? ? ?}
? ? ? ?}
? ? ? ?}?
? ? ? ?然后,分別在onCreateView(...)和onActivityResult(...)方法中調(diào)用updatePhotoView()
? ? ? ?方法,如下代碼清單所示。
? ? ? ?調(diào)用updatePhotoView()方法(CrimeFragment.java)
? ? ? ?mPhotoButton.setOnClickListener(new View.OnClickListener() {
? ? ? ?@Override
? ? ? ?public void onClick(View v) {
? ? ? ?startActivityForResult(captureImage, REQUEST_PHOTO);
? ? ? ?}
? ? ? ?});
? ? ? ?mPhotoView = (ImageView) v.findViewById(R.id.crime_photo);
? ? ? ?updatePhotoView();
? ? ? ?return v;
? ? ? ?}
? ? ? ?@Override
? ? ? ?public void onActivityResult(int requestCode, int resultCode, Intent data) {
? ? ? ?if (resultCode != Activity.RESULT_OK) {
? ? ? ?return;
? ? ? ?}
? ? ? ?if (requestCode == REQUEST_DATE) {
? ? ? ?...
? ? ? ?} else if (requestCode == REQUEST_CONTACT && data != null) {
? ? ? ?...
? ? ? ?} else if (requestCode == REQUEST_PHOTO) {
? ? ? ?updatePhotoView();
? ? ? ?}
? ? ? ?}?
? ? ? ?再次運(yùn)行應(yīng)用,這樣就可以看到已拍照片的縮略圖了。