1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > android 仿微信选取相册_Android模仿微信选择图片

android 仿微信选取相册_Android模仿微信选择图片

时间:2021-12-22 14:05:34

相关推荐

android 仿微信选取相册_Android模仿微信选择图片

前言

最近公司需要做一个类似微信那种选择头像和上传图片的功能,本想上github上找的,后来想了想,还是自己做一个,不仅方便以后用(毕竟自己写的修改起来也比较方便),还可以学到一些知识,废话少说,先看效果图:

(ps:大致的功能就这样,拍照功能就是拍了照片之后跳到剪切的页面,这里没有截出来,主要是为了压缩下gif图的大小)

现在来简单的介绍下有什么功能:

可根据传入的值控制是选择头像还是上传图片,大于1就是选择图片,等于1救是选择头像

可根据传入的值控制选择图片的数量,并且当选中的图片数量等于这个数量时,则其他没有被选中的图片变成不可选择

可选择不同文件夹下的图片

自定义ViewGroup显示选中的图片数,不同的数量显示的格式不一样(gif最后那一帧录制的不是很清楚),类似微信那种,1张,2张还是9张显示的格式不同

拍照剪切头像

大概下就是这么些,现在我们来说说实现的思路,主要分为几步

在子线程中读出sd卡下所有的文件夹下的图片,并且在RecyclerView中显示出来

RecyclerView采用多item布局方式,分开拍照和图片,主要是方便修改拍照的view,这里只是用图片显示

适配每个图片等宽度和高度为屏幕宽度等三分之一

底部采用PopupWindow显示出所有的图片所在的文件夹

如果是多选图片,则为每个view添加checkbox的选中监听,否则就调用系统的剪切图片功能,剪切完成之后显示出来

根据选中的图片数,展示不同的布局

好了,现在我们来看看代码

ImageSelectActivity

这个activity主要是用来显示从sd中读取出来的图片

package com.myimageselectcontainer;

import android.app.Activity;

import android.app.ProgressDialog;

import android.content.ContentResolver;

import android.content.Intent;

import android.database.Cursor;

import android.graphics.Bitmap;

import android.graphics.BitmapFactory;

import .Uri;

import android.os.Bundle;

import android.os.Environment;

import android.os.Handler;

import android.provider.MediaStore;

import android.support.annotation.BoolRes;

import android.support.annotation.Nullable;

import android.support.v7.app.AppCompatActivity;

import android.support.v7.widget.GridLayoutManager;

import android.support.v7.widget.LinearLayoutManager;

import android.support.v7.widget.RecyclerView;

import android.util.DisplayMetrics;

import android.util.Log;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.view.WindowManager;

import android.widget.LinearLayout;

import android.widget.PopupWindow;

import android.widget.TextView;

import android.widget.Toast;

import com.myimageselectcontainer.adapter.ImageDirAdapter;

import com.myimageselectcontainer.adapter.MyAdapter;

import com.myimageselectcontainer.adapter.SpacesItemDecoration;

import com.myimageselectcontainer.bean.ImageBean;

import com.myimageselectcontainer.bean.ImageDirBean;

import com.myimageselectcontainer.click.OnChangeListener;

import com.myimageselectcontainer.click.OnImageDirItemListener;

import com.myimageselectcontainer.click.OnItemClickListener;

import java.io.ByteArrayOutputStream;

import java.io.File;

import java.io.FilenameFilter;

import java.util.ArrayList;

import java.util.Arrays;

import java.util.HashSet;

import java.util.List;

public class ImageSelectActivity extends AppCompatActivity implements OnItemClickListener,

