没有效果图的示例简直就是扯淡

下篇文章实现安卓实现微信朋友圈查看图片功能,跟微信朋友圈效果一样,支持拖拽,支持动画,代码完全开发,完全自定义,可自行修改效果。快去看看吧

控件通过完全自定义的方式实现:具有以下功能:

  1. 完全动态适配手机屏幕宽度;
  2. 单张图片时可以自定义图片大小;
  3. 可自定义多张图片之间的间距;
  4. 可自定义最大限制长度;
  5. 多张图片时根据间距自动计算图片的大小;
  6. 可实现图片的点击功能;
  7. 可实现图片的长按功能;
  8. 大于9张图片时+n布局自动展示;
  9. +n布局可以在代码中自动修改样式;
  10. 支持Glide等多种图片加载框架。

直接看代码吧。

图片加载布局自定义类:
MyCustomImageLayout.class

import android.content.Context;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.SparseArray;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;import com.bumptech.glide.Glide;import java.util.ArrayList;
import java.util.List;/*** 根据ImageWatcher源码修改得来** @author 小口口* 自定义显示图片(可显示一张、多张。如果大于9张最后一张会显示+n)*/
public class MyCustomImageLayout extends FrameLayout implements View.OnClickListener, View.OnLongClickListener {//默认布局最多显示9个,超出显示+n//也可以通过函数setMaxCount()方法设置public int MAX_DISPLAY_COUNT = 9;//image布局private LayoutParams lpChildImage =new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);//单张最大宽高private int mSingleMaxSize;//多张图片间距private int mSpace;//显示view的集合private final List<ImageView> iPictureList = new ArrayList<>();private final SparseArray<ImageView> mVisiblePictureList = new SparseArray<>();//如果超出9个,最后一个+n显示的布局private final TextView tOverflowCount;//图片点击事件回调private Callback mCallback;//图片长按点击事件回调private OnImageLongClickListener clickListener;//图片数据集合private List<String> mImageDataLists = new ArrayList<>();/*** 构造方法(用来处理view初始化)** @param context* @param attrs*/public MyCustomImageLayout(Context context, @Nullable AttributeSet attrs) {super(context, attrs);//获取单张图片默认大小和间距DisplayMetrics mDisplayMetrics = context.getResources().getDisplayMetrics();//本来是要也可以通过配置xml文件实现//这里用的是直接设置的//设置单个图片大小为200dp*200dp//这是多个图片之间的间距为5dpmSingleMaxSize = (int) (TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 200, mDisplayMetrics));mSpace = (int) (TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, mDisplayMetrics));//开始创建9个imageviewfor (int i = 0; i < MAX_DISPLAY_COUNT; i++) {ImageView squareImageView = new SquareImageView(context);squareImageView.setScaleType(ImageView.ScaleType.CENTER_CROP);squareImageView.setVisibility(View.GONE);//new图片的时候添加点击事件和长按事件squareImageView.setOnClickListener(this);squareImageView.setOnLongClickListener(this);addView(squareImageView);iPictureList.add(squareImageView);}//如果图片个数大于9张,这个就是第九个图片上面的+n的view创建tOverflowCount = new TextView(context);tOverflowCount.setTextColor(0xFFFFFFFF);tOverflowCount.setTextSize(24);tOverflowCount.setGravity(Gravity.CENTER);tOverflowCount.setBackgroundColor(0x66000000);tOverflowCount.setVisibility(View.GONE);addView(tOverflowCount);}/*** 这个是单张图片的调用方法(废弃了)** @param list*/public void setUrlData(String list) {mImageDataLists.clear();mImageDataLists.add(list);mSingleMaxSize = (int) (getWidth() * 1f - mSpace);notifyDataChanged();}/*** 设置图片数据方法* 目前是用的list集合,如果是数组的话请自行转* @param list*/public void setUrlListData(List<String> list) {mImageDataLists.clear();mImageDataLists = list;notifyDataChanged();}/*** 数据刷新*/private void notifyDataChanged() {//图片的长度final int urlListSize = mImageDataLists.size();//如果图片不为空并且大于0,显示布局setVisibility(mImageDataLists.size() < 1 ? View.GONE : View.VISIBLE);if (mImageDataLists.size() < 1) {return;}//默认每行显示3个图片int column = 3;//判断每行需要显示的图片数量if (urlListSize == 1) {column = 1;} else if (urlListSize == 4) {column = 2;}//默认显示1行int row = 1;//判断需要显示的行数if (urlListSize > 6) {row = 3;} else if (urlListSize > 3) {row = 2;} else if (urlListSize > 0) {row = 1;}//确认每个图片显示的大小了int imageSize = 0;//如果是一个图片的话,就显示默认的单个图片大小if (urlListSize == 1) {imageSize = mSingleMaxSize;} else if (urlListSize == 2 || urlListSize == 4) {      //如果是两张或者四张的话,每行显示2个,显示2行imageSize = (int) ((getWidth() * 1f - mSpace) / 2);} else {imageSize = (int) ((getWidth() * 1f - mSpace) / 3); //否则显示3个}//将图片大小给到子布局(宽高设置为一样的)lpChildImage.width = imageSize;lpChildImage.height = imageSize;//如果图片数量大于MAX_DISPLAY_COUNT值,显示+n布局tOverflowCount.setVisibility(urlListSize > MAX_DISPLAY_COUNT ? View.VISIBLE : View.GONE);tOverflowCount.setText("+ " + (urlListSize - MAX_DISPLAY_COUNT));tOverflowCount.setLayoutParams(lpChildImage);//加载图片之前,清空已显示的图片集合mVisiblePictureList.clear();//遍历图片集合for (int i = 0; i < iPictureList.size(); i++) {//加载每一个图片final ImageView iPicture = iPictureList.get(i);if (i < urlListSize) {iPicture.setVisibility(View.VISIBLE);mVisiblePictureList.put(i, iPicture);iPicture.setLayoutParams(lpChildImage);iPicture.setBackgroundResource(R.mipmap.icon_myphoto_default);Glide.with(getContext()).load(mImageDataLists.get(i)).into(iPicture);iPicture.setTranslationX((i % column) * (imageSize + mSpace));iPicture.setTranslationY((i / column) * (imageSize + mSpace));//设置tag,在图片点击事件的时候可以当作图片的下标iPicture.setTag(i);} else {iPicture.setVisibility(View.GONE);}//第九个单独处理if (i == MAX_DISPLAY_COUNT - 1) {tOverflowCount.setTranslationX((i % column) * (imageSize + mSpace));tOverflowCount.setTranslationY((i / column) * (imageSize + mSpace));}}//根据自布局显示整体布局的高getLayoutParams().height = imageSize * row + mSpace * (row - 1);}/*** 设置回调接口** @param callback*/public void setOnImageClickListener(Callback callback) {mCallback = callback;}/*** 图片的点击事件** @param v*/@Overridepublic void onClick(View v) {if (mCallback != null) {mCallback.onImageClick((ImageView) v, mVisiblePictureList, mImageDataLists);}}/*** 回调事件接口*/public interface Callback {void onImageClick(ImageView i, SparseArray<ImageView> imageGroupList, List<String> urlList);}/*** 长按事件** @param v* @return*/@Overridepublic boolean onLongClick(View v) {if (clickListener != null) {clickListener.onImageLongClick((ImageView) v, mVisiblePictureList, mImageDataLists);}return true;}/*** 回调长按事件接口*/public interface OnImageLongClickListener {void onImageLongClick(ImageView i, SparseArray<ImageView> imageGroupList, List<String> urlList);}/*** 设置长按事件回调接口** @param callback*/public void setOnImageLongClickListener(OnImageLongClickListener callback) {clickListener = callback;}/*** 一旦计算出宽高,刷新数据** @param w* @param h* @param oldw* @param oldh*/@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);notifyDataChanged();}/*** 设置图片的最大数量** @param count*/public void setMaxCount(int count) {this.MAX_DISPLAY_COUNT = count;}}
import android.content.Context;
import android.util.AttributeSet;/*** 正方形的ImageView* @author 小口口、*/
public class SquareImageView extends androidx.appcompat.widget.AppCompatImageView {public SquareImageView(Context context) {this(context, null);}public SquareImageView(Context context, AttributeSet attrs) {super(context, attrs);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int widthSize = MeasureSpec.getSize(widthMeasureSpec);setMeasuredDimension(widthSize, widthSize);}
}

就这样,代码完了。


Activity这样调用

import android.os.Bundle;import androidx.appcompat.app.AppCompatActivity;import com.google.android.material.snackbar.Snackbar;import java.util.ArrayList;/*** 主界面* @author 小口口、*/
public class MainActivity extends AppCompatActivity {//获取布局MyCustomImageLayout mPhotoGridView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mPhotoGridView = findViewById(R.id.image_layout);//监听点击事件mPhotoGridView.setOnImageClickListener((i, imageGroupList, urlList) -> {//图片下标+1int index = (int)i.getTag() + 1;//单个图片的点击事件Snackbar.make(findViewById(R.id.cl), "你点击了第" + index + "个图片", 3000).show();});//监听长按事件mPhotoGridView.setOnImageLongClickListener((i, imageGroupList, urlList) -> {//图片下标+1int index = (int)i.getTag() + 1;//单个图片的长按事件Snackbar.make(findViewById(R.id.cl), "你长按了第" + index + "个图片", 3000).show();});//点击事件findViewById(R.id.txt_1).setOnClickListener(v -> setImage(1));findViewById(R.id.txt_2).setOnClickListener(v -> setImage(2));findViewById(R.id.txt_3).setOnClickListener(v -> setImage(3));findViewById(R.id.txt_4).setOnClickListener(v -> setImage(4));findViewById(R.id.txt_6).setOnClickListener(v -> setImage(6));findViewById(R.id.txt_9).setOnClickListener(v -> setImage(9));findViewById(R.id.txt_15).setOnClickListener(v -> setImage(15));}/*** 根据要求生成集合个数* @param number*/private void setImage(int number){//动态相册集合ArrayList<String> imageList = new ArrayList<>();for (int i = 0; i < number; i++){imageList.add("https://img2.baidu.com/it/u=4067224682,690721702&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=450");}//设置数据mPhotoGridView.setUrlListData(imageList);}}

activity的xml文件是这样的

<com.cc.imageiwatcherdemo.MyCustomImageLayoutandroid:id="@+id/image_layout"android:layout_width="match_parent"android:layout_height="wrap_content"tools:ignore="MissingConstraints" />

另外还有个图片:icon_myphoto_default.png


呐,代码就这些啦,简单吧~~

附上demo源码。

源码:源码请点这里

如果下不了源码,请联系我。


phone:18588400509
email:mr.cai_cai@foxmail.com

如果有什么问题,欢迎大家指导。并相互联系,希望能够通过文章互相学习。

