Skip to content

Commit

Permalink
Merge pull request #22 from ryan-conway/fix/ui
Browse files Browse the repository at this point in the history
Fix/UI
  • Loading branch information
ryan-conway authored Nov 25, 2021
2 parents 19ad974 + cbc816b commit 9b8b6c1
Show file tree
Hide file tree
Showing 19 changed files with 302 additions and 211 deletions.
6 changes: 6 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-kapt'
id 'kotlin-parcelize'
id 'dagger.hilt.android.plugin'
id 'androidx.navigation.safeargs.kotlin'
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package com.example.nimblesurveys.login

import android.animation.AnimatorSet
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
Expand Down Expand Up @@ -50,6 +52,7 @@ class LoginFragment : Fragment() {

private fun initUi() {
binding.bLogin.setOnClickListener {
hideKeyboard(it)
val email = binding.etUsername.text.toString()
val password = binding.etPassword.text.toString()
viewModel.login(email, password)
Expand Down Expand Up @@ -89,4 +92,9 @@ class LoginFragment : Fragment() {
}
}
}

private fun hideKeyboard(view: View) {
val inputMethodManager = view.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.hideSoftInputFromWindow(view.windowToken, 0)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,25 @@ package com.example.nimblesurveys.survey

import android.os.Bundle
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.PagerSnapHelper
import androidx.recyclerview.widget.RecyclerView
import com.example.nimblesurveys.databinding.FragmentSurveyBinding
import com.example.nimblesurveys.util.PagerDecorator
import com.example.nimblesurveys.util.PixelUtil
import com.example.nimblesurveys.R
import com.example.nimblesurveys.databinding.FragmentSurveyListBinding
import com.example.nimblesurveys.util.finishOnBackPressed
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.tabs.TabLayoutMediator
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
class SurveyListFragment : Fragment() {

private lateinit var binding: FragmentSurveyBinding
private lateinit var binding: FragmentSurveyListBinding
private val viewModel: SurveyListViewModel by viewModels()

private lateinit var adapter: SurveyListAdapter
private lateinit var adapter: SurveyListFragmentAdapter

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Expand All @@ -36,7 +33,7 @@ class SurveyListFragment : Fragment() {
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentSurveyBinding.inflate(inflater, container, false)
binding = FragmentSurveyListBinding.inflate(inflater, container, false)
return binding.root
}

Expand All @@ -48,32 +45,33 @@ class SurveyListFragment : Fragment() {
viewModel.getSurveys()
}

private fun initUi() {
private fun initUi() = activity?.let { activity ->
binding.shimmer.root.startShimmer()
adapter = SurveyListAdapter()
binding.recycler.setHasFixedSize(true)
binding.recycler.adapter = adapter
PagerSnapHelper().attachToRecyclerView(binding.recycler)
val pixelUtil = PixelUtil(binding.root.context)
val pagerDecorator = PagerDecorator(
pixelUtil.dpToPx(40f),
pixelUtil.dpToPx(32F) + pixelUtil.spToPx(28f * 3f) + pixelUtil.spToPx(18f * 3f)
)
binding.recycler.addItemDecoration(pagerDecorator)
binding.recycler.addOnItemTouchListener(object : RecyclerView.OnItemTouchListener {
override fun onTouchEvent(rv: RecyclerView, e: MotionEvent) = Unit
override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) = Unit
override fun onInterceptTouchEvent(rv: RecyclerView, motionEvent: MotionEvent) =
pagerDecorator.isIndicatorPressing(motionEvent, rv)
})

binding.fab.setOnClickListener { viewModel.viewSurvey(pagerDecorator.activeIndicator) }
val tabPosY = binding.viewpager.height - (
resources.getDimension(R.dimen.activity_margin) +
(resources.getDimension(R.dimen.text_medium) * 2) +
(resources.getDimension(R.dimen.text_large) * 2.5f)
)

binding.tabLayout.y = tabPosY
adapter = SurveyListFragmentAdapter(activity)
binding.viewpager.adapter = adapter
TabLayoutMediator(binding.tabLayout, binding.viewpager) { _, _ -> }.attach()

binding.fab.setOnClickListener {
viewModel.viewSurvey(binding.tabLayout.selectedTabPosition)
}
}

private fun observeData() {
viewModel.surveys.observe(viewLifecycleOwner) {
it?.let {
adapter.submitList(it.map { survey -> survey.toListItem() })
adapter.setItems(it.map { survey -> survey.toListItem() })
viewModel.restorePage?.let { page ->
binding.viewpager.setCurrentItem(page, false)
viewModel.restorePage = null
}
binding.shimmer.root.visibility = View.GONE
binding.fab.show()
}
Expand All @@ -86,6 +84,7 @@ class SurveyListFragment : Fragment() {
}
viewModel.eventViewSurvey.observe(viewLifecycleOwner) {
it?.let {
viewModel.restorePage = binding.tabLayout.selectedTabPosition
val action = SurveyListFragmentDirections.actionSurveyListToDetails(it.id)
findNavController().navigate(action)
viewModel.onDoneViewSurvey()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.example.nimblesurveys.survey

import android.annotation.SuppressLint
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.adapter.FragmentStateAdapter

class SurveyListFragmentAdapter(
fragmentActivity: FragmentActivity
) : FragmentStateAdapter(fragmentActivity) {

private var items = listOf<SurveyListItem>()

override fun getItemCount(): Int = items.size

override fun createFragment(position: Int): Fragment =
SurveyListItemFragment.newInstance(items[position])

@SuppressLint("NotifyDataSetChanged")
fun setItems(items: List<SurveyListItem>) {
this.items = items
notifyDataSetChanged()
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.example.nimblesurveys.survey

import android.os.Parcelable
import kotlinx.parcelize.Parcelize

@Parcelize
data class SurveyListItem(
val id: String,
val name: String,
val description: String,
val coverImageUrl: String,
val coverImageThumbnailUrl: String,
val date: String
): Parcelable
Original file line number Diff line number Diff line change
@@ -1,32 +1,40 @@
package com.example.nimblesurveys.survey

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import androidx.fragment.app.Fragment
import com.bumptech.glide.Glide
import com.example.nimblesurveys.databinding.ItemSurveyBinding
import com.example.nimblesurveys.databinding.FragmentSurveyListItemBinding
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.*
import java.util.concurrent.TimeUnit

class SurveyListAdapter :
ListAdapter<SurveyListItem, SurveyListViewHolder>(SurveyListItemDiffCallback()) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
SurveyListViewHolder.from(parent)
class SurveyListItemFragment: Fragment() {

override fun onBindViewHolder(holder: SurveyListViewHolder, position: Int) =
holder.bind(getItem(position))
}
private lateinit var binding: FragmentSurveyListItemBinding
private var surveyListItem: SurveyListItem? = null

class SurveyListViewHolder(
private val binding: ItemSurveyBinding
) : RecyclerView.ViewHolder(binding.root) {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
surveyListItem = arguments?.getParcelable(ARG_SURVEY_ITEM)
}

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentSurveyListItemBinding.inflate(inflater, container, false)
return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

fun bind(survey: SurveyListItem?) {
survey ?: return
val survey = surveyListItem ?: return

binding.tvDate.text = survey.date.formatDate()
binding.tvDateSubtitle.text = survey.date.getDifference()
Expand Down Expand Up @@ -70,25 +78,16 @@ class SurveyListViewHolder(
}

companion object {
fun from(parent: ViewGroup) = SurveyListViewHolder(
ItemSurveyBinding.inflate(LayoutInflater.from(parent.context), parent, false)
)

private const val ARG_SURVEY_ITEM = "ARG_SURVEY_ITEM"

@JvmStatic
fun newInstance(param: SurveyListItem) =
SurveyListItemFragment().apply {
arguments = Bundle().apply {
putParcelable(ARG_SURVEY_ITEM, param)
}
}

}
}

class SurveyListItemDiffCallback : DiffUtil.ItemCallback<SurveyListItem>() {
override fun areItemsTheSame(oldItem: SurveyListItem, newItem: SurveyListItem) =
oldItem.id == newItem.id

override fun areContentsTheSame(oldItem: SurveyListItem, newItem: SurveyListItem) =
oldItem == newItem
}

data class SurveyListItem(
val id: String,
val name: String,
val description: String,
val coverImageUrl: String,
val coverImageThumbnailUrl: String,
val date: String
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ class SurveyListViewModel @Inject constructor(
private val _eventViewSurvey = MutableLiveData<Survey>()
val eventViewSurvey: LiveData<Survey> get() = _eventViewSurvey

var restorePage: Int? = null

fun getSurveys() = viewModelScope.launch {
withContext(dispatchers.io()) {
val surveyResult = getSurveysUseCase.execute()
Expand Down
Loading

0 comments on commit 9b8b6c1

Please sign in to comment.