OnChangeListener, View.OnClickListener, PopupWindow.OnDismissListener, OnImageDirItemListener {

private static final int PHOTO_REQUEST_CAMERA = 1;// 拍照

private static final int PHOTO_REQUEST_CUT = 2;// 结果

private ProgressDialog mProgressDialog;

/**

* 存储文件夹中的图片数量

*/

private int mPicsSize;

/**

* 扫描拿到所有的图片文件夹

*/

private List imageDirBeans = new ArrayList<>();

/**

* 图片数量

*/

private int totalCount = 0;

/**

* 临时的辅助类,用于防止同一个文件夹的多次扫描

*/

private HashSet mDirPaths = new HashSet<>();

/**

* 所有的图片

*/

private List mImages = new ArrayList<>();

/**

* 选中的图片集合

*/

private ArrayList mSelectImages = new ArrayList<>();

/**

* 最大的图片数

*/

private int maxImageCount = 9;

/**

* 屏幕高度

*/

private int mScreenHeight;

/**

* 用来存储选中的文件

*/

private File mSelectFile;

/**

* 用于显示全部文件夹

*/

private PopupWindow mPopupWindow;

/**

* 当PopupWindow显示或者消失时改变背景色

*/

private WindowManager.LayoutParams lp;

/**

* 拿到传过来的值,测试选择图片

*/

private int select;

/**

* 存储拍照和选中的图片

*/

private File file;

private MyThread mThread;

private ImageDirBean imageDirBean;

private ImageBean imageBean;

private RecyclerView rcyImageSelect;

private TextView tvImageCount;

private TextView tvImageDir;

private TextView tvConfirm;

private LinearLayout linearLayout;

private Handler mHandler = new Handler() {

public void handleMessage(android.os.Message msg) {

mProgressDialog.dismiss();

//绑定数据

setData();

if (mThread != null && !mThread.isInterrupted()) {

mThread.isInterrupted();

}

}

};

private MyAdapter mAdapter;

@Override

protected void onCreate(@Nullable Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_image_select);

select = getIntent().getIntExtra("select", 0);

maxImageCount = select;

rcyImageSelect = (RecyclerView) findViewById(R.id.rcyView_imageSelect);

tvImageCount = (TextView) findViewById(R.id.tv_imageCount);

tvImageDir = (TextView) findViewById(R.id.tv_imageDir);

tvConfirm = (TextView) findViewById(R.id.tv_confirm);

linearLayout = (LinearLayout) findViewById(R.id.linearLayout);

mPopupWindow = new PopupWindow(this);

//获取屏幕高度,设给PopupWindow

DisplayMetrics outMetrics = new DisplayMetrics();

getWindowManager().getDefaultDisplay().getMetrics(outMetrics);

mScreenHeight = outMetrics.heightPixels;

lp = getWindow().getAttributes();

rcyImageSelect.setLayoutManager(new GridLayoutManager(this, 3));

tvConfirm.setText("确定" + mSelectImages.size() + "/" + maxImageCount);

getImageList();

setImageDirData();

tvImageDir.setOnClickListener(this);

tvConfirm.setOnClickListener(this);

mPopupWindow.setOnDismissListener(this);

file = new File(Environment.getExternalStorageDirectory(), "temp.jpg");

}

private void setData() {

mAdapter = new MyAdapter(this, maxImageCount, mImages, this, this);

rcyImageSelect.setAdapter(mAdapter);

rcyImageSelect.addItemDecoration(new SpacesItemDecoration(2));

tvImageCount.setText(totalCount + "张");

}

//图片文件数据

private void setImageDirData() {

if (!imageDirBeans.isEmpty()) {

View contentView = LayoutInflater.from(this).inflate(R.layout.image_dir_list, null);

RecyclerView rcyViewImageDir = (RecyclerView) contentView.findViewById(R.id.rcyView_imageDir);

rcyViewImageDir.setLayoutManager(new LinearLayoutManager(this));

rcyViewImageDir.setAdapter(new ImageDirAdapter(this, imageDirBeans, this));

mPopupWindow.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);

mPopupWindow.setHeight((int) (mScreenHeight * 0.7f));

mPopupWindow.setContentView(contentView);

mPopupWindow.setOutsideTouchable(true);

mPopupWindow.setFocusable(true);

mPopupWindow.showAsDropDown(linearLayout, 0, 0);

// 设置背景颜色变暗

lp.alpha = 0.5f;

getWindow().setAttributes(lp);

}

}

