1. 程式人生 > >Android仿微信新增照片並且隨意限制照片數量並顯示縮圖介面

Android仿微信新增照片並且隨意限制照片數量並顯示縮圖介面

前段時間做專案時產品加入一個新功能,拍照並顯示縮圖,之前我們公司的都是隻顯示拍了幾張照片 然後點選之後跳到另外一個介面顯示這幾張照片,自我感覺這種方式很是不方便,就趁次機會做了一個實用並且通用的拍照顯示工具,先看效果

這是拍照過程中,如果沒有達到設定的拍照數量那麼拍照按鈕就顯示著還可以繼續拍

當拍照數量達到設定的數量後最後的拍照按鈕隱藏,我在這裡設定的9張照片,你用的時候可以隨意設定

一、實現這個功能主要在於介面卡怎麼寫,其實邏輯也比較簡單,我們定一個數字作為照片數量的限制,然後在介面卡getCount()方法中用這個值和現有照片數量做對比然後返回相應的數量即可,寫的demo,所以主介面很簡單 就一個GridView,其實現在可以用recycleview代替現有的Listview和GridView,比如前幾天我就遇到一個這個問題,產品原型畫出來了,效果圖還沒出來,資料也沒有,但我們不能等他們要先用假資料做介面,其中一個介面是這樣的,就是一個列表,每個item是一張圖對應一句話,原型是一行一個,我就想著先用listview把效果實現了,等設計和資料來了稍作修改即可,可不曾想設計圖出來後傻了,設計覺得每行顯示一列不好看,設計成了每行兩列,這就意味著我要重新換控制元件,如果以後介面再改又要換,所以直接用了recycleview,這樣以後管他橫排豎排橫滑豎滑只需對recycleview進行設定即可,話說回來,我們這裡還暫用GridView,因為我不想再換了,想換可以自行修改

二、主介面就是拍照然後重新整理介面卡這些操作,我們直接看adapter

item佈局要注意一下,因為要包含圖片和拍照按鈕

程式碼如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:background="@drawable/selector_presse"
    android:orientation="vertical" >

    <ImageView
        android:id="@+id/iconImageView"
        android:layout_width="match_parent"
        android:layout_height="130dp"
        android:background="@null"
        android:scaleType="fitXY"
        android:src="@drawable/defelt_icon" />

    <FrameLayout
        android:id="@+id/framelayout_add_pic"
        android:layout_width="match_parent"
        android:layout_height="130dp"
        android:background="@color/gray_bg_color" >

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="130dp"
            android:gravity="center"
            android:orientation="vertical" >

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="+"
                android:textColor="@color/gray_text_color"
                android:textSize="40dp" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp"
                android:text="新增圖片"
                android:textColor="@color/gray_text_color" />
        </LinearLayout>
    </FrameLayout>

</LinearLayout>

由於拍照按鈕用照片的話在不同手機上顯示效果不同,有可能會變形,所以用了佈局的方式,圖片加文字,這樣看著就會很自然,再看介面卡主要是getcount()方法

@Override
	public int getCount() {
		int size = 1;
		if (mPictures.size() >= mNums) {
			// 限制拍照數量mNums張
			size = mPictures.size();
		} else {
			size += mPictures.size();
		}
		return size;
	}

這裡面的mNums是傳進來的 用於限定拍照數量,拍照按鈕顯示與否是要靠返回的size控制,這裡至少要返回1,因為一開始要顯示拍照按鈕,如果沒有達到設定數量,那麼每次返回的數量要+1,給拍照按鈕留下位置,如果達到數量那麼就直接返回照片數量,不需多返回一個位置,至於顯示照片還是新增照片按鈕要在下面的getView()種控制。構造如下:其中CreateBmpFactory是拍照的一個工具類,稍後我會上傳完整demo

public PhotoAdapter(List<String> mPictures, int mNums, CreateBmpFactory mCreateBmpFactory, Context mContext) {
		super();
		this.mPictures = mPictures;
		this.mCreateBmpFactory = mCreateBmpFactory;
		this.mContext = mContext;
		this.mNums = mNums;
	}

然後另一關鍵處是getView()方法裡要靠position和照片集合的size對比,因為position是從0開始,而size是從1開始,所以正常情況下position總是比size小,所以當position==mPictures.size()的時候說明此時getCount()多返回了一個位置,此時就是拍照數量沒達到設定值需要顯示拍照按鈕(這個地方有點繞),來看getView()方法:

