Foggy day

Android(Kotlin) - question example using assets file - 2 본문

Android

Android(Kotlin) - question example using assets file - 2

jinhan38 2021. 3. 14. 21:34

 

 

6. QuestionFragment

 

Here, i used ViewPager2, RecyclerView, and EventBus.

 

Layout image

 

- fragment_survey_question.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".viewPager.survey.question.SurveyQuestionFragment">

    <TextView
        android:id="@+id/tvSurveyQuestionTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dp"
        android:text="Survey Question"
        android:textColor="@color/black"
        android:textSize="30dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />


    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/vp2SurveyQuestion"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginTop="30dp"
        app:layout_constraintBottom_toTopOf="@+id/constBottomBtn"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/tvSurveyQuestionTitle" />

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/constBottomBtn"
        android:layout_width="match_parent"
        android:layout_height="80dp"
        android:layout_marginHorizontal="30dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/vp2SurveyQuestion">

        <androidx.appcompat.widget.AppCompatButton
            android:id="@+id/btnBack"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginRight="20dp"
            android:text="Back"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/btnNext"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <androidx.appcompat.widget.AppCompatButton
            android:id="@+id/btnNext"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginLeft="20dp"
            android:text="Next"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toEndOf="@+id/btnBack"
            app:layout_constraintTop_toTopOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>


</androidx.constraintlayout.widget.ConstraintLayout>

 

 

- SurveyQuestionFragment

The thing to note here is EventBus. To use EnvetBus, you should add register, unregister, and @Subscribe.

Register EventBus in onCreate, unregister onDestroy, and make a method with @Subscribe annotation, parameter.

class SurveyQuestionFragment : Fragment(), View.OnClickListener {


    lateinit var b: FragmentSurveyQuestionBinding
    lateinit var mContext: Context
    var surveyType = ""
    lateinit var surveyListModel: SurveyListModel
    var currentPage = 0
    var scoreHashMap = HashMap<Int, Int>()
    lateinit var surveyChoiceModel: SurveyChoiceModel
    private lateinit var surveyViewPager2Adapter: SurveyViewPager2Adapter


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        GlobalBus.bus!!.register(this)
        arguments.let {
            surveyType = requireArguments()["surveyType"] as String
            surveyListModel = requireArguments()["surveyData"] as SurveyListModel

        }

    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?,
    ): View? {

        b = FragmentSurveyQuestionBinding.inflate(layoutInflater)

        mContext = requireContext()


        surveyViewPager2Adapter = SurveyViewPager2Adapter(requireActivity(), surveyListModel)

        b.vp2SurveyQuestion.adapter = surveyViewPager2Adapter


        b.vp2SurveyQuestion.isUserInputEnabled = false // false : viewpager2 swipe disable

        setupListener()

        return b.root
    }


    fun setupListener() {
        b.btnBack.setOnClickListener(this)
        b.btnNext.setOnClickListener(this)
    }


    private fun changeViewPagerCurrentPage(value: String) {
        if (value == "plus") {
            currentPage++
        } else {
            if (currentPage > 0) {
                currentPage--
                surveyViewPager2Adapter.uiUpdate(currentPage)
            }
        }
        b.vp2SurveyQuestion.currentItem = currentPage
    }


    override fun onClick(v: View?) {

        when (v!!.id) {

            R.id.btnBack -> {
                if (scoreHashMap.size != 0) {
                    if (scoreHashMap.containsKey(b.vp2SurveyQuestion.currentItem)) {
                        scoreHashMap.remove(b.vp2SurveyQuestion.currentItem)
                    }
                    changeViewPagerCurrentPage("minus")

                } else {
                    Toast.makeText(mContext, "It is firstPage", Toast.LENGTH_SHORT).show()
                }
            }

            R.id.btnNext -> {

                when {

                    scoreHashMap.size == surveyListModel.list.size -> {
                        val bundle = Bundle()
                        bundle.putString("surveyType", surveyType)
                        bundle.putSerializable("resultValue", scoreHashMap)
                        bundle.putParcelable("surveyData", surveyListModel)

                        findNavController().navigate(R.id.action_surveyQuestionFragment_to_surveyResultFragment,
                            bundle)

                    }

                    b.vp2SurveyQuestion.currentItem == scoreHashMap.size - 1 -> {
                        changeViewPagerCurrentPage("plus")
                    }

                    else -> {
                        Toast.makeText(requireActivity(),
                            "Please, choice answer",
                            Toast.LENGTH_SHORT).show()
                    }
                }

            }
        }
    }


    @Subscribe
    fun changeViewPagerPage(surveyChoiceModel: SurveyChoiceModel) {
        this.surveyChoiceModel = surveyChoiceModel

        scoreHashMap[surveyChoiceModel.questionNumber] = surveyChoiceModel.clickedNumber

    }


    override fun onDestroy() {
        GlobalBus.bus!!.unregister(this)
        super.onDestroy()
    }


}

 

 

