Android Kotlin开发问卷调查编辑器

来源:互联网 发布:心理训练软件 编辑:程序博客网 时间:2024/06/05 21:06

关于这个作者

作为一个初学者但是没有女朋友的大学生,所以前所未有的荷尔蒙全投入到代码中,花了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闪烁啊,什么焦点监听不响应啊之类的,网上百度都有,而我说的这些,大部分网上都没有。。。