Android Kotlin开发问卷调查编辑器

关于这个作者

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


猜你喜欢

转载自blog.csdn.net/renhaopeng/article/details/77975822