@Override
	public View getView(final int position, View convertView, ViewGroup parent) {
		ViewHolder holder;
		if (convertView == null) {
			holder = new ViewHolder();
			convertView = LayoutInflater.from(mContext).inflate(R.layout.layout_picture, parent, false);
			holder.iv_icon = (ImageView) convertView.findViewById(R.id.iconImageView);
			holder.framelayout_add_pic = (FrameLayout) convertView.findViewById(R.id.framelayout_add_pic);
			convertView.setTag(holder);
		} else {
			holder = (ViewHolder) convertView.getTag();
		}

		if (position == mPictures.size()) {
			holder.iv_icon.setVisibility(View.GONE);
			holder.framelayout_add_pic.setVisibility(View.VISIBLE);
		} else {
			holder.iv_icon.setVisibility(View.VISIBLE);
			holder.framelayout_add_pic.setVisibility(View.GONE);
			holder.iv_icon.setTag(mPictures.get(position).toString());
			new GetBitmapTask().execute(holder.iv_icon);
		}
		convertView.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				if (position == mPictures.size()) {

					AlertDialog.Builder builder = new AlertDialog.Builder(mContext );
					builder.setTitle("請選擇操作");
					final String[] menu = { "拍照", "從相簿中選擇" };
					builder.setItems(menu, new DialogInterface.OnClickListener() {
						@Override
						public void onClick(DialogInterface dialog, int which) {
							switch (which) {
							case 0:
								mCreateBmpFactory.OpenCamera();
								break;

							case 1:
								mCreateBmpFactory.OpenGallery();
								break;
							}
						}
					});
					builder.show();
				} else {

					AlertDialog.Builder builder = new Builder(mContext).setTitle("檢視大圖");
					View view = LayoutInflater.from(mContext).inflate(R.layout.layout_img_dialog, null);
					ImageView bigPhoto = ((ImageView) view.findViewById(R.id.bigPic));
					bigPhoto.setImageBitmap(BitmapFactory.decodeFile(mPictures.get(position).toString()));
					builder.setView(view).setPositiveButton("刪除", new DialogInterface.OnClickListener() {

						@Override
						public void onClick(DialogInterface dialog, int which) {
							// 刪除圖片
							mPictures.remove(position);
							notifyDataSetChanged();
						}
					}).setNegativeButton("返回", null).create().show();
				}
			}
		});

		return convertView;
	}

主要判斷在於這:

if (position == mPictures.size()) {
			holder.iv_icon.setVisibility(View.GONE);
			holder.framelayout_add_pic.setVisibility(View.VISIBLE);
		} else {
			holder.iv_icon.setVisibility(View.VISIBLE);
			holder.framelayout_add_pic.setVisibility(View.GONE);
			holder.iv_icon.setTag(mPictures.get(position).toString());
			new GetBitmapTask().execute(holder.iv_icon);
		}

當然那個彈框看大圖的只是實現以下點選事件,這裡你可以進行你自己的其他操作。由於顯示的是圖片所以會有一個問題就是圖片過大時候會比較卡,比如你專案裡用的時候肯定是要儲存圖片然後進行回顯的,這時候直接主執行緒里加載就會很卡,所以顯示照片的操作可以放線上程裡面做,上面的new GetBitmapTask().execute(holder.iv_icon)就是用來非同步載入的,具體實現如下:

class GetBitmapTask extends AsyncTask<ImageView, Void, ImageView> {
		Bitmap bitmap = null;
		ImageView view = null;

		@Override
		protected ImageView doInBackground(ImageView... params) {
			// TODO Auto-generated method stub
			view = params[0];
			String path = view.getTag().toString();
			bitmap = BitmapHelp.getSmallBitmap(path);
			return view;
		}

		@Override
		protected void onPostExecute(ImageView v) {
			// TODO Auto-generated method stub
			v.setImageBitmap(bitmap);
			super.onPostExecute(v);
		}
	}

傳入控制元件,把照片的路徑以Tag的方式設定給控制元件即可。至此功能完美實現。

需要demo的小夥伴可以加qq群自行下載(TakePhotoAdapter.zip):579699145