**一:本文使用GradView来做图片的展示,来达到仿微信的动态添加效果
这是效果图,正在整理项目,就没有重写一个Demo,直接将我关于GradView的东西展示出来,关于项目的我会隐藏。。。
**
首先分析一波,要做这个玩意,需要对GradView有一个了解,当然,我相信看这篇文章的大佬都晓得,玩有和我一样的小白也不用怕,我会将代码全部刚出来,只需要整理进去Demo运行一波就ok,话不多说,做这个玩意,我是自己写了adapter,用adapter来适配,达到动态添加的目的。
先把adapter放出来
package bitmap;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.Priority;
import com.nanjingtechlogy.quanguanban.R;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import My_Utils.ListDataSave;
/**
* com.bm.falvzixun.adapter.GridViewAddImgAdpter
*
* @author yuandl on 2015/12/24.
* 添加上传图片适配器
*/
public class GridViewAddImgesAdpter extends BaseAdapter {
private List<Map<String, Object>> datas;
private List<File> mList = new ArrayList<>();
private Context context;
private LayoutInflater inflater;
/**
* 可以动态设置最多上传几张,之后就不显示+号了,用户也无法上传了
* 默认4张
*/
private int maxImages = 4;
public GridViewAddImgesAdpter(List<Map<String, Object>> datas, Context context) {
this.datas = datas;
this.context = context;
inflater = LayoutInflater.from(context);
}
/**
* 获取最大上传张数
*
* @return
*/
public int getMaxImages() {
return maxImages;
}
/**
* 设置最大上传张数
*
* @param maxImages
*/
public void setMaxImages(int maxImages) {
this.maxImages = maxImages;
}
/**
* 让GridView中的数据数目加1最后一个显示+号
*
* @return 返回GridView中的数量
*/
@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();
}
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();
}
//移除集合中的对象
//我会把这个类放出来,这个是我的工具类,关于sp存储,下边我会将此处代码详细说明
ListDataSave dataSave = new ListDataSave(context, "PaImage");
List<Object> dataList = dataSave.getDataList("PaImageitem");
dataList.remove(position);
dataSave.delateData();
dataSave.setDataList("PaImageitem",dataList);
notifyDataSetChanged();
}
});
} else {
Glide.with(context)
.load(R.mipmap.tianjiahzaopian)
.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 ImageView btdel;
public final View root;
public ViewHolder(View root) {
ivimage = (ImageView) root.findViewById(R.id.iv_image);
btdel = (ImageView) root.findViewById(R.id.bt_del);
this.root = root;
}
}
}
接下来我把adapter用到的xml文件刚下来,不知为什么,在这儿放看不到,特意放到文章末尾
没什么难度,大家应该都看的懂,这边我将sp存储的工具类放出来
package My_Utils;
import android.content.Context;
import android.content.SharedPreferences;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Administrator on 2018/3/1 0001.
*/
public class ListDataSave {
private SharedPreferences preferences;
private SharedPreferences.Editor editor;
public ListDataSave(Context mContext, String preferenceName) {
preferences = mContext.getSharedPreferences(preferenceName, Context.MODE_PRIVATE);
editor = preferences.edit();
}
/**
* 保存List
* @param tag
* @param datalist
*/
public <T> void setDataList(String tag, List<T> datalist) {
if (null == datalist || datalist.size() <= 0)
return;
Gson gson = new Gson();
//转换成json数据,再保存
String strJson = gson.toJson(datalist);
editor.clear();
editor.putString(tag, strJson);
editor.commit();
}
/**
* 获取List
* @param tag
* @return
*/
public <T> List<T> getDataList(String tag) {
List<T> datalist=new ArrayList<T>();
String strJson = preferences.getString(tag, null);
if (null == strJson) {
return datalist;
}
Gson gson = new Gson();
datalist = gson.fromJson(strJson, new TypeToken<List<T>>() {
}.getType());
return datalist;
}
public void delateData(){
preferences.edit().clear().commit();
}
}
这个是sp工具类,我这边使用这个主要就是为了得到GradView所展示的数据,,,具体用来干什么我会在将代码搞完后文末说逻辑
二、activity里搞事情
1、首先是xml文件,其实无比简单,一个GradView就可以
<GridView
android:layout_below="@id/wu004"
android:id="@+id/gw"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:columnWidth="90dp"
android:gravity="center"
android:horizontalSpacing="5dp"
android:numColumns="3"
android:stretchMode="columnWidth"
android:verticalSpacing="5dp" />
这个很简单,如果对GradView效果不满意,可以查看GradView的文档,各种属性。
2、activity里搞事情
private List<Map<String, Object>> datas;
private GridViewAddImgesAdpter gridViewAddImgesAdpter;
private final int PHOTO_REQUEST_CAREMA = 1;// 拍照
private final int PHOTO_REQUEST_GALLERY = 2;// 从相册中选择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";
List<String> mList = new ArrayList<>();
private ListDataSave dataSave;
int y = 1;
gw = (GridView) findViewById(R.id.gw);
gw.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
showdialog();
}
});
private void showdialog() {
LinearLayout tv_photo;
LinearLayout tv_camera;
//显示弹窗
View mView = showdialogview(R.layout.dialog_user);
tv_camera = showId(mView, R.id.tv_camera);
tv_photo = showId(mView, R.id.tv_photo);
tv_camera.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
openCamraYes();
}
});
tv_photo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mDialog.dismiss();
//动态权限
if (ContextCompat.checkSelfPermission(PatrolLawEnforcementActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(PatrolLawEnforcementActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
return;
} else {
gallery();//打开相册
}
}
});
}
*弹窗设置
private View showdialogview(@LayoutRes int layoutId) {
//显示弹窗
mDialog = new AlertDialog.Builder(PatrolLawEnforcementActivity.this).create();
mDialog.show();
View mView = LayoutInflater.from(PatrolLawEnforcementActivity.this).inflate(layoutId, null);
mDialog.setContentView(mView);
DisplayMetrics dm = new DisplayMetrics();
//获取屏幕信息
this.getWindowManager().getDefaultDisplay().getMetrics(dm);
int screenWidth = dm.widthPixels;
int screenHeigh = dm.heightPixels;
Window mWindow = mDialog.getWindow();
mWindow.getDecorView().setPadding(0, 0, 0, 0);//设置padding值
WindowManager.LayoutParams mAttributes = mWindow.getAttributes();//属性参数
mAttributes.width = screenWidth - 150;
mAttributes.height = screenHeigh / 6;
mWindow.setAttributes(mAttributes);
mWindow.setGravity(Gravity.CENTER);
return mView;
}
//动态权限
public void openCamraYes() {
mDialog.dismiss();
if (Build.VERSION.SDK_INT >= 23) {
int checkCallPhonePermission = ContextCompat.checkSelfPermission(PatrolLawEnforcementActivity.this, Manifest.permission.CAMERA);
if (checkCallPhonePermission != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(PatrolLawEnforcementActivity.this, new String[]{Manifest.permission.CAMERA}, 222);
return;
} else {
camera();
}
} else {
camera();
}
}
/**
* 拍照
*/
public void camera() {
// 判断存储卡是否可以用,可用进行存储
if (hasSdcard()) {
File dir = new File(IMAGE_DIR);
if (!dir.exists()) {
dir.mkdir();
}
tempFile = new File(dir,
System.currentTimeMillis() + "_" + PHOTO_FILE_NAME);
//从文件中创建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);
// 开启一个带有返回值的Activity,请求码为PHOTO_REQUEST_CAREMA
startActivityForResult(intent, PHOTO_REQUEST_CAREMA);
} else {
Toast.makeText(this, "未找到存储卡,无法拍照!", Toast.LENGTH_SHORT).show();
}
}
/**
* 判断sdcard是否被挂载
*/
public boolean hasSdcard() {
return Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED);
}
/**
* 从相册获取2
*/
public void gallery() {
Intent intent = new Intent(
Intent.ACTION_PICK,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, PHOTO_REQUEST_GALLERY);
}
/**
* 上传图片
*
* @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();
mHandler.sendMessage(message);
}
}.start();
}
public void photoPath(String path) {
Map<String, Object> map = new HashMap<>();
map.put("path", path);
datas.add(map);
if (y == 1) {
mList.add(path);
dataSave = new ListDataSave(this, "PaImage");
dataSave.setDataList("PaImageitem", mList);
y++;
} else {
List<Object> dataList = dataSave.getDataList("PaImageitem");
dataSave.delateData();
dataList.add(path);
dataSave.setDataList("PaImageitem", dataList);
}
gridViewAddImgesAdpter.notifyDataSetChanged();
}
//handler里边,用handler来进行更新UI
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 0xAAAAAAAA:
photoPath(msg.obj.toString());
break;
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
if (requestCode == PHOTO_REQUEST_GALLERY) {
// 从相册返回的数据
if (data != null) {
// 得到图片的全路径
Uri uri = data.getData();
String[] proj = {MediaStore.Images.Media.DATA};
//好像是android多媒体数据库的封装接口,具体的看Android文档
Cursor cursor = managedQuery(uri, proj, null, null, null);
//按我个人理解 这个是获得用户选择的图片的索引值
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
//将光标移至开头 ,这个很重要,不小心很容易引起越界
cursor.moveToFirst();
//最后根据索引值获取图片路径
String path = cursor.getString(column_index);
uploadImage(path);
}
} else if (requestCode == PHOTO_REQUEST_CAREMA) {
if (resultCode != RESULT_CANCELED) {
// 从相机返回的数据
if (hasSdcard()) {
if (tempFile != null) {
uploadImage(tempFile.getPath());
} else {
Toast.makeText(this, "相机异常请稍后再试!", Toast.LENGTH_SHORT).show();
}
Log.i("images", "拿到照片path=" + tempFile.getPath());
} else {
Toast.makeText(this, "未找到存储卡,无法存储照片!", Toast.LENGTH_SHORT).show();
}
}
}
}
}
//下面这个是动态权限获取
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
//就像onActivityResult一样这个地方就是判断你是从哪来的。
case 222:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission Granted
openCamra(0);
} else {
// Permission Denied
Toast.makeText(PatrolLawEnforcementActivity.this, "很遗憾你把相机权限禁用了。请务必开启相机权限享受我们提供的服务吧。", Toast.LENGTH_SHORT)
.show();
}
break;
default:
}
}
好了,主要代码全部上去了,应该是没什么遗漏,毕竟是整理嘛,
这些代码和adapter代码对应,这是我为了获取GradView里边的信息,所搞得,我这边主要就是在页面下边进行点击将最终的图片数据传到服务器,又不能传加载 的哪一张图片,所有我就用sp存储来做,先在这边加数据添加,在adapter进行删除的时候在将删除的数据从adapter删除出去,取数据的时候直接从sp取就行,大家看代码应该能搞懂,其实用数据库也能做,但是这边需要进行好几次删除操作,我想了想就先用sp存储来做,可能要比数据库要好一点把。
到此结束,我贴代码还时比较全面的,基本该有的都有了,万一剩几个也是小事儿,大家随便就能补好,无伤大雅。
恩,就这样,大家万一有什么问题的话,直接在下方评论就行,我经常在网上查资料,看到就给大家解答。大家有好的解决GradView获取最终数据的方法欢迎留下,我急需啊,现在这个获取方法看着好难受,完全不够美观健壮。
*下方是adapter的xml文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="74dp"
android:layout_height="80dp">
<FrameLayout
android:layout_width="74dp"
android:layout_height="80dp">
<ImageView
android:id="@+id/iv_image"
android:layout_width="68dp"
android:layout_height="68dp"
android:layout_marginBottom="10dp"
android:layout_marginTop="5dp"
android:scaleType="fitXY"
android:src="@mipmap/tianjiahzaopian" />
<LinearLayout
android:layout_width="74dp"
android:layout_height="wrap_content"
android:gravity="right">
<ImageView
android:id="@+id/bt_del"
android:layout_width="18dp"
android:layout_height="18dp"
android:src="@mipmap/shanchu"
android:visibility="gone" />
</LinearLayout>
</FrameLayout>