700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 仿微信朋友圈9图上传选择器

仿微信朋友圈9图上传选择器

时间:2020-03-17 14:19:42

相关推荐

仿微信朋友圈9图上传选择器

本人最新公众号《Android百科全书》,汇集了各个公众号的优秀文章,进行分类整理,让大家能够更方便的查阅,希望大家多多支持,来个关注奥。

这个开源项目,之前就想写,一直没有时间整理,这次整理出来,方便以后使用,封装成了库,支持定制,废话不多说,先上图

这是微信的朋友圈发布选择器,一般大家都是用recyclerview或者gridview写一个出来,然后里面再做其他处理,当时我就想,我能不能把它封装成一个控件,然后以后就再也不用写了,得出的结论是能,于是开始封装,封装完成呢,效果图就是下面这个

动图太大上传不了了,那就放出github地址来

单纯的上传图片展示控件ImageShowPicker

这里的readme有动态图,大家可以看下。

废话不多说,大家先来看看怎么使用这个控件

ImageShowPickerView pickerView = (ImageShowPickerView)findViewById(R.id.it_picker_view);final List<ImageBean> list = getItem(position);pickerView.setImageLoaderInterface(new Loader());pickerView.setNewData(list);//展示有动画和无动画//设置监听pickerView.setPickerListener(new ImageShowPickerListener() {@Overridepublic void addOnClickListener(int remainNum) {Toast.makeText(context, "remainNum" + remainNum, Toast.LENGTH_SHORT).show();//在listview或recyclerview才会使用这个list.add(),其他情况都不用list.add(new ImageBean("/res/0604/1029007_0604114552332126_1.jpg"));pickerView.addData(new ImageBean("/res/0604/1029007_0604114552332126_1.jpg"));}@Overridepublic void picOnClickListener(List<ImageShowPickerBean> list, int position, int remainNum) {Toast.makeText(context, list.size() + "========" + position + "remainNum" + remainNum, Toast.LENGTH_SHORT).show();}@Overridepublic void delOnClickListener(int position, int remainNum) {list.remove(position);Toast.makeText(context, "delOnClickListenerremainNum" + remainNum, Toast.LENGTH_SHORT).show();}});//所有设置完毕后调用该方法pickerView.show();//获取所有数据pickerView.getDataList();

声明控件后做一些设置就使用这个控件了,是不是比之前的自己写recyclerview简单多了,再也不用一次次重写了,

这里就不做过多说明,更详细的使用方法,请大家移步github,欢迎star呀

下面,来为大家做一下介绍,看看我们的这个picker到底是怎么封装的,我是通过这几部来封装的

1、分析需求,分析定制目标2、选择实现方法3、编写代码4、完善方法

以上4步就是我这个项目的经历过程,下面一一介绍,并说明原理

1、分析需求,分析定制目标

我们要写的这个选择器,首先他要轻便,就是不抢其他人的工作,不去给开发者带来其他的局限性,so我们就不能直接指定某个图片加载框架,者就是一个需求;其次,我们的选择器应该有多种定制选择,比如微信的选择器就没有删除小按钮,但是其他的app里有,我们就要定制这一个属性,让用户来选择是否显示,还有recyclerview自带的增加删除动画,有的app就想要,有的就不想要,so我们也要提供方法让使用者来定制。

2、选择实现方法

实现方法的选择是个问题,关于图片加载的实现方法,我参考了[banner]这个开源项目的接口处理,十分感谢该项目给我的思路,他的地址如下/youth514/banner,解决了这个问题,还有一个问题困扰我,就是如何获取数据,开始我想用反射来进行操作,但是反射的性能不好,同时使用者混淆代码时,又增添了很多麻烦,因为数据类的参数的不确定性,所以抛弃了这种处理方式,最后选择继承重写方法的这个思路来实现。

3、编写代码

解决了上面两个问题,下面就可以开始写代码了,一点点来说

(1).为view 设置属性

这里一定要注意,自定义控件设置属性后一定要调用typedArray.recycle();这个方法,否则后果你可以试试,爽到飞起

TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ImageShowPickerView);mPicSize = typedArray.getDimensionPixelSize(R.styleable.ImageShowPickerView_pic_size, SizeUtils.getSizeUtils().dp2px(getContext(), PIC_SIZE));isShowDel = typedArray.getBoolean(R.styleable.ImageShowPickerView_is_show_del, true);isShowAnim = typedArray.getBoolean(R.styleable.ImageShowPickerView_is_show_anim, false);mAddLabel = typedArray.getResourceId(R.styleable.ImageShowPickerView_add_label, R.mipmap.image_show_piceker_add);mDelLabel = typedArray.getResourceId(R.styleable.ImageShowPickerView_del_label, R.mipmap.image_show_piceker_del);oneLineShowNum = typedArray.getInt(R.styleable.ImageShowPickerView_one_line_show_num, ONE_LINE_SHOW_NUM);maxNum = typedArray.getInt(R.styleable.ImageShowPickerView_max_num, MAX_NUM);typedArray.recycle();

