Android Kotlin开发问卷调查编辑器
程序员文章站
2022-05-05 18:24:53
...
关于这个作者:
作为一个初学者但是没有女朋友的大学生,所以前所未有的荷尔蒙全投入到代码中,花了5个月学了java开发了springmvc后端,哎不够啊!!我要当全栈大王!但还是止不住我的笨,
因此看在我每天百分之四十的时间都在敲代码的份上,请大家给点支持,有错误欢迎指出。
关于这个项目:
语言:Kotlin
环境:Java1.8
IDE:Android Studio
实现问卷调查编辑器,使用了RecyclerView库,实现了动态控件的添加,数据的绑定。
编辑器有三个按钮,增加陈述题,单选题,多选题,后面两种题型可以增加多个选项,并且这些都会有删除功能。
代码在github里面,如果对大家有帮助,请给个星支持一下呀!!
https://github.com/rendawudi/AndroidRecyclerQuestionnaireMkr
具体代码我就不展示了,我就总结一下我踩的RecyclerView中的巨坑吧(这些坑肯定是因为我经验不够才这样的。。。。)
首先是动态加载控件,我一开始是在Adapter中的onBindViewHolder根据 + 控件监听动态addview实现选项的增加,如图
结果呢
不要忘了ViewHolder的复用功能啊!!每次从数据源list中读取item的时候都会执行onBindViewHolder,而这个方法会从缓存中读取之前已存在的view进行匹配加载,
而我每次都addview后,就会出现每次点击 多选题 这个按钮时,他会加载一个已经加载了一堆选项的题目
因此,我上网查如何禁止复用,holder.setIsRecyclable(false) 简直是我梦中情人
然而呢?????我居然每次点击删除后,程序通过notifyItemChanged(position)刷新时,居然画面有之前选项残留!!!漂浮并固定在屏幕上,点一下还要崩溃!!!!!
好吧 经过许多个小时的尝试,我知道了,布局的加载必须在onCreateViewHolder中进行,因此,我想出个办法,在viewholder中增加选项布局的list
class ViewHolder : RecyclerView.ViewHolder {
var selectionNum = 0
var selectionEdit: ArrayList<EditText>
var selectionButton: ArrayList<Button>
.....
}
并且在onCreateViewHolder中创建view时,根据数据源每个问题的选项的个数的数量加载 选项布局
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
var view: View = LayoutInflater.from(parent.context).inflate(R.layout.question, parent, false)
var selectionEdit: ArrayList<EditText> = ArrayList()
var selectionButton: ArrayList<Button> = ArrayList()
for (i in 0..viewType - 1) {
var linLayout: LinearLayout = view.findViewById(R.id.danxuanLayout) as LinearLayout
val itemLayout: LayoutInflater = LayoutInflater.from(view.context)
var selectionLayout: LinearLayout = itemLayout.inflate(R.layout.selection, null).findViewById(R.id.selectionLayout) as LinearLayout
linLayout.addView(selectionLayout)
selectionEdit.add(selectionLayout.findViewById(R.id.editSelection) as EditText)
selectionButton.add(selectionLayout.findViewById(R.id.delSelection) as Button)
}
var holder: ViewHolder = ViewHolder(view, selectionEdit, selectionButton)
return holder
}
OK!大功告成
接下来一个坑
holder.wendatiButton.setOnClickListener {
if (holder.delBok) {
holder.delBok = false
mQstList.removeAt(position)
notifyItemRemoved(position)
notifyItemChanged(position, itemCount)
Thread(Runnable {
Thread.sleep(200)
holder.delBok = true
}).start()
}
}
删除啊,RecyclerView删除一个item时,会执行一个动画诶!它会慢慢的消失,然而最坑的是什么,它慢就算了,居然还可以点击!!!我去
点一下就崩溃,提示数组越界
所以看上面,我加了个删除判断标志,让他在动画播放时,无法点击删除,然后慢慢点没问题了!!!怎么快速点击呢?网上有个土方法,加个线程,在这个线程结束后也就是动画结束后
就可以点击删除了
然后呢??
什么坑都难不倒我嘛???
看图
怎么我往下翻一下再回一下头,“yyyy”数据就没了啊
我本以为是数据源没有绑定成功,结果查了资料不存在的
原来是EditText按钮监听有毒啊!
我最开始设置EditText是通过TextWatcher 中afterTextChanged,
然而并没有卵用,为啥?
因为只要一删除选项或者问题,这个afterTextChanged就会执行一下,我数据源都没这东西了,它一执行,就崩溃了。。。。。
因此,我要选一个不管出了啥事,监听器只看软键盘或者光标的脸色行事
于是,我开始选了setOnEditorActionListener 中的onEditorAction,判断用户按了一下回车键,不对啊!
我要是用户的话,我要是突然想起有什么东西错了要用手点一下其他选项,没有按回车,那岂不是数据就没了???
不要不要!!
好的,我又选了setOnFocusChangeListener没错,就是她!!!我的天,真是适合我,只要焦点一改变,就把数据读取到数据源中
哇哦!!!
还是有个小bug
那就是你想想,用户写完后,他没有点其他的EditText,他直接点击了保存!那就相当于焦点没有改变啊,就意味着你最后一个选项的数据没有保存啊!
怎么办??
“聪明的我”将保存按钮设置成了
android:focusable="true" android:focusableInTouchMode="true"
哈哈哈哈哈哈
结果变成了点两下才能保存。。。。。
为啥
因为这是焦点模式开启,就像windows系统中的,鼠标点一下是选中,点两下是执行
哦!我的天,用户体验极差,但是这难不倒聪明的我
R.id.jiancha ->{
v.isFocusable = true
v.isFocusableInTouchMode = true
v.requestFocus()
var gson: Gson = Gson()
Log.d("值为",gson.toJson(taskList))
v.isFocusable = false
v.isFocusableInTouchMode = false
}
我将保存按钮点击事件中,设置了开启焦点模式,并将其设置为焦点,POFET,数据全部都保存啦!!!!!!!!!!!!!!!!!
还有其他的notifyItemChanged闪烁啊,什么焦点监听不响应啊之类的,网上百度都有,而我说的这些,大部分网上都没有。。。
下一篇: CountDownLatch的使用