private void getImageList() {

//判断是否有内存卡

if (!Environment.getExternalStorageState().equals(

Environment.MEDIA_MOUNTED)) {

Toast.makeText(this, "暂无外部存储", Toast.LENGTH_SHORT).show();

} else {

mProgressDialog = new ProgressDialog(this);

mProgressDialog.setMessage("正在加载...");

mProgressDialog.show();

mThread = new MyThread();

mThread.start();

//在子线程中读取最多图片的集合

// new Thread(new Runnable() {

// @Override

// public void run() {

// //第一张图片

// String firstImage = null;

// //获取内存卡路径

// Uri mImageUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;

// //通过内容解析器解析出png和jpeg格式的图片

// ContentResolver mContentResolver = ImageSelectActivity.this

// .getContentResolver();

// Cursor mCursor = mContentResolver.query(mImageUri, null,

// MediaStore.Images.Media.MIME_TYPE + "=? or "

// + MediaStore.Images.Media.MIME_TYPE + "=?",

// new String[]{"image/png", "image/jpeg"},

// MediaStore.Images.Media.DATE_MODIFIED);

// //判断是否存在图片

// if (mCursor.getCount() > 0) {

// while (mCursor.moveToNext()) {

// // 获取图片的路径

// String path = mCursor.getString(mCursor

// .getColumnIndex(MediaStore.Images.Media.DATA));

// // 拿到第一张图片的路径

// if (firstImage == null)

// firstImage = path;

// // 获取该图片的文件名

// File parentFile = new File(path).getParentFile();

// if (parentFile == null)

// continue;

// //获取到文件地址

// String dirPath = parentFile.getAbsolutePath();

// imageBean = new ImageBean();

// imageBean.setPath(path);

// mImages.add(imageBean);

// if (mDirPaths.contains(dirPath)) {

// continue;

// } else {

// mDirPaths.add(dirPath);

// imageDirBean = new ImageDirBean();

// imageDirBean.setDir(dirPath);

// imageDirBean.setImagePath(path);

// }

// int picSize = parentFile.list(new FilenameFilter() {

// @Override

// public boolean accept(File dir, String filename) {

// if (filename.endsWith(".jpg")

// || filename.endsWith(".png")

// || filename.endsWith(".jpeg"))

// return true;

// return false;

// }

// }).length;

// totalCount += picSize;

//

// imageDirBean.setImageCount(picSize);

// imageDirBeans.add(imageDirBean);

// if (picSize > mPicsSize) {

// mPicsSize = picSize;

// }

// }

// mCursor.close();

// mDirPaths = null;

// // 通知Handler扫描图片完成

// mHandler.sendEmptyMessage(0x110);

// }

// }

// }).start();

}

}

@Override

public void onItemClickListener(View view, int position) {

if (position != 0) {

if (maxImageCount == 1) {

clipPhoto(Uri.fromFile(new File(mImages.get(position).getPath())), PHOTO_REQUEST_CUT);//开始裁减图片

} else {

Toast.makeText(this, position + "", Toast.LENGTH_SHORT).show();

}

} else if (select == 1) {

Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

// 下面这句指定调用相机拍照后的照片存储的路径

cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));

startActivityForResult(cameraIntent, PHOTO_REQUEST_CAMERA);// CAMERA_OK是用作判断返回结果的标识

}

}

@Override

public void OnChangeListener(int position, boolean isChecked) {

if (isChecked) {

mImages.get(position).setSelect(true);

if (!contains(mSelectImages, mImages.get(position))) {

mSelectImages.add(mImages.get(position));

if (mSelectImages.size() == maxImageCount) {

mAdapter.notifyData(mSelectImages);

}

}

} else {

mImages.get(position).setSelect(false);

if (contains(mSelectImages, mImages.get(position))) {

mSelectImages.remove(mImages.get(position));

if (mSelectImages.size() == maxImageCount - 1) {

mAdapter.notifyData(mSelectImages);

}

}

}

tvConfirm.setText("确定" + mSelectImages.size() + "/" + maxImageCount);

}

