Foggy day
Android(Kotlin) - question example using assets file - 2 본문
6. QuestionFragment
Here, i used ViewPager2, RecyclerView, and EventBus.
- 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
}
}
'Android' 카테고리의 다른 글
Android(Kotlin) - RxKotlin -1 : PublishSubject (0) | 2021.03.23 |
---|---|
Android - getSupportFragmentManager, getChildFragmentManager (0) | 2021.03.21 |
Android(Kotlin) - question example using assets file - 1 (0) | 2021.03.14 |
Android(안드로이드) - EventBus Example (0) | 2021.03.10 |
Android(java) - exoplayer2 (0) | 2021.03.05 |