(2).添加数据时刷新,这里就包括动画的处理了

这只是其中一个方法,写到这里就是为了让大家了解一下,提供个思路

/*** 添加新数据** @param bean* @param <T>*/public <T extends ImageShowPickerBean> void addData(T bean) {if (bean == null) {return;}this.list.add(bean);if (isShowAnim) {if (adapter != null) {adapter.notifyItemChanged(list.size() - 1);adapter.notifyItemChanged(list.size());}} else {adapter.notifyDataSetChanged();}}

(3).重头戏来了,也就是加载图片接口

我们定义这个接口,用来实现加载图片的自定义化,无论你用什么框架,就都可以兼容了,第一眼看,有的人可能没明白怎么处理,其实就是继承接口后重写这个方法,我们在view里只不过把这个方法当成已经写好的方法,调用了一下他的方法名,这样解释是不是就更清晰些,动手试试就懂了

/*** Author 姚智胜* Version V1.0版本* Description: 加载图片接口* Date: /4/6*/public interface ImageLoaderInterface<T extends View> extends Serializable {void displayImage(Context context, String path, T imageView);void displayImage(Context context, @DrawableRes Integer resId, T imageView);T createImageView(Context context);}

(4).RecyclerView的holder处理

把这个放到这里,主要是为了给大家看下onclick事件应该写在哪里,如果写到onBindViewHolder这个方法里,那就是无限的重复创建了,没有理解Holder的作用,我们要在最开始就对他进行创建,然后去复用他

//自定义的ViewHolder,持有每个Item的的所有界面元素public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {public View iv_pic;public ImageView iv_del;private ImageShowPickerPicListener picOnClickListener;public ViewHolder(View view, ImageLoaderInterface imageLoaderInterface, ImageShowPickerPicListener picOnClickListener) {super(view);this.picOnClickListener = picOnClickListener;iv_pic = imageLoaderInterface.createImageView(view.getContext());FrameLayout.LayoutParams pic_params = new FrameLayout.LayoutParams(iconHeight,iconHeight);pic_params.setMargins(10, 10, 10, 10);iv_pic.setLayoutParams(pic_params);iv_del = new ImageView(view.getContext());FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);layoutParams.gravity = Gravity.TOP | Gravity.END;iv_del.setPadding(5, 5, 5, 5);iv_del.setLayoutParams(layoutParams);iv_pic.setId(R.id.iv_image_show_picker_pic);iv_del.setId(R.id.iv_image_show_picker_del);iv_pic.setOnClickListener(this);iv_del.setOnClickListener(this);}@Overridepublic void onClick(View v) {int i = v.getId();if (i == R.id.iv_image_show_picker_pic) {picOnClickListener.onPicClickListener(getLayoutPosition());} else if (i == R.id.iv_image_show_picker_del) {picOnClickListener.onDelClickListener(getLayoutPosition());}}}

(5).意外发现recyclerview的bug

在代码里,我们在adapter内部使用了notifyItemChanged,程序却异常崩溃了,查阅过资料后,发现这个google的bug,所以重写了这个布局管理器,处理这个问题,算是意外收获

/*** Author 姚智胜* Version V1.0版本* Description: 处理recyclerview在adapter内调用notifyItemChanged崩溃的解决方法* Date: /4/15*/public class MyGridLayoutManager extends GridLayoutManager {public MyGridLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {super(context, attrs, defStyleAttr, defStyleRes);}public MyGridLayoutManager(Context context, int spanCount) {super(context, spanCount);}public MyGridLayoutManager(Context context, int spanCount, int orientation, boolean reverseLayout) {super(context, spanCount, orientation, reverseLayout);}@Overridepublic boolean supportsPredictiveItemAnimations() {return false;}@Overridepublic void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {//override this method and implement code as belowtry {super.onLayoutChildren(recycler, state);} catch (Exception e) {e.printStackTrace();}}}

(6).数据类的父类

原理很简单,只是思路问题,我们继承这个父类后,只需重写两个方法,把我们数据类的url,为指定方法赋值就可以了,一个小思路,有可能不是最好的,希望有更好意见的来提下意见

/*** Author 姚智胜* Version V1.0版本* Description: 显示数据类的父类,必须继承于该类* Date: /4/10*/public abstract class ImageShowPickerBean {public String getImageShowPickerUrl() {return setImageShowPickerUrl();}public int getImageShowPickerDelRes() {return setImageShowPickerDelRes();}/*** 为URL赋值,必须重写方法** @return*/public abstract String setImageShowPickerUrl();/*** 为删除label赋值,必须重写方法** @return*/public abstract int setImageShowPickerDelRes();}

4、完善方法

这里要做的其实就是小修小补,比如我们的封装的view ,在最后的时候我又增加了几个自定义属性,让他的可定制性更强,也是在这个步骤里对我们的封装进行最后一次的检查和完善。

以上就是我在写ImageShowPickerView的时候走的几个步骤,会有比我这个更加好的模式,分享出来,就是为了共同进步,和给自己写完一个项目的总结,继续努力,向资深程序员进发!!!

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