private boolean contains(List list, ImageBean imageBean) {

for (ImageBean bean : list) {

if (bean.getPath().equals(imageBean.getPath())) {

return true;

}

}

return false;

}

@Override

public void onClick(View v) {

if (v.getId() == R.id.tv_imageDir) {

setImageDirData();

} else if (v.getId() == R.id.tv_confirm) {

if (mSelectImages.size() != 0) {

Intent intent = new Intent();

intent.putParcelableArrayListExtra("selectImages", mSelectImages);

setResult(Activity.RESULT_OK, intent);

finish();

} else {

Toast.makeText(this, "请选择至少一张图片", Toast.LENGTH_SHORT).show();

}

}

}

@Override

public void onDismiss() {

// 设置背景颜色变暗

lp = getWindow().getAttributes();

lp.alpha = 1.0f;

getWindow().setAttributes(lp);

}

@Override

public void onImageDirItemListener(View view, int position) {

mImages.clear();

mImages.add(null);

if (mSelectImages.size() > 0) {

mSelectImages.clear();

}

String dir = imageDirBeans.get(position).getDir();

mSelectFile = new File(dir);

List imagePath = Arrays.asList(mSelectFile.list(new FilenameFilter() {

@Override

public boolean accept(File dir, String filename) {

if (filename.endsWith(".jpg") || filename.endsWith(".png")

|| filename.endsWith(".jpeg"))

return true;

return false;

}

}));

for (int i = 0; i < imagePath.size(); i++) {

imageBean = new ImageBean();

imageBean.setPath(dir + "/" + imagePath.get(i));

imageBean.setSelect(false);

mImages.add(imageBean);

}

tvImageDir.setText(imageDirBeans.get(position).getImageName());

tvImageCount.setText(imageDirBeans.get(position).getImageCount() + "张");

mAdapter.notifyDataSetChanged();

mPopupWindow.dismiss();

}

@Override

protected void onActivityResult(int requestCode, int resultCode, Intent data) {

super.onActivityResult(requestCode, resultCode, data);

if (resultCode == RESULT_OK)

switch (requestCode) {

case PHOTO_REQUEST_CAMERA:

clipPhoto(Uri.fromFile(file), PHOTO_REQUEST_CAMERA);//开始裁减图片

break;

case PHOTO_REQUEST_CUT:

Bitmap bitmap = data.getParcelableExtra("data");

Intent intent = new Intent();

ByteArrayOutputStream bs = new ByteArrayOutputStream();

press(pressFormat.PNG, 100, bs);

byte[] bitmapByte = bs.toByteArray();

intent.putExtra("bitmap", bitmapByte);

setResult(RESULT_OK, intent);

finish();

break;

}

}

private void clipPhoto(Uri uri, int type) {

Intent intent = new Intent("com.android.camera.action.CROP");

intent.setAction("com.android.camera.action.CROP");

intent.setDataAndType(uri, "image/*");// mUri是已经选择的图片Uri

intent.putExtra("crop", "true");

intent.putExtra("aspectX", 1);// 裁剪框比例

intent.putExtra("aspectY", 1);

intent.putExtra("outputX", 150);// 输出图片大小

intent.putExtra("outputY", 150);

intent.putExtra("return-data", true);

if (type == PHOTO_REQUEST_CAMERA) {

intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);

}

startActivityForResult(intent, PHOTO_REQUEST_CUT);

}

// 利用子线程来读取sd卡的图片

