Android Kotlin development questionnaire editor

About this author :

As a college student who is a beginner but has no girlfriend , the unprecedented hormones are all put into the code, and it took 5 months to learn java and develop the springmvc backend, alas, it is not enough! ! I want to be the full stack king ! But I still can't stop my stupidity,

Therefore, since I spend 40% of my time typing code every day, please give me some support, and please point out any mistakes.

 

About this project :

Language: Kotlin

Environment: Java1.8

IDE : Android Studio

 

Implement the questionnaire editor, use the RecyclerView library, and realize the addition of dynamic controls and data binding.

 

The editor has three buttons, adding statement questions, multiple-choice questions, and multiple-choice questions . The latter two types of questions can add multiple options, and these will have a delete function.



The code is in github. If it is helpful to you, please give a star to support it! !

https://github.com/rendawudi/AndroidRecyclerQuestionnaireMkr


I won't show the specific code. I will summarize the giant pits in the RecyclerView that I stepped on (these pits must be because of my lack of experience...)

 

The first is to dynamically load the control. I started with the onBindViewHolder in the Adapter according to the + control to monitor the increase of the dynamic addview implementation options, as shown in the figure
 
 
 
 
 
 
the result
 
 
Don't forget the reuse function of ViewHolder ! ! Every time an item is read from the data source list , onBindViewHolder will be executed , and this method will read the existing view from the cache for matching loading .
And after I addview every time , every time I click the button of multiple-choice question, it will load a question that has already loaded a bunch of options


 
 
So, I checked online how to disable reuse, holder.setIsRecyclable(false) is my dream lover
However? ? ? ? ? Every time I click delete, when the program is refreshed through notifyItemChanged(position) , the screen has the previous options left! ! ! Floating and pinned to the screen, and crashing with a click! ! ! ! !
Well, after many hours of trying, I know that the loading of the layout must be done in onCreateViewHolder , so I figured out a way to add a list of options to the layout in the viewholder

 
 
class ViewHolder : RecyclerView.ViewHolder {

        var selectionNum = 0
        var selectionEdit: ArrayList<EditText>
        var selectionButton: ArrayList<Button>
        .....
}
 
 
And when the view is created in onCreateViewHolder , the option layout is loaded according to the number of options for each question in the data source

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! You're done
 
 
next pit

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()
                    }
                }

Delete, when RecyclerView deletes an item , it will perform an animation! It will slowly disappear, but what is the most pitiful thing, even if it is slow, it can still be clicked! ! ! I go
Click to crash, prompting array out of bounds
So look at the above, I added a delete judgment mark, so that he can't click delete when the animation is playing, and then click it slowly, no problem! ! ! How to click quickly? There is a local method on the Internet, add a thread, after the thread ends, that is, after the animation ends
just click delete
 
and then? ?
What pit can't trouble me? ? ?
look at the picture

 
 
Why do I scroll down and look back, the "yyyy" data is gone?
I thought it was because the data source was not bound successfully, but it turned out that the data did not exist.
It turns out that EditText button monitoring is poisonous!
I first set EditText through afterTextChanged in TextWatcher,
But it didn't work, why?
Because as long as the option or question is deleted, this afterTextChanged will be executed, and my data source has no such thing. As soon as it is executed, it crashes . . . . .
So, I'm going to pick one that no matter what happens, the listener just looks at the soft keyboard or the cursor.
 
 
So, I started to select onEditorAction in setOnEditorActionListener, and judged that the user pressed the Enter key, which is not right!
If I were a user, if I suddenly remembered that something was wrong and I had to click on other options with my hand and didn't press Enter, wouldn't the data be lost? ? ?
Don't don't! !
Alright , I chose setOnFocusChangeListener again. That's right, it's her! ! ! Omg, that works for me, just read the data into the data source as soon as the focus changes
Wow! ! !
Still a little bug
That's what you think, after the user finished writing, he didn't click on other EditText, he just clicked save! That means that the focus has not changed, which means that the data of your last option has not been saved !
How to do? ?
"Smart Me" set the save button to
android:focusable="true"
android:focusableInTouchMode="true"
hahahahahaha
The result becomes two clicks to save. . . . .
why
Because this is the focus mode turned on, just like in the windows system, click the mouse once to select, and click twice to execute
Oh! My God, the user experience is very poor, but this is not difficult for the smart me
R.id.jiancha ->{
    v.isFocusable = true
    v.isFocusableInTouchMode = true
    v.requestFocus()
    var gson: Gson = Gson ()
    Log.d("value", gson.toJson(taskList))
    v.isFocusable = false
    v.isFocusableInTouchMode = false
}

In the click event of the save button, I set the open focus mode, and set it as the focus , POFET, and all the data are saved! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !
 
There are other notifyItemChanged flickering, what focus monitoring is not responding, etc. Baidu has it on the Internet, and most of the things I mentioned are not available on the Internet. . .


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325801561&siteId=291194637