Android GridView擴(kuò)展仿微信微博發(fā)圖動(dòng)態(tài)添加刪除圖片功能
在平時(shí)的開發(fā)中,我們會(huì)看到不管是微信發(fā)朋友圈照片還是微博發(fā)布新鮮事,添加圖片的時(shí)候都是選完后面還有個(gè)+號(hào)再去選擇圖片,這樣的話比較方便用戶去添加圖片,有的右上角還有個(gè)-號(hào)方便用戶去刪除圖片,而一般用戶選擇的圖片多少都是不定的,我們只限制最大張數(shù),我們用gridview去實(shí)現(xiàn),代碼可能比較簡(jiǎn)單,高手請(qǐng)略過。
0.效果圖

1.準(zhǔn)備資源圖片
添加圖片的+號(hào)圖片

刪除圖片的圖片

2.可設(shè)置限制用戶選擇最大張數(shù)
/**
* 可以動(dòng)態(tài)設(shè)置最多上傳幾張,之后就不顯示+號(hào)了,用戶也無法上傳了
* 默認(rèn)9張
*/
private int maxImages = 9;
/**
* 獲取最大上傳張數(shù)
*
* @return
*/
public int getMaxImages() {
return maxImages;
}
/**
* 設(shè)置最大上傳張數(shù)
*
* @param maxImages
*/
public void setMaxImages(int maxImages) {
this.maxImages = maxImages;
}
3.設(shè)置GridView的總數(shù)
/**
* 讓GridView中的數(shù)據(jù)數(shù)目加1最后一個(gè)顯示+號(hào)
* 當(dāng)?shù)竭_(dá)最大張數(shù)時(shí)不再顯示+號(hào)
* @return 返回GridView中的數(shù)量
*/
@Override
public int getCount() {
int count = datas == null ? 1 : datas.size() + 1;
if (count >= maxImages) {
return datas.size();
} else {
return count;
}
}
4.getView()中根據(jù)position判斷+號(hào)的顯示
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = null;
if (convertView == null) {
convertView = inflater.inflate(R.layout.item_published_grida, parent, false);
viewHolder = new ViewHolder(convertView);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
/**代表+號(hào)之前的需要正常顯示圖片**/
if (datas != null && position < datas.size()) {
final File file = new File(datas.get(position).get("path").toString());
Glide.with(context)
.load(file)
.priority(Priority.HIGH)
.into(viewHolder.ivimage);
viewHolder.btdel.setVisibility(View.VISIBLE);
viewHolder.btdel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (file.exists()) {
file.delete();
}
datas.remove(position);
notifyDataSetChanged();
}
});
} else {
/**代表+號(hào)的需要+號(hào)圖片顯示圖片**/
Glide.with(context)
.load(R.mipmap.image_add)
.priority(Priority.HIGH)
.centerCrop()
.into(viewHolder.ivimage);
viewHolder.ivimage.setScaleType(ImageView.ScaleType.FIT_XY);
viewHolder.btdel.setVisibility(View.GONE);
}
return convertView;
}
5.GridView的完整代碼
package cn.bluemobi.dylan.gridviewaddimage;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.Priority;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* com.bm.falvzixun.adapter.GridViewAddImgAdpter
*
* @author yuandl on 2015/12/24.
* 添加上傳圖片適配器
*/
public class GridViewAddImgesAdpter extends BaseAdapter {
private List<Map<String, Object>> datas;
private Context context;
private LayoutInflater inflater;
/**
* 可以動(dòng)態(tài)設(shè)置最多上傳幾張,之后就不顯示+號(hào)了,用戶也無法上傳了
* 默認(rèn)9張
*/
private int maxImages = 9;
public GridViewAddImgesAdpter(List<Map<String, Object>> datas, Context context) {
this.datas = datas;
this.context = context;
inflater = LayoutInflater.from(context);
}
/**
* 獲取最大上傳張數(shù)
*
* @return
*/
public int getMaxImages() {
return maxImages;
}
/**
* 設(shè)置最大上傳張數(shù)
*
* @param maxImages
*/
public void setMaxImages(int maxImages) {
this.maxImages = maxImages;
}
/**
* 讓GridView中的數(shù)據(jù)數(shù)目加1最后一個(gè)顯示+號(hào)
* 當(dāng)?shù)竭_(dá)最大張數(shù)時(shí)不再顯示+號(hào)
* @return 返回GridView中的數(shù)量
*/
@Override
public int getCount() {
int count = datas == null ? 1 : datas.size() + 1;
if (count >= maxImages) {
return datas.size();
} else {
return count;
}
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
public void notifyDataSetChanged(List<Map<String, Object>> datas) {
this.datas = datas;
this.notifyDataSetChanged();
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = null;
if (convertView == null) {
convertView = inflater.inflate(R.layout.item_published_grida, parent, false);
viewHolder = new ViewHolder(convertView);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
/**代表+號(hào)之前的需要正常顯示圖片**/
if (datas != null && position < datas.size()) {
final File file = new File(datas.get(position).get("path").toString());
Glide.with(context)
.load(file)
.priority(Priority.HIGH)
.into(viewHolder.ivimage);
viewHolder.btdel.setVisibility(View.VISIBLE);
viewHolder.btdel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (file.exists()) {
file.delete();
}
datas.remove(position);
notifyDataSetChanged();
}
});
} else {
/**代表+號(hào)的需要+號(hào)圖片顯示圖片**/
Glide.with(context)
.load(R.mipmap.image_add)
.priority(Priority.HIGH)
.centerCrop()
.into(viewHolder.ivimage);
viewHolder.ivimage.setScaleType(ImageView.ScaleType.FIT_XY);
viewHolder.btdel.setVisibility(View.GONE);
}
return convertView;
}
public class ViewHolder {
public final ImageView ivimage;
public final Button btdel;
public final View root;
public ViewHolder(View root) {
ivimage = (ImageView) root.findViewById(R.id.iv_image);
btdel = (Button) root.findViewById(R.id.bt_del);
this.root = root;
}
}
}
6.用法
主布局文件activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#FFFFFF" android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="cn.bluemobi.dylan.gridviewaddimage.MainActivity"> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:text="說點(diǎn)什么" android:textColor="#000000" /> <GridView android:layout_marginTop="10dp" android:id="@+id/gw" android:numColumns="5" android:horizontalSpacing="6dp" android:columnWidth="60dp" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
gridview的item布局文件item_published_grida.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="66dp" android:layout_height="66dp"> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/iv_image" android:layout_width="match_parent" android:gravity="center" android:layout_height="match_parent" android:scaleType="centerCrop"/> <Button android:id="@+id/bt_del" android:layout_width="20dp" android:layout_height="20dp" android:layout_alignParentRight="true" android:background="@drawable/bt_dynamic_del" /> </RelativeLayout> </RelativeLayout>
彈出拍照和從相冊(cè)選擇的對(duì)話框布局文件dialog_add_picture.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginLeft="5.0dip" android:layout_marginRight="5.0dip" android:background="@android:color/transparent" android:orientation="vertical"> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_margin="30px" android:orientation="vertical"> <TextView android:id="@+id/tv_camera" android:layout_width="wrap_content" android:layout_height="144px" android:background="@mipmap/btn_top_arc" android:gravity="center" android:text="拍照" android:textColor="#666666" android:textSize="48px" /> <ImageView android:layout_width="1022px" android:layout_height="4px" android:background="#666666" /> <TextView android:id="@+id/tv_gallery" android:layout_width="wrap_content" android:layout_height="144px" android:gravity="center" android:background="@mipmap/btn_bottom_arc" android:text="從手機(jī)相冊(cè)選擇" android:textColor="#666666" android:textSize="48px" /> </LinearLayout> <TextView android:id="@+id/tv_cancel" android:layout_width="wrap_content" android:layout_height="144px" android:layout_marginTop="20px" android:layout_marginLeft="30px" android:layout_marginRight="30px" android:layout_gravity="center_horizontal" android:background="@mipmap/btn_top_arc" android:gravity="center" android:text="取消" android:textColor="#666666" android:textSize="48px" /> </LinearLayout>
MainActivity
package cn.bluemobi.dylan.gridviewaddimage;
import android.app.Dialog;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Display;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.TextView;
import android.widget.Toast;
import net.bither.util.NativeUtil;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MainActivity extends AppCompatActivity {
private GridView gw;
private List<Map<String, Object>> datas;
private GridViewAddImgesAdpter gridViewAddImgesAdpter;
private Dialog dialog;
private final int PHOTO_REQUEST_CAREMA = 1;// 拍照
private final int PHOTO_REQUEST_GALLERY = 2;// 從相冊(cè)中選擇private static final String PHOTO_FILE_NAME = "temp_photo.jpg";
private File tempFile;
private final String IMAGE_DIR = Environment.getExternalStorageDirectory() + "/gridview/";
/* 頭像名稱 */
private final String PHOTO_FILE_NAME = "temp_photo.jpg";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gw = (GridView) findViewById(R.id.gw);
datas = new ArrayList<>();
gridViewAddImgesAdpter = new GridViewAddImgesAdpter(datas, this);
gw.setAdapter(gridViewAddImgesAdpter);
gw.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
showdialog();
}
});
}
/**
* 選擇圖片對(duì)話框
*/
public void showdialog() {
View localView = LayoutInflater.from(this).inflate(
R.layout.dialog_add_picture, null);
TextView tv_camera = (TextView) localView.findViewById(R.id.tv_camera);
TextView tv_gallery = (TextView) localView.findViewById(R.id.tv_gallery);
TextView tv_cancel = (TextView) localView.findViewById(R.id.tv_cancel);
dialog = new Dialog(this, R.style.custom_dialog);
dialog.setContentView(localView);
dialog.getWindow().setGravity(Gravity.BOTTOM);
// 設(shè)置全屏
WindowManager windowManager = getWindowManager();
Display display = windowManager.getDefaultDisplay();
WindowManager.LayoutParams lp = dialog.getWindow().getAttributes();
lp.width = display.getWidth(); // 設(shè)置寬度
dialog.getWindow().setAttributes(lp);
dialog.show();
tv_cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
dialog.dismiss();
}
});
tv_camera.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dialog.dismiss();
// 拍照
camera();
}
});
tv_gallery.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dialog.dismiss();
// 從系統(tǒng)相冊(cè)選取照片
gallery();
}
});
}
/**
* 拍照
*/
public void camera() {
// 判斷存儲(chǔ)卡是否可以用,可用進(jìn)行存儲(chǔ)
if (hasSdcard()) {
File dir = new File(IMAGE_DIR);
if (!dir.exists()) {
dir.mkdir();
}
tempFile = new File(dir,
System.currentTimeMillis() + "_" + PHOTO_FILE_NAME);
//從文件中創(chuàng)建uri
Uri uri = Uri.fromFile(tempFile);
Intent intent = new Intent();
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
intent.addCategory(intent.CATEGORY_DEFAULT);
// 開啟一個(gè)帶有返回值的Activity,請(qǐng)求碼為PHOTO_REQUEST_CAREMA
startActivityForResult(intent, PHOTO_REQUEST_CAREMA);
} else {
Toast.makeText(this, "未找到存儲(chǔ)卡,無法拍照!", Toast.LENGTH_SHORT).show();
}
}
/**
* 判斷sdcard是否被掛載
*/
public boolean hasSdcard() {
return Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED);
}
/**
* 從相冊(cè)獲取2
*/
public void gallery() {
Intent intent = new Intent(
Intent.ACTION_PICK,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, PHOTO_REQUEST_GALLERY);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
if (requestCode == PHOTO_REQUEST_GALLERY) {
// 從相冊(cè)返回的數(shù)據(jù)
if (data != null) {
// 得到圖片的全路徑
Uri uri = data.getData();
String[] proj = {MediaStore.Images.Media.DATA};
//好像是android多媒體數(shù)據(jù)庫(kù)的封裝接口,具體的看Android文檔
Cursor cursor = managedQuery(uri, proj, null, null, null);
//按我個(gè)人理解 這個(gè)是獲得用戶選擇的圖片的索引值
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
//將光標(biāo)移至開頭 ,這個(gè)很重要,不小心很容易引起越界
cursor.moveToFirst();
//最后根據(jù)索引值獲取圖片路徑
String path = cursor.getString(column_index);
uploadImage(path);
}
} else if (requestCode == PHOTO_REQUEST_CAREMA) {
if (resultCode != RESULT_CANCELED) {
// 從相機(jī)返回的數(shù)據(jù)
if (hasSdcard()) {
if (tempFile != null) {
uploadImage(tempFile.getPath());
} else {
Toast.makeText(this, "相機(jī)異常請(qǐng)稍后再試!", Toast.LENGTH_SHORT).show();
}
Log.i("images", "拿到照片path=" + tempFile.getPath());
} else {
Toast.makeText(this, "未找到存儲(chǔ)卡,無法存儲(chǔ)照片!", Toast.LENGTH_SHORT).show();
}
}
}
}
}
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == 0xAAAAAAAA) {
photoPath(msg.obj.toString());
}
}
};
/**
* 上傳圖片
*
* @param path
*/
private void uploadImage(final String path) {
new Thread() {
@Override
public void run() {
if (new File(path).exists()) {
Log.d("images", "源文件存在" + path);
} else {
Log.d("images", "源文件不存在" + path);
}
File dir = new File(IMAGE_DIR);
if (!dir.exists()) {
dir.mkdir();
}
final File file = new File(dir + "/temp_photo" + System.currentTimeMillis() + ".jpg");
NativeUtil.compressBitmap(path, file.getAbsolutePath(), 50);
if (file.exists()) {
Log.d("images", "壓縮后的文件存在" + file.getAbsolutePath());
} else {
Log.d("images", "壓縮后的不存在" + file.getAbsolutePath());
}
Message message = new Message();
message.what = 0xAAAAAAAA;
message.obj = file.getAbsolutePath();
handler.sendMessage(message);
}
}.start();
}
public void photoPath(String path) {
Map<String,Object> map=new HashMap<>();
map.put("path",path);
datas.add(map);
gridViewAddImgesAdpter.notifyDataSetChanged();
}
}
7.GitHub源碼 :GridViewAddImage
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Kotlin?this關(guān)鍵字的使用實(shí)例詳解
這篇文章主要介紹了Kotlin?this關(guān)鍵字的使用實(shí)例,在Kotlin中,this關(guān)鍵字允許我們引用一個(gè)類的實(shí)例,該類的函數(shù)恰好正在運(yùn)行。此外,還有其他方式可以使this表達(dá)式派上用場(chǎng)2023-02-02
android 仿微信demo——微信消息界面實(shí)現(xiàn)(服務(wù)端)
本系列文章主要介紹了微信小程序-閱讀小程序?qū)嵗╠emo),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧,希望能給你們提供幫助2021-06-06
Android控件之RatingBar自定義星級(jí)評(píng)分樣式
RatingBar為評(píng)分條控件,默認(rèn)效果為若干個(gè)綠色的星星,如果想將其換成其他自定義圖片就要自定義它的style。接下來通過本文給大家介紹Android控件之RatingBar自定義星級(jí)評(píng)分樣式,感興趣的朋友一起學(xué)習(xí)吧2016-02-02
Android Studio綁定下拉框數(shù)據(jù)詳解
這篇文章主要為大家詳細(xì)介紹了Android Studio綁定下拉框數(shù)據(jù),Android Studio綁定網(wǎng)絡(luò)JSON數(shù)據(jù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10
Android 系統(tǒng)net和wap接入點(diǎn)的區(qū)別
這篇文章主要介紹了Android 系統(tǒng)net和wap接入點(diǎn)的區(qū)別的相關(guān)資料,需要的朋友可以參考下2016-09-09
Android實(shí)現(xiàn)USB掃碼槍獲取掃描內(nèi)容
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)USB掃碼槍獲取掃描內(nèi)容,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09
Android編程實(shí)現(xiàn)類似于圓形ProgressBar的進(jìn)度條效果
這篇文章主要介紹了Android編程實(shí)現(xiàn)類似于圓形ProgressBar的進(jìn)度條效果,結(jié)合實(shí)例形式分析了Android通過自定義View實(shí)現(xiàn)圓形進(jìn)度條效果的操作方法,需要的朋友可以參考下2017-03-03
android計(jì)算器實(shí)現(xiàn)兩位數(shù)的加減乘除
這篇文章主要為大家詳細(xì)介紹了android計(jì)算器實(shí)現(xiàn)兩位數(shù)的加減乘除,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-03-03
Android編程之Activity中onDestroy()調(diào)用分析
這篇文章主要介紹了Android編程之Activity中onDestroy()調(diào)用方法,針對(duì)onDestroy引起的內(nèi)存泄露及解決方法進(jìn)行了分析,并給出了解決方案,需要的朋友可以參考下2015-12-12

