D8-Android自定义控件之DotNum及item复用问题

mac2022-06-30  106

零、前言

今天写了一个圆点数字控件,效果如下: 最主要是想借此讲一下关于ListView,或RecyclerView的复用问题。 本案例在图片选择中测试,有时间会把我的图形选择小项目写一下,现在先看这个小控件吧。 本控件绘图部分使用我的LogicCanvas绘图库:基础使用在此, 喜欢的话可以到github上看看,顺便给个star 支持属性依次:大圆颜色,圆的高度(原生宽高无效),文字,是否选中,小圆颜色。

toly:z_Dot_BigColor="@color/cornsilk" toly:z_Dot_Height="@dimen/dp_56" toly:z_Dot_text="H" toly:z_Dot_isChecked="false" toly:z_Dot_SmallColor="@color/small_circle" 效果图.gif

一、绘制

1.绘制思路:大圆+小圆+文字+状态控制
成员变量
/** * 大圆高 */ private float mBigHeight = dp2px(20); /** * 大圆颜色 */ private int mBigCircleColor = 0x88000000; /** * 小圆颜色 */ private int mCenterColor = 0x885DFBF9; /** * 文字 */ private String mText = ""; /** * 是否选中 */ private boolean isChecked;
自定义属性
<!--圆点数字自定义控件--> <declare-styleable name="DotNumView"> <!--自定义属性名 和 类型--> <attr name="z_Dot_Height" format="dimension"/> <attr name="z_Dot_text" format="string"/> <attr name="z_Dot_BigColor" format="reference|color"/> <attr name="z_Dot_SmallColor" format="reference|color"/> <attr name="z_Dot_isChecked" format="boolean"/> </declare-styleable> mBigHeight = ta.getDimension(R.styleable.DotNumView_z_Dot_Height, mBigHeight); mBigCircleColor = ta.getColor(R.styleable.DotNumView_z_Dot_BigColor, mBigCircleColor); mCenterColor = ta.getColor(R.styleable.DotNumView_z_Dot_SmallColor, mCenterColor); mText = ta.getString(R.styleable.DotNumView_z_Dot_text); isChecked = ta.getBoolean(R.styleable.DotNumView_z_Dot_isChecked, false); ta.recycle();//一定记得回收!!!
绘制
//获取绘画者 Painter painter = PainterEnum.INSTANCE.getInstance(canvas); float R = mBigHeight / 2; if (isChecked) {//选中状态绘制 painter.draw(sa.deepClone().r(R).ang(360).p(R, -R).fs(mCenterColor)); painter.drawText(st.deepClone() .size((int) (0.6 * mBigHeight)).str(mText) .p(R, R + (int) (0.2 * mBigHeight)).fs(Color.WHITE)); } else {//未中状态绘制 painter.draw(sa.deepClone().r(R).ang(360).p(R, -R).fs(mBigCircleColor)); painter.draw(sa.deepClone().r((float) (0.3 * R)).ang(360).p(R, -R).fs(mCenterColor)); }
测量:取大圆高
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension((int) mBigHeight, (int) mBigHeight); }
更新视图方法:
//属性的get、set方法略 /** * 更新视图 * @param text 文字 * @param checked 是否选中 */ public void update(String text, boolean checked) { mText = text; this.isChecked = checked; invalidate(); }

二、使用:在适配器中获取item的布局时使用

//获取ImageView final ImageView itemIv = holder.getView(R.id.id_iv_photo); //获取DotNumView final DotNumView dotNum = holder.getView(R.id.id_dot_check); //设置默认图片 itemIv.setImageResource(R.drawable.no_photo); //加点灰 itemIv.setColorFilter(Color.parseColor("#11000000")); //加载图片 final String filePath = currentDir + File.separator + data; //通过文件路径加载图片 ImageLoader.getInstance(3, ImageLoader.Type.LIFO).loadImage(mContext, filePath, itemIv); //点击选中,添加遮罩 itemIv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) {//已被选择 //如果文件夹包含了路径 if (mSelectedImg.contains(filePath)) { unSelect();//移除选中 } else { select();//选中 } mTvSelectCount.setText("已选" + mSelectedImg.size() + "张"); } /** * 选中时的操作 */ private void select() { //如果选中的小于9个 if (mSelectedImg.size() < 9) { //将选中的filePath加入集合 mSelectedImg.add(filePath); //更新dotNum的状态 dotNum.update(mSelectedImg.size() + "", true); //item背景加深灰 itemIv.setColorFilter(Color.parseColor("#77000000")); } else { //否则警告 String alert = ResUtils.getString(mCtx, R.string.select_max_count); Toast.makeText(mCtx, alert, Toast.LENGTH_SHORT).show(); } } /** * 移除选中的操作 */ private void unSelect() { mSelectedImg.remove(filePath); itemIv.setColorFilter(Color.parseColor("#22000000")); dotNum.update(mSelectedImg.size() + "", false); mTvSelectCount.setText("已选" + mSelectedImg.size() + "张"); } });

三、复用问题的解决方法:

百度了几个说得云里雾里,不太明白。仔细想一下,还是发挥自己的聪明才智吧 思路:用一个Map装一下选中的点和对应的数字,布局加载是动态判断一下,是否是该position的点,然后更新状态 一开始用List,然后发现需要两个字段,才改成Map 一开始声明后在获取item布局时才初始化map,怎么搞的都不对,然后想想--这是不对的

1.新建mCheckedMap
private Map mCheckedMap = new HashMap<Integer, Integer>();
2.动态恢复
//所有dotNum更新到状态 dotNum.update("", false); //检查mCheckedMap,动态回复状态 if (mCheckedMap.containsKey(position)) { L.d("position:" + position + L.l()); dotNum.update(mCheckedMap.get(position)+"", true); itemIv.setColorFilter(Color.parseColor("#77000000")); }
3.选中加入Map
mCheckedMap.put(position, mSelectedImg.size());
4.不选了从Map移除
mCheckedMap.remove(position);

对于任何复用问题都可以使用这种思路来解决,好了,就到这里


后记、

1.声明:

[1]本文由张风捷特烈原创,转载请注明 [2]欢迎广大编程爱好者共同交流 [3]个人能力有限,如有不正之处欢迎大家批评指证,必定虚心改正 [4]你的喜欢与支持将是我最大的动力

2.连接传送门:

更多安卓技术欢迎访问:安卓技术栈 我的github地址:欢迎star 张风捷特烈个人网站,编程笔记请访问:http://www.toly1994.com

3.联系我

QQ:1981462002 邮箱:1981462002@qq.com 微信:zdl1994328

4.欢迎关注我的微信公众号,最新精彩文章,及时送达:
公众号.jpg

转载于:https://www.cnblogs.com/toly-top/p/9781881.html

最新回复(0)