class MyThread extends Thread {

@Override

public void run() {

super.run();

//第一张图片

String firstImage = null;

//获取内存卡路径

Uri mImageUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;

//通过内容解析器解析出png和jpeg格式的图片

ContentResolver mContentResolver = ImageSelectActivity.this

.getContentResolver();

Cursor mCursor = mContentResolver.query(mImageUri, null,

MediaStore.Images.Media.MIME_TYPE + "=? or "

+ MediaStore.Images.Media.MIME_TYPE + "=?",

new String[]{"image/png", "image/jpeg"},

MediaStore.Images.Media.DATE_MODIFIED);

//判断是否存在图片

if (mCursor.getCount() > 0) {

mImages.add(null);

while (mCursor.moveToNext()) {

// 获取图片的路径

String path = mCursor.getString(mCursor

.getColumnIndex(MediaStore.Images.Media.DATA));

// 拿到第一张图片的路径

if (firstImage == null)

firstImage = path;

// 获取该图片的文件名

File parentFile = new File(path).getParentFile();

if (parentFile == null)

continue;

//获取到文件地址

String dirPath = parentFile.getAbsolutePath();

imageBean = new ImageBean();

imageBean.setPath(path);

mImages.add(imageBean);

if (mDirPaths.contains(dirPath)) {

continue;

} else {

mDirPaths.add(dirPath);

imageDirBean = new ImageDirBean();

imageDirBean.setDir(dirPath);

imageDirBean.setImagePath(path);

}

int picSize = parentFile.list(new FilenameFilter() {

@Override

public boolean accept(File dir, String filename) {

if (filename.endsWith(".jpg")

|| filename.endsWith(".png")

|| filename.endsWith(".jpeg"))

return true;

return false;

}

}).length;

totalCount += picSize;

imageDirBean.setImageCount(picSize);

imageDirBeans.add(imageDirBean);

if (picSize > mPicsSize) {

mPicsSize = picSize;

}

}

mCursor.close();

mDirPaths = null;

}

// 通知Handler扫描图片完成

mHandler.sendEmptyMessage(0x110);

}

}

}

我们在子线程中读取到sd卡中的文件夹已经文件夹下的图片,并且用两个bean来记录他们,当操作完成之后,通过handler来设置给RecyclerView,我们在来看看adapter

MyAdapter

package com.myimageselectcontainer.adapter;

import android.content.Context;

import android.os.Handler;

import android.support.v7.widget.GridLayoutManager;

import android.support.v7.widget.RecyclerView;

import android.util.DisplayMetrics;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.view.WindowManager;

import android.widget.CheckBox;

import poundButton;

import android.widget.GridLayout;

import android.widget.ImageView;

import android.widget.LinearLayout;

import android.widget.RelativeLayout;

import android.widget.TextView;

import com.bumptech.glide.Glide;

import com.myimageselectcontainer.click.OnChangeListener;

import com.myimageselectcontainer.click.OnItemClickListener;

import com.myimageselectcontainer.R;

import com.myimageselectcontainer.bean.ImageBean;

import java.util.List;

public class MyAdapter extends RecyclerView.Adapter {

//相机布局

private static final int CAMERA_TYPE = 0;

//普通布局

private static final int LAYOUT_TYPE = 1;

private List mList;

private Context mContext;

private float mScreenWidth;

//可选择的图片数,动态控制选择图片

private int mMaxImageCount;

private OnItemClickListener mOnItemClickListener;

private OnChangeListener mOnChangeListener;

private List mSelectImages;

public MyAdapter(Context context, int maxImageCount, List list, OnChangeListener onChangeListener,

OnItemClickListener onItemClickListener) {

//获取屏幕宽度

WindowManager wm = (WindowManager) context

.getSystemService(Context.WINDOW_SERVICE);

DisplayMetrics dm = new DisplayMetrics();

wm.getDefaultDisplay().getMetrics(dm);

mScreenWidth = dm.widthPixels;

this.mContext = context;

this.mMaxImageCount = maxImageCount;

this.mOnItemClickListener = onItemClickListener;

this.mOnChangeListener = onChangeListener;

this.mList = list;

}

@Override

public int getItemViewType(int position) {

if (position == 0) {

return CAMERA_TYPE;

}

return LAYOUT_TYPE;

}

@Override

public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

View view;

if (viewType == CAMERA_TYPE) {

view = LayoutInflater.from(mContext).inflate(R.layout.camera_item, parent, false);

return new CameraViewHolder(view, mOnItemClickListener);

} else {

view = LayoutInflater.from(mContext).inflate(R.layout.image_select_item, parent, false);

return new MyViewHolder(view, mOnItemClickListener, mOnChangeListener);

}

}