- GlobalBus 

  implementation 'com.squareup:otto:1.3.7'
object GlobalBus {
    private var sBus: Bus? = null
    val bus: Bus?
        get() {
            if (sBus ==null) sBus = Bus()
            return sBus
        }
}

 

 

- SurveyViewPager2Adapter

class SurveyViewPager2Adapter : FragmentStateAdapter {

    private var surveyListModel: SurveyListModel
    var fragmentArray = ArrayList<SurveyViewPager2Fragment>()

    constructor(
        fragmentActivity: FragmentActivity,
        surveyListModel: SurveyListModel,
    ) : super(fragmentActivity) {
        this.surveyListModel = surveyListModel
        for (i in 0 until surveyListModel.list.size) {
            fragmentArray.add(SurveyViewPager2Fragment().newInstance(surveyListModel.list[i]))
        }
    }


    override fun getItemCount(): Int {
        return surveyListModel.list.size
    }

    override fun createFragment(position: Int): Fragment {
        return fragmentArray[position]
    }

    fun uiUpdate(pageNum: Int) {
        fragmentArray[pageNum].surveyRecyclerViewAdapter.clickedPosition = -1
        fragmentArray[pageNum].surveyRecyclerViewAdapter.notifyDataSetChanged()

    }
}

 

 

- fragment_survey_view_pager2.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".viewPager.survey.question.SurveyViewPager2Fragment">


    <androidx.appcompat.widget.AppCompatTextView
        android:id="@+id/tvQuestionNumber"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:gravity="center"
        android:textColor="@color/black"
        android:textSize="20dp"
        tools:text="questionNumber" />

    <androidx.appcompat.widget.AppCompatTextView
        android:id="@+id/tvQuestion"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textStyle="bold"
        android:layout_marginTop="30dp"
        android:gravity="center_vertical"
        android:paddingStart="30dp"
        android:textColor="@color/black"
        android:textSize="20dp"
        tools:text="질문" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rvSurveyViewPager2"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:overScrollMode="never"
        android:layout_marginTop="30dp"
        tools:itemCount="5"
        tools:listitem="@layout/survey_recyclerview_item" />

</LinearLayout>

 

 

- SurveyViewPager2Fragment

The thing to note here is GlobalBus.post and completion.

If you post some data using GloobalBus, you would get data in changeViewPagerPage() method with Subscribe annotation in SurveyQuestionFragment.

class SurveyViewPager2Fragment : Fragment() {

    private lateinit var questionList: SurveyListModel.List
    lateinit var b: FragmentSurveyViewPager2Binding
    lateinit var surveyRecyclerViewAdapter: SurveyRecyclerViewAdapter

    fun newInstance(
        questionList: SurveyListModel.List,
    ): SurveyViewPager2Fragment {
        val args = Bundle()
        args.putParcelable("questionList", questionList)
        val surveyViewPager2Fragment = SurveyViewPager2Fragment()
        surveyViewPager2Fragment.arguments = args
        return surveyViewPager2Fragment
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        arguments.let {
            questionList = requireArguments()["questionList"] as SurveyListModel.List
        }

    }

