本片文章是根据项目要求的思路去学习其他的博主改良的思路,思路会有雷同,但是该文确实属于本人原文创作,参考链接会在文章最后展示(啊啊啊啊啊,好官方。。。。)
先说一下项目的功能要求,类似于QQ和微信在举报\投诉用户时的界面,需要要求用户上传相关违规的聊天截图,当然在实现这个功能之前用户是已经将截图保存到手机相册里的,所以这个多图上传的功能就比较简单了,当时在做这个功能的时候本人也是从网上查找了很多资料,我一开始的思路是用代码去调系统相册,然后从系统相册去选择图片,但是运行之后发现图片只能选择一张,不能多张选择,这不符合开发逻辑(主要原因还是自己经验不足,竟然不知道还有图片选择器这个框架),发现图片选择器的相关的框架种类还是有多的的,有原生的也有大牛直接用代码手敲出来的,(但是本人更喜欢原生的,因为大牛的思路并不是人人都能理解的。。。。)所以我就不多说大牛的了,我来例举几个原生的,初级码农还是容易理解的哦,不说了,直接来给大家介绍一下吧!
布局代码:只展示显示图片的那部分代码哈
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<GridView
android:id="@+id/add_pic"
android:layout_width="200dp"
android:layout_height="fill_parent"
android:layout_marginStart="30dp"
android:background="@drawable/input_bg"
android:minHeight="56dp"
android:scrollbars="none"
android:layout_margin="10dp"
android:visibility="gone"
android:gravity="fill_horizontal"
android:stretchMode="columnWidth"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toLeftOf="@id/btn_add_pic"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
//点击该按钮跳转到系统图片选择器中
<Button
android:id="@+id/btn_add_pic"
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_margin="10dp"
android:background="@drawable/add_picture_bg"
android:foreground="@mipmap/add"
android:foregroundGravity="center"
app:backgroundTint="#EFEFEF"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/add_pic"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
按照项目要求做出来的布局是这样式的: 
接下来是java代码的功能实现:
public class btnAddPicOnClickListener implements View.OnClickListener {
@Override
public void onClick(View v) {
//开启多图选择器
Intent intent=new Intent(MainActivity.this, ImagesSelectorActivity.class);
//设置选择图片的最大数量
intent.putExtra(SelectorSettings.SELECTOR_MAX_IMAGE_NUMBER,3);
//设置显示的图像的最小尺寸;过滤微小的图像(主要是图标)
intent.putExtra(SelectorSettings.SELECTOR_MIN_IMAGE_SIZE,100000);
//是否显示相机
intent.putExtra(SelectorSettings.SELECTOR_SHOW_CAMERA,false);
//将当前选定的图像集合作为初始值
intent.putStringArrayListExtra(SelectorSettings.SELECTOR_INITIAL_SELECTED_LIST,imagePaths);
//跳转到多图选择器中
startActivityForResult(intent,REQUEST_CODE);
}
}
//获取图片路径 响应startActivityForResult 并将图片显示到网格布局中去
@SuppressLint("LongLogTag")
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//requestCode:状态标识码
if (requestCode==REQUEST_CODE){
//resultCode:结果标识码
if (resultCode==RESULT_OK){
//从选择器中获取选择结果
ArrayList<String> list=data.getStringArrayListExtra(SelectorSettings.SELECTOR_RESULTS);
//显示选中的图片
loadAdapter(list);
Log.i("jjjj", "list: "+ list.toString());
//网格布局一开始是隐藏的,主要是为了显示的布局好看,在选中了图片之后再给他显示出来
gvPic.setVisibility(View.VISIBLE);
//给网格布局设置最大列数
gvPic.setNumColumns(list.size());
}
}
}
当然网格布局用的就是自定义适配器BaseAdapter代码如下:
private void loadAdapter(ArrayList<String> paths){
//首先清空图片路径的集合
if (imagePaths!=null&& imagePaths.size()>0){
imagePaths.clear();
}
//同样清出掉paths里的没用的数据
if (paths.contains("000000")){
paths.remove("000000");
}
// paths.add("000000");
imagePaths.addAll(paths);
adapter=new GridAdapter(imagePaths,MainActivity.this);
// adapter.notifyDataSetChanged();
gvPic.setAdapter(adapter);
}
private class GridAdapter extends BaseAdapter{
//创建入口参数,数据列表,布局填充器,上下文内容
private ArrayList<String> listUrls;
private LayoutInflater inflater;
private Context context;
public GridAdapter(ArrayList<String> listUrls,Context context){
this.listUrls=listUrls;
this.context=context;
inflater=LayoutInflater.from(MainActivity.this);
}
//获取列表数据有几条
@Override
public int getCount() {
return listUrls.size();
}
//获取列表中的某一条数据
@Override
public Object getItem(int position) {
return listUrls.get(position);
}
//获取列表中的某条数据的位置
@Override
public long getItemId(int position) {
return position;
}
//绘制列表
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//实列化视图持有者类
ViewHolder holder=null;
//对内容视图判空
if (convertView==null){
holder=new ViewHolder();
//填充内容视图(R.layout.add_pic_item为网格布局的子布局)
convertView=inflater.inflate(R.layout.add_pic_item,parent,false);
//将内容视图中的控件id赋值给视图持有者中控件
holder.image=(ImageView) convertView.findViewById(R.id.img_pic);
holder.image.setBackground(getResources().getDrawable(R.drawable.add_picture_bg));
convertView.setTag(holder);
}else {
holder= (ViewHolder) convertView.getTag();
}
//将图片布置到视图中去
final String path=listUrls.get(position);
if (path.equals("000000")){
// holder.image.setImageResource(R.mipmap.ic_launcher);
// listUrls.clear();
listUrls.remove("000000");
}else{
//通过Glide图片缓存机制框架加载图片
Glide.with(MainActivity.this)
.load(path)
.placeholder(R.mipmap.ic_launcher_round)
.error(R.mipmap.ic_launcher_round)
.centerCrop()
.crossFade()
.into(holder.image);
//如果图片数量达到了3张就隐藏添加按钮来控制用户行为
if(listUrls.size()==3){
// Toast.makeText(context, "只能选择3张哦!", Toast.LENGTH_SHORT).show();
btnAddPic.setVisibility(View.GONE);
}
}
return convertView;
}
//创建视图持有者类
class ViewHolder{
ImageView image;
}
}
在写java代码的时候需要注意的点:
1.写java代码时在项目中添加“multiple-images-selector”多图选择器的依赖: 2. 开启图片选择器的时候需要开启读取系统相册的权限以及网络访问权限。 3. 添加图片选择器图片。
//在build.gradle文件中添加,然后同步项目
implementation 'com.zfdang.multiple-images-selector:multiple-images-selector:1.1.5'
//因为是使用的Glide图片加载器显示的图片,所以还需要添加glide的依赖
implementation 'com.github.bumptech.glide:glide:3.7.0'
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
//下面两个权限是你想要在图片选择器中实现拍照所需的权限
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
...
android:name=".DemoApplication"
...
<activity
android:name="com.zfdang.multiple_images_selector.ImagesSelectorActivity"
android:configChanges="orientation|screenSize"/>
</application>
当然了,Android6.0版本后,还需要手动添加程序运行时的读取相册权限,代码如下:
//高版本手动获取权限
public void myPermission() {
int permission = ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (permission != PackageManager.PERMISSION_GRANTED) {
// We don't have permission so prompt the user
ActivityCompat.requestPermissions(
this,
PERMISSIONS_STORAGE,
IMAGE_OPEN
);
}
}
//申请回调
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case IMAGE_OPEN:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_DENIED) {
isGreen = false;
} else {
isGreen = true;
}
break;
}
}
- 应用初始化
public class DemoApplication extends Application
{
@Override
public void onCreate() {
super.onCreate();
// the following line is important
Fresco.initialize(getApplicationContext());
}
}
以上就是我在公司项目中使用的多图选择器的一种原生框架,相对来说比较简单易理解,适合初级开发者,该框架github的源码文档也给大家看一下吧:点击此处进入传送门
当然android中并不是只有这一种框架的,接下来继续介绍吧:
Matisse图片选择器的使用详解 一、简介
- 简单容易上手
- 支持日夜间模式,可以自定义主题
- 自定义选中图片的最大数
- JPEG, PNG, GIF 图片类型的显示
- 支持有序选择图片,也即选择图片的时候会有 1, 2, 3, 4… 样式的 CheckBox;
- 支持自定义筛选,完全自定义筛选规则
- 可以定义图片缩略图的缩放比例。
- 支持横竖屏。Matisse 做了状态保存的工作
- 支持不同的图片加载库,目前支持 Glide 和 Picasso
二、使用步骤 1、 添加依赖 build.gradle文件中代码:
repositories {
jcenter()
}
dependencies {
compile 'com.zhihu.android:matisse:0.5.0-alpha4'
compile 'com.github.bumptech.glide:glide:3.7.0'
}
2、添加相关权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
//android6.0版本权限申请要求同上multiple-images-selector多图选择器
3、启动选择器
如果你不需要点击拍照,而且也对过滤没有要求的话就可以直接使用了 intent跳转到MatisseActivity从你当前的Activity或者Fragment
基本使用方式 1.定义常量
private static final int REQUEST_CODE_CHOOSE = 23;//定义请求码常量
2.启动MatisseActivity
Matisse
.from(MainActivity.this)
.choose(MimeType.allOf())//照片视频全部显示
.countable(true)//有序选择图片
.maxSelectable(9)//最大选择数量为9
.gridExpectedSize(120)//图片显示表格的大小getResources()
.getDimensionPixelSize(R.dimen.grid_expected_size)
.restrictOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)//图像选择和预览活动所需的方向。
.thumbnailScale(0.85f)//缩放比例
.theme(R.style.Matisse_Zhihu)//主题 暗色主题 R.style.Matisse_Dracula
.imageEngine(new GlideEngine())//加载方式
.forResult(REQUEST_CODE_CHOOSE);//请求码
3.接受选择的结果
List<Uri> mSelected;
@Override //接收返回的地址
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_CHOOSE && resultCode == RESULT_OK) {
mSelected = Matisse.obtainResult(data);
Log.d("Matisse", "mSelected: " + mSelected);
}
}
当然如果大家想要试试实现拍照和过滤器的话,可以参考这位大牛的博客,(点击有惊喜)
好啦,最后来看一下运行效果吧:
好了,以上就是本篇文章的内容,都是android的原生框架,会用就可以了,懂逻辑就行,当然我做的介绍也是很简单易懂的,因为只是去实现选择图片,然后把图片显示出来,逻辑好理解,当然如果大家想要进一步探讨对图片的加工处理,裁剪等,可以参考一下:点击进入新世界
隔了那么长时间再次写博客,居然有点手生了,要尽快熟悉起来呀!!!
|