@Override

public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, final int position) {

if (viewHolder instanceof MyViewHolder) {

MyViewHolder holder = (MyViewHolder) viewHolder;

holder.cbSelect.setVisibility(View.VISIBLE);

Glide.with(mContext).load(mList.get(position).getPath()).into(holder.imageView);

if (mList.get(position).isSelect()) {

holder.cbSelect.setChecked(true);

holder.canSelect();

} else {

if (mSelectImages == null) {

holder.canSelect();

} else if (mSelectImages.size() == mMaxImageCount) {

holder.cannotSelect();

} else {

holder.canSelect();

}

holder.cbSelect.setChecked(false);

}

if (mMaxImageCount == 1) {

holder.cbSelect.setVisibility(View.GONE);

}

}

}

@Override

public int getItemCount() {

return mList.size();

}

//当选择的图片大于可选择图片数的时候,就不能继续选择

public void notifyData(List list) {

mSelectImages = list;

Handler handler = new Handler();

handler.post(new Runnable() {

@Override

public void run() {

notifyDataSetChanged();

}

});

}

class MyViewHolder extends RecyclerView.ViewHolder

implements View.OnClickListener, CompoundButton.OnCheckedChangeListener {

private ImageView imageView;

private CheckBox cbSelect;

private OnItemClickListener mOnItemClickListener;

private OnChangeListener mOnChangeListener;

public MyViewHolder(View itemView, OnItemClickListener onItemClickListener,

OnChangeListener onChangeListener) {

super(itemView);

this.mOnItemClickListener = onItemClickListener;

this.mOnChangeListener = onChangeListener;

imageView = (ImageView) itemView.findViewById(R.id.imageView);

cbSelect = (CheckBox) itemView.findViewById(R.id.ch_select);

//适配imageView,正方形,宽和高都是屏幕宽度的1/3

RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) imageView.getLayoutParams();

params.width = (int) mScreenWidth / 3 - params.rightMargin - params.leftMargin;

params.height = (int) mScreenWidth / 3 - params.topMargin - params.bottomMargin;

imageView.setLayoutParams(params);

if (onItemClickListener != null) {

itemView.setOnClickListener(this);

}

if (onChangeListener != null) {

cbSelect.setOnCheckedChangeListener(this);

}

}

@Override

public void onClick(View v) {

if (mOnItemClickListener != null) {

mOnItemClickListener.onItemClickListener(v, getAdapterPosition());

}

}

@Override

public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

if (mOnChangeListener != null) {

mOnChangeListener.OnChangeListener(getAdapterPosition(), isChecked);

}

}

public void cannotSelect() {

imageView.setAlpha(0.3f);

cbSelect.setClickable(false);

}

public void canSelect() {

imageView.setAlpha(1.0f);

cbSelect.setClickable(true);

}

}

class CameraViewHolder extends RecyclerView.ViewHolder

implements View.OnClickListener {

private ImageView imageView;

private OnItemClickListener mOnItemClickListener;

public CameraViewHolder(View itemView, OnItemClickListener onItemClickListener) {

super(itemView);

this.mOnItemClickListener = onItemClickListener;

imageView = (ImageView) itemView.findViewById(R.id.imageView);

// 适配imageView,正方形,宽和高都是屏幕宽度的1/3

LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) imageView.getLayoutParams();

params.width = (int) mScreenWidth / 3 - params.rightMargin - params.leftMargin;

params.height = (int) mScreenWidth / 3 - params.topMargin - params.bottomMargin;

imageView.setLayoutParams(params);

if (onItemClickListener != null) {

itemView.setOnClickListener(this);

}

}

@Override

public void onClick(View v) {

if (mOnItemClickListener != null) {

mOnItemClickListener.onItemClickListener(v, getAdapterPosition());

}

}

}

}

很简单,onBindViewHolder里主要做的就是根据ImageBean里的isSelect来判断图片是否选中,在ViewHolder里对图片进行适配,选择完成之后,根据不同数量的图片显示不同的布局,来看看代码

NineImageView

package com.myimageselectcontainer.widget;

import android.content.Context;

import android.util.AttributeSet;

import android.view.View;

import android.view.ViewGroup;

import java.util.ArrayList;

import java.util.List;

public class NineImageView extends ViewGroup {

/**

* 存储所有的View,按行记录

*/

private List> mAllViews = new ArrayList<>();

/**

* 记录每一行的最大高度

*/

private List mLineHeight = new ArrayList<>();

public NineImageView(Context context) {

super(context);

}

public NineImageView(Context context, AttributeSet attrs) {

super(context, attrs);

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

//总宽度和高度

int totalWidth = 0;

int totalHeight = 0;

for (int i = 0; i < getChildCount(); i++) {

View child = getChildAt(i);

measureChild(child, widthMeasureSpec, heightMeasureSpec);

// 得到child的lp

MarginLayoutParams lp = (MarginLayoutParams) child

.getLayoutParams();

// 当前子空间实际占据的宽度

int childWidth = child.getMeasuredWidth() + lp.leftMargin

+ lp.rightMargin;

// 当前子空间实际占据的高度

int childHeight = child.getMeasuredHeight() + lp.topMargin

+ lp.bottomMargin;

if (getChildCount() <= 3) {

totalWidth += childWidth;

totalHeight = childHeight;

} else if (getChildCount() <= 6) {

if (getChildCount() == 4) {

totalWidth = childWidth * 2;

totalHeight = childHeight * 2;

} else {

totalWidth = childWidth * 3;

totalHeight = childHeight * 2;

}

} else if (getChildCount() <= 9) {

totalWidth = childWidth * 3;

totalHeight = childHeight * 3;

}

}

setMeasuredDimension(totalWidth + getPaddingLeft() + getPaddingRight(),

totalHeight + getPaddingTop() + getPaddingBottom());

}

@Override

protected void onLayout(boolean changed, int l, int t, int r, int b) {

//onLayout会被调用多次,为了预防重叠

mAllViews.clear();

mLineHeight.clear();

//获取总宽度

int width = getWidth();

//单行宽度和当行高度

int lineWidth = 0;

int lineHeight = 0;

// 存储每一行所有的childView

List childViews = new ArrayList<>();

int childCount = getChildCount();

// 遍历所有的子view

for (int i = 0; i < childCount; i++) {

View child = getChildAt(i);

MarginLayoutParams lp = (MarginLayoutParams) child

.getLayoutParams();

int childWidth = child.getMeasuredWidth();

int childHeight = child.getMeasuredHeight();

// 如果已经需要换行

if (childWidth + lp.leftMargin + lp.rightMargin + lineWidth > width) {

// 记录这一行所有的View以及最大高度

mLineHeight.add(lineHeight);

// 将当前行的childView保存,然后开启新的ArrayList保存下一行的childView

mAllViews.add(childViews);

lineWidth = 0;// 重置行宽

childViews = new ArrayList<>();

}

// 如果不需要换行,则累加

lineWidth += childWidth + lp.leftMargin + lp.rightMargin;

lineHeight = Math.max(lineHeight, childHeight + lp.topMargin

+ lp.bottomMargin);

childViews.add(child);

}

// 记录最后一行

mLineHeight.add(lineHeight);

mAllViews.add(childViews);

int left = getPaddingLeft();

int top = getPaddingTop();

// 得到总行数

int lineNum = mAllViews.size();

for (int i = 0; i < lineNum; i++) {

// 每一行的所有的views

childViews = mAllViews.get(i);

// 当前行的最大高度

lineHeight = mLineHeight.get(i);

// 遍历当前行所有的子View

for (int j = 0; j < childViews.size(); j++) {

View child = childViews.get(j);

if (child.getVisibility() != View.GONE) {

MarginLayoutParams lp = (MarginLayoutParams) child

.getLayoutParams();

//计算childView的left,top,right,bottom

int childLeft = left + lp.leftMargin;

int childTop = top + lp.topMargin;

int childRight = childLeft + child.getMeasuredWidth();

int childBottom = childTop + child.getMeasuredHeight();

child.layout(childLeft, childTop, childRight, childBottom);

left += child.getMeasuredWidth() + lp.rightMargin

+ lp.leftMargin;

}

}

//换行后,重新从第一个开始,高度累加

left = getPaddingTop();

top += lineHeight;

}

}

@Override

public LayoutParams generateLayoutParams(AttributeSet attrs) {

return new MarginLayoutParams(getContext(), attrs);

}

}