    @SuppressLint("SetTextI18n")
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?,
    ): View? {

        b = FragmentSurveyViewPager2Binding.inflate(layoutInflater)


        b.tvQuestionNumber.text = "Question Number ${questionList.number}"
        b.tvQuestion.text = "Q. ${questionList.question}"

        b.rvSurveyViewPager2.apply {

            setHasFixedSize(true)
            layoutManager = LinearLayoutManager(requireContext())
            surveyRecyclerViewAdapter = SurveyRecyclerViewAdapter()
            surveyRecyclerViewAdapter.addItem(questionList)
            adapter = surveyRecyclerViewAdapter

        }



        return b.root

    }

    
    inner class SurveyRecyclerViewAdapter :
        RecyclerView.Adapter<SurveyRecyclerViewAdapter.ItemViewHolder>() {

        private lateinit var questionList: SurveyListModel.List

        var clickedPosition: Int = -1

        fun addItem(questionList: SurveyListModel.List) {
            this.questionList = questionList
        }

        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
            return ItemViewHolder(SurveyRecyclerviewItemBinding.inflate(LayoutInflater.from(parent.context),
                parent, false))
        }

        override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
            holder.bind(questionList, completion = {
                notifyDataSetChanged()
            })
        }

        override fun getItemCount(): Int {
            return questionList.answerList.size
        }


        inner class ItemViewHolder(itemView: SurveyRecyclerviewItemBinding) :
            RecyclerView.ViewHolder(itemView.root) {


            fun bind(
                questionList: SurveyListModel.List,
                completion: () -> Unit,
            ) {

                itemView.apply {

                    tvSurveyQuestionItem.text =
                        questionList.answerList[absoluteAdapterPosition].item

                    tvSurveyQuestionItem.setBackgroundColor(Common.setColor(context,
                        R.color.white))

                    tvSurveyQuestionItem.setOnClickListener {

                        clickedPosition = absoluteAdapterPosition

                        completion()

                        GlobalBus.bus!!.post(
                            SurveyChoiceModel(questionList.number, clickedPosition)
                        )

                    }


                    if (clickedPosition == absoluteAdapterPosition) {
                        tvSurveyQuestionItem.setBackgroundColor(Common.setColor(context,
                            R.color.lightPink))
                    } else {
                        tvSurveyQuestionItem.setBackgroundColor(Common.setColor(context,
                            R.color.white))
                    }


                }
            }

        }

    }

}

 

 

 

 

7. Result Fragment

 

- fragment_survey_result.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".viewPager.survey.result.SurveyResultFragment">

    <androidx.appcompat.widget.AppCompatTextView
        android:id="@+id/appCompatTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="50dp"
        android:text="Question Result"
        android:textColor="@color/black"
        android:textSize="30dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.appcompat.widget.AppCompatTextView
        android:id="@+id/tvSurveyType"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="50dp"
        android:text="타입"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/appCompatTextView" />

    <androidx.appcompat.widget.AppCompatTextView
        android:id="@+id/tvResultScore"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="130dp"
        android:textSize="25dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/tvSurveyType" />


</androidx.constraintlayout.widget.ConstraintLayout>

 

 

- SurveyResultFragment

class SurveyResultFragment : Fragment() {


    lateinit var b: FragmentSurveyResultBinding
    var surveyType = ""
    var scoreHashMap = HashMap<Int, Int>()
    lateinit var surveyListModel: SurveyListModel
    var totalScore = 0

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        arguments?.let {
            surveyType = requireArguments()["surveyType"] as String
            scoreHashMap = requireArguments()["resultValue"] as HashMap<Int, Int>
            surveyListModel = requireArguments()["surveyData"] as SurveyListModel
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?,
    ): View? {


        b = FragmentSurveyResultBinding.inflate(layoutInflater)

        b.tvSurveyType.text = "question type : $surveyType"

        for (i in 0 until scoreHashMap.size) {
            if (surveyListModel.list[i].answerList[scoreHashMap[i + 1]!!].answer) {
                totalScore += 10
            }
        }

        val thread = Thread {
            Handler(Looper.getMainLooper()).post {
                b.tvResultScore.text = "Score : $totalScore"
            }
        }

        thread.start()

        return b.root
    }
}