                                                                         ---财财亲笔

Android实现九宫格图片控件相关推荐

  1. 【Android之SmartImageView图片控件】

    源码地址是https://github.com/loopj/android-smart-image-view,没有sample,本文最后会提供一个sample. smartimageview提供的主要 ...

  2. Android微信九宫格图片展示控件

    版权声明:本文为xing_star原创文章,转载请注明出处! 本文同步自http://javaexception.com/archives/214 Android微信九宫格图片展示控件 半年前,公司产 ...

  3. android 绘制正方形图片,是Android的自定义View-绘制流程-正方形图片控件(SquareImageView)...

    前言 了解View的绘制三大流程后,接下来就要对这些知识做一个实践,首先来实现一个在Android中最为常见的控件--方形图片控件,即让图片在一个方形区域内显示,最常见的场景是在九宫格图片当中. 一般 ...

  4. Android图片控件,跟随列表(recyclerView)的上下滚动而同步平移。

    一个用于放置在RecycleView中的图片控件,其主要功能是跟随列表的上下滚动而上下平移,使得呈现出一种图像相对列表静止的感觉. Overview ScrollingImageView 提供以下特性 ...

  5. android xml图片缩放,Android通过自定义ImageView控件实现图片的缩放和拖动的实现代码...

    概述:通过自定义ImageView控件,在xml布局里面调用自定的组件实现图片的缩放. /** * 自定义的ImageView控制,可对图片进行多点触控缩放和拖动 * * @author qiuwan ...

  6. Android 宫格图控件MultiImageView(RecyclerView适配器中展示不定数量的图片)

    Android 宫格图控件MultiImageView(RecyclerView适配器中展示不定数量的图片) 最近的github上的996ICU在IT界应该很多人听说了,不知道CSDN上什么是最受大家 ...

  7. Android中的基础控件TextView、Button、ImageView、EditText、ProgressBar

    文章目录 1 Android中的基础控件 1.1 控件的通用属性 2 TextView 2.1 TextView的继承关系 2.2 TextView的常用属性 3 EditText 3.1 常用属性 ...

  8. android中的标题栏是什么意思,Android通用标题栏组合控件

    原标题:Android通用标题栏组合控件 快,点击蓝色"字体"关注这个公众号,一起涨姿势 由于项目中经常用到此种组合控件,就封装了下,具体效果看下图,老司机可以绕道哈! 一.主要功 ...

  9. MFC 对话框Picture Control(图片控件)中静态和动态显示Bmp图片

    最近有同学问我如何实现MFC基于对话框在图片控件中加载图片?其实使用MFC显示图片的方法各种各样,但是还是有些同学不知道怎样显示.以前在<数字图像处理>课程中完成的软件都是基于单文档的程序 ...

  10. Android开源库集合(控件)

    RecycleView: RecycleView功能增强 https://github.com/Malinskiy/SuperRecyclerView RecycleView功能增强(拖拽,滑动删除, ...

最新文章

  1. 如何防止果照外泄?自己先上传就OK!扎克伯格这波操作给网友整不会了
  2. 高颜值俄罗斯天才少女加入华为,曾获“编程界的奥林匹克”世界冠军
  3. 操作系统原理第四章:线程
  4. 在没有安装有mvc3的主机上部署asp.net mvc3网站,需要包含的DLL文件
  5. DL之BP:神经网络算法简介之BP算法简介(链式法则/计算图解释)、案例应用之详细攻略
  6. GDB 调试多进程或者多线程应用
  7. 【转】Asp.NET大文件上传开发总结(一)
  8. jQuery:从零开始,DIY一个jQuery(2)
  9. np.random的随机数函数
  10. 【华为云技术分享】原来CTR预估模型的发展有这样的规律
  11. android studio 图表,Android Studio——记账本以及图表可视化实现
  12. C语言和设计模式(之模板模式)
  13. 在cmd里面运行adb命令的时候提示:adb server is out of date. killing...
  14. Python3 实现来宾抽签
  15. Android ImageView点击效果
  16. p系列服务器产品介绍,常用p系列服务器RS6000服务器产品号码对照表.doc
  17. 使用ildasm反编译修改c# dll
  18. 05Echarts - 折线图(Smoothed Line Chart)
  19. Pegasus Serial Port Tool @ Simplicity Version 串口测试工具简化版发布
  20. m3u8切片程序PHP视频切片软件转码系统易语言源码 云转码工具源码

热门文章

  1. 电商双十一调查数据分析报告
  2. 黑魂3无法从服务器获取信息,黑魂3怎么读取信息 | 手游网游页游攻略大全
  3. pandas -- 基础操作(六):数据分组及透视表,df.groupby、pd.pivot,、pd.pivot_table、stack(堆叠)、 unstack(不堆叠)
  4. 测试工程师如何规划自己的职业生涯
  5. 数字传感器:新兴的应用
  6. 基于Python的人脸识别(68个识别点)和焦点人物检测
  7. 如何记忆和使用PNP和NPN?
  8. java图书商城项目_JavaWeb之网上图书商城-框架搭建
  9. 洛谷P4315 月下“毛景树”(树剖+线段树)
  10. cube 设置滴答定时器_基于STM32CubeMX的定时器设置