因为我们是根据数量来显示图片布局,也就是说需要自定义的说ViewGroup,onMeasure方法里,根据子view的数量来测量出布局的宽高,它的宽高说由子view的宽高以及数量决定,onLayout就是根据不同的位置来摆放子view,具体思路可以看看我的博客/p/730333c61ea3

这篇博客就是当初写这个自定义ViewGroup时写的,感兴趣的可以去看看

最后我们来看看MainActivity

MainActivity

package com.myimageselectcontainer;

import android.app.Activity;

import android.content.Intent;

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

import android.util.Log;

import android.view.LayoutInflater;

import android.view.View;

import android.widget.Button;

import android.widget.ImageView;

import com.bumptech.glide.Glide;

import com.myimageselectcontainer.bean.ImageBean;

import com.myimageselectcontainer.widget.NineImageView;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

private NineImageView mNineImageView;

private ImageView imageView;

private Button button,button1;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

button = (Button) findViewById(R.id.button);

button1= (Button) findViewById(R.id.button1);

mNineImageView = (NineImageView) findViewById(R.id.nineImageView);

imageView= (ImageView) findViewById(R.id.imageView);

button.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

Intent intent = new Intent(MainActivity.this, ImageSelectActivity.class);

intent.putExtra("select",9);

startActivityForResult(intent, 0);

}

});

button1.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

Intent intent = new Intent(MainActivity.this, ImageSelectActivity.class);

intent.putExtra("select",1);

startActivityForResult(intent, 1);

}

});

}

@Override

protected void onActivityResult(int requestCode, int resultCode, Intent data) {

super.onActivityResult(requestCode, resultCode, data);

if(resultCode==Activity.RESULT_OK){

switch (requestCode){

//多图

case 0:

Bundle bundle = data.getExtras();

ArrayList list = bundle.getParcelableArrayList("selectImages");

LayoutInflater inflater = LayoutInflater.from(this);

//避免重复添加

if (mNineImageView.getChildCount() > 0) {

mNineImageView.removeAllViews();

}

for (int i = 0; i < list.size(); i++) {

ImageView imageView = (ImageView) inflater.inflate(R.layout.nine_image, mNineImageView, false);

Glide.with(this).load(list.get(i).getPath()).into(imageView);

mNineImageView.addView(imageView);

}

break;

//头像

case 1:

byte [] bitmap=data.getByteArrayExtra("bitmap");

Glide.with(this).load(bitmap).into(imageView);

break;

}

}

}

}

不难,相信大家都很容易理解,这里不做过多的解析

最后说说两点需要注意的地方:

如何处理选中图片,图片数量达到最大可选数和取消选中图片的时候,RecyclerView刷新时数据不会错乱

如何处理RecyclerView复用时,数据不会错乱

其实实现的思路时一样,给bean对象添加一个子段,记录当前图片等状态,根据状态来改变view等状态,相信有些人会遇到checkbox复用等时候到坑,当RecyclerView复用的时候,checkbox的OnChangeListener是一定会触发,它有两个状态,选中和没选中,所以,我们需要在复用等时候去做处理,个人认为最好的办法就是在bean中记录状态,不仅能保证数据的正确性,也是最容易处理,万物皆对象嘛

最后附上github地址,感兴趣的可以下载来看下,有问题欢迎提出

(ps:这里没有做6.0权限处理,自己可以添加上去,记得添加权限)

/ReturnYhh/ImageSelectContainer

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。