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