Fix elevation overlay on pre-lolipop (#475)

This commit is contained in:
Rafał Borcz 2019-09-02 12:56:13 +02:00 committed by Mikołaj Pich
parent bb9ea7eda1
commit 0aac6459f3
24 changed files with 167 additions and 139 deletions

View File

@ -17,11 +17,13 @@ import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.modules.attendance.summary.AttendanceSummaryFragment import io.github.wulkanowy.ui.modules.attendance.summary.AttendanceSummaryFragment
import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.main.MainView import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.utils.dpToPx
import io.github.wulkanowy.utils.setOnItemClickListener import io.github.wulkanowy.utils.setOnItemClickListener
import kotlinx.android.synthetic.main.fragment_attendance.* import kotlinx.android.synthetic.main.fragment_attendance.*
import javax.inject.Inject import javax.inject.Inject
class AttendanceFragment : BaseFragment(), AttendanceView, MainView.MainChildView, MainView.TitledView { class AttendanceFragment : BaseFragment(), AttendanceView, MainView.MainChildView,
MainView.TitledView {
@Inject @Inject
lateinit var presenter: AttendancePresenter lateinit var presenter: AttendancePresenter
@ -35,14 +37,11 @@ class AttendanceFragment : BaseFragment(), AttendanceView, MainView.MainChildVie
fun newInstance() = AttendanceFragment() fun newInstance() = AttendanceFragment()
} }
override val titleStringId: Int override val titleStringId get() = R.string.attendance_title
get() = R.string.attendance_title
override val isViewEmpty: Boolean override val isViewEmpty get() = attendanceAdapter.isEmpty
get() = attendanceAdapter.isEmpty
override val currentStackSize: Int? override val currentStackSize get() = (activity as? MainActivity)?.currentStackSize
get() = (activity as? MainActivity)?.currentStackSize
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -60,19 +59,21 @@ class AttendanceFragment : BaseFragment(), AttendanceView, MainView.MainChildVie
} }
override fun initView() { override fun initView() {
attendanceAdapter.setOnItemClickListener { presenter.onAttendanceItemSelected(it) } attendanceAdapter.setOnItemClickListener(presenter::onAttendanceItemSelected)
attendanceRecycler.run { with(attendanceRecycler) {
layoutManager = SmoothScrollLinearLayoutManager(context) layoutManager = SmoothScrollLinearLayoutManager(context)
adapter = attendanceAdapter adapter = attendanceAdapter
addItemDecoration(FlexibleItemDecoration(context) addItemDecoration(FlexibleItemDecoration(context)
.withDefaultDivider() .withDefaultDivider()
.withDrawDividerOnLastItem(false) .withDrawDividerOnLastItem(false))
)
} }
attendanceSwipe.setOnRefreshListener { presenter.onSwipeRefresh() }
attendanceSwipe.setOnRefreshListener(presenter::onSwipeRefresh)
attendancePreviousButton.setOnClickListener { presenter.onPreviousDay() } attendancePreviousButton.setOnClickListener { presenter.onPreviousDay() }
attendanceNextButton.setOnClickListener { presenter.onNextDay() } attendanceNextButton.setOnClickListener { presenter.onNextDay() }
attendanceNavContainer.setElevationCompat(requireContext().dpToPx(8f))
} }
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {

View File

@ -15,6 +15,7 @@ import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import io.github.wulkanowy.R import io.github.wulkanowy.R
import io.github.wulkanowy.ui.base.BaseFragment import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.modules.main.MainView import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.utils.dpToPx
import io.github.wulkanowy.utils.setOnItemSelectedListener import io.github.wulkanowy.utils.setOnItemSelectedListener
import kotlinx.android.synthetic.main.fragment_attendance_summary.* import kotlinx.android.synthetic.main.fragment_attendance_summary.*
import javax.inject.Inject import javax.inject.Inject
@ -35,11 +36,9 @@ class AttendanceSummaryFragment : BaseFragment(), AttendanceSummaryView, MainVie
fun newInstance() = AttendanceSummaryFragment() fun newInstance() = AttendanceSummaryFragment()
} }
override val titleStringId: Int override val titleStringId get() = R.string.attendance_title
get() = R.string.attendance_title
override val isViewEmpty override val isViewEmpty get() = attendanceSummaryAdapter.isEmpty
get() = attendanceSummaryAdapter.isEmpty
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_attendance_summary, container, false) return inflater.inflate(R.layout.fragment_attendance_summary, container, false)
@ -52,25 +51,26 @@ class AttendanceSummaryFragment : BaseFragment(), AttendanceSummaryView, MainVie
} }
override fun initView() { override fun initView() {
attendanceSummaryRecycler.run { with(attendanceSummaryRecycler) {
layoutManager = SmoothScrollLinearLayoutManager(context) layoutManager = SmoothScrollLinearLayoutManager(context)
adapter = attendanceSummaryAdapter adapter = attendanceSummaryAdapter
} }
attendanceSummarySwipe.setOnRefreshListener { presenter.onSwipeRefresh() }
context?.let { attendanceSummarySwipe.setOnRefreshListener(presenter::onSwipeRefresh)
subjectsAdapter = ArrayAdapter(it, android.R.layout.simple_spinner_item, ArrayList<String>())
subjectsAdapter.setDropDownViewResource(R.layout.item_attendance_summary_subject)
}
attendanceSummarySubjects.run { subjectsAdapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, mutableListOf())
subjectsAdapter.setDropDownViewResource(R.layout.item_attendance_summary_subject)
with(attendanceSummarySubjects) {
adapter = subjectsAdapter adapter = subjectsAdapter
setOnItemSelectedListener { presenter.onSubjectSelected((it as TextView).text.toString()) } setOnItemSelectedListener<TextView> { presenter.onSubjectSelected(it?.text?.toString()) }
} }
attendanceSummarySubjectsContainer.setElevationCompat(requireContext().dpToPx(1f))
} }
override fun updateSubjects(data: ArrayList<String>) { override fun updateSubjects(data: ArrayList<String>) {
subjectsAdapter.run { with(subjectsAdapter) {
clear() clear()
addAll(data) addAll(data)
notifyDataSetChanged() notifyDataSetChanged()
@ -78,9 +78,9 @@ class AttendanceSummaryFragment : BaseFragment(), AttendanceSummaryView, MainVie
} }
override fun updateDataSet(data: List<AttendanceSummaryItem>, header: AttendanceSummaryScrollableHeader) { override fun updateDataSet(data: List<AttendanceSummaryItem>, header: AttendanceSummaryScrollableHeader) {
attendanceSummaryAdapter.apply { with(attendanceSummaryAdapter) {
updateDataSet(data, true) updateDataSet(data, true)
removeAllScrollableHeaders() removeAllScrollableFooters()
addScrollableHeader(header) addScrollableHeader(header)
} }
} }

View File

@ -46,7 +46,7 @@ class AttendanceSummaryPresenter @Inject constructor(
loadData(currentSubjectId, true) loadData(currentSubjectId, true)
} }
fun onSubjectSelected(name: String) { fun onSubjectSelected(name: String?) {
Timber.i("Select attendance summary subject $name") Timber.i("Select attendance summary subject $name")
view?.run { view?.run {
showContent(false) showContent(false)

View File

@ -16,6 +16,7 @@ import io.github.wulkanowy.data.db.entities.Exam
import io.github.wulkanowy.ui.base.BaseFragment import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.main.MainView import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.utils.dpToPx
import io.github.wulkanowy.utils.setOnItemClickListener import io.github.wulkanowy.utils.setOnItemClickListener
import kotlinx.android.synthetic.main.fragment_exam.* import kotlinx.android.synthetic.main.fragment_exam.*
import javax.inject.Inject import javax.inject.Inject
@ -34,11 +35,9 @@ class ExamFragment : BaseFragment(), ExamView, MainView.MainChildView, MainView.
fun newInstance() = ExamFragment() fun newInstance() = ExamFragment()
} }
override val titleStringId: Int override val titleStringId get() = R.string.exam_title
get() = R.string.exam_title
override val isViewEmpty: Boolean override val isViewEmpty get() = examAdapter.isEmpty
get() = examAdapter.isEmpty
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_exam, container, false) return inflater.inflate(R.layout.fragment_exam, container, false)
@ -51,20 +50,21 @@ class ExamFragment : BaseFragment(), ExamView, MainView.MainChildView, MainView.
} }
override fun initView() { override fun initView() {
examAdapter.run { examAdapter.setOnItemClickListener(presenter::onExamItemSelected)
setOnItemClickListener { presenter.onExamItemSelected(it) }
} with(examRecycler) {
examRecycler.run {
layoutManager = SmoothScrollLinearLayoutManager(context) layoutManager = SmoothScrollLinearLayoutManager(context)
adapter = examAdapter adapter = examAdapter
addItemDecoration(FlexibleItemDecoration(context) addItemDecoration(FlexibleItemDecoration(context)
.withDefaultDivider(R.layout.item_exam) .withDefaultDivider(R.layout.item_exam)
.withDrawDividerOnLastItem(false) .withDrawDividerOnLastItem(false))
)
} }
examSwipe.setOnRefreshListener { presenter.onSwipeRefresh() }
examSwipe.setOnRefreshListener(presenter::onSwipeRefresh)
examPreviousButton.setOnClickListener { presenter.onPreviousWeek() } examPreviousButton.setOnClickListener { presenter.onPreviousWeek() }
examNextButton.setOnClickListener { presenter.onNextWeek() } examNextButton.setOnClickListener { presenter.onNextWeek() }
examNavContainer.setElevationCompat(requireContext().dpToPx(8f))
} }
override fun hideRefresh() { override fun hideRefresh() {

View File

@ -17,6 +17,7 @@ import io.github.wulkanowy.ui.modules.grade.details.GradeDetailsFragment
import io.github.wulkanowy.ui.modules.grade.statistics.GradeStatisticsFragment import io.github.wulkanowy.ui.modules.grade.statistics.GradeStatisticsFragment
import io.github.wulkanowy.ui.modules.grade.summary.GradeSummaryFragment import io.github.wulkanowy.ui.modules.grade.summary.GradeSummaryFragment
import io.github.wulkanowy.ui.modules.main.MainView import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.utils.dpToPx
import io.github.wulkanowy.utils.setOnSelectPageListener import io.github.wulkanowy.utils.setOnSelectPageListener
import kotlinx.android.synthetic.main.fragment_grade.* import kotlinx.android.synthetic.main.fragment_grade.*
import javax.inject.Inject import javax.inject.Inject
@ -37,11 +38,9 @@ class GradeFragment : BaseFragment(), GradeView, MainView.MainChildView, MainVie
fun newInstance() = GradeFragment() fun newInstance() = GradeFragment()
} }
override val titleStringId: Int override val titleStringId get() = R.string.grade_title
get() = R.string.grade_title
override val currentPageIndex: Int override val currentPageIndex get() = gradeViewPager.currentItem
get() = gradeViewPager.currentItem
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -64,7 +63,7 @@ class GradeFragment : BaseFragment(), GradeView, MainView.MainChildView, MainVie
} }
override fun initView() { override fun initView() {
pagerAdapter.apply { with(pagerAdapter) {
containerId = gradeViewPager.id containerId = gradeViewPager.id
addFragmentsWithTitle(mapOf( addFragmentsWithTitle(mapOf(
GradeDetailsFragment.newInstance() to getString(R.string.all_details), GradeDetailsFragment.newInstance() to getString(R.string.all_details),
@ -73,14 +72,18 @@ class GradeFragment : BaseFragment(), GradeView, MainView.MainChildView, MainVie
)) ))
} }
gradeViewPager.run { with(gradeViewPager) {
adapter = pagerAdapter adapter = pagerAdapter
offscreenPageLimit = 3 offscreenPageLimit = 3
setOnSelectPageListener { presenter.onPageSelected(it) } setOnSelectPageListener(presenter::onPageSelected)
} }
gradeTabLayout.setupWithViewPager(gradeViewPager) with(gradeTabLayout) {
gradeSwipe.setOnRefreshListener { presenter.onSwipeRefresh() } setupWithViewPager(gradeViewPager)
setElevationCompat(context.dpToPx(4f))
}
gradeSwipe.setOnRefreshListener(presenter::onSwipeRefresh)
} }
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
@ -118,19 +121,19 @@ class GradeFragment : BaseFragment(), GradeView, MainView.MainChildView, MainVie
} }
override fun showSemesterDialog(selectedIndex: Int) { override fun showSemesterDialog(selectedIndex: Int) {
arrayOf(getString(R.string.grade_semester, 1), val choices = arrayOf(
getString(R.string.grade_semester, 2)).also { array -> getString(R.string.grade_semester, 1),
context?.let { getString(R.string.grade_semester, 2)
AlertDialog.Builder(it) )
.setSingleChoiceItems(array, selectedIndex) { dialog, which ->
presenter.onSemesterSelected(which) AlertDialog.Builder(requireContext())
dialog.dismiss() .setSingleChoiceItems(choices, selectedIndex) { dialog, which ->
} presenter.onSemesterSelected(which)
.setTitle(R.string.grade_switch_semester) dialog.dismiss()
.setNegativeButton(android.R.string.cancel) { _, _ -> }
.show()
} }
} .setTitle(R.string.grade_switch_semester)
.setNegativeButton(android.R.string.cancel) { _, _ -> }
.show()
} }
fun onChildRefresh() { fun onChildRefresh() {

View File

@ -19,6 +19,7 @@ import io.github.wulkanowy.data.db.entities.GradeStatistics
import io.github.wulkanowy.ui.base.BaseFragment import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.modules.grade.GradeFragment import io.github.wulkanowy.ui.modules.grade.GradeFragment
import io.github.wulkanowy.ui.modules.grade.GradeView import io.github.wulkanowy.ui.modules.grade.GradeView
import io.github.wulkanowy.utils.dpToPx
import io.github.wulkanowy.utils.getThemeAttrColor import io.github.wulkanowy.utils.getThemeAttrColor
import io.github.wulkanowy.utils.setOnItemSelectedListener import io.github.wulkanowy.utils.setOnItemSelectedListener
import kotlinx.android.synthetic.main.fragment_grade_statistics.* import kotlinx.android.synthetic.main.fragment_grade_statistics.*
@ -37,8 +38,7 @@ class GradeStatisticsFragment : BaseFragment(), GradeStatisticsView, GradeView.G
fun newInstance() = GradeStatisticsFragment() fun newInstance() = GradeStatisticsFragment()
} }
override val isViewEmpty override val isViewEmpty get() = gradeStatisticsChart.isEmpty
get() = gradeStatisticsChart.isEmpty
private lateinit var gradeColors: List<Pair<Int, Int>> private lateinit var gradeColors: List<Pair<Int, Int>>
@ -75,7 +75,7 @@ class GradeStatisticsFragment : BaseFragment(), GradeStatisticsView, GradeView.G
} }
override fun initView() { override fun initView() {
gradeStatisticsChart.run { with(gradeStatisticsChart) {
description.isEnabled = false description.isEnabled = false
setHoleColor(context.getThemeAttrColor(android.R.attr.windowBackground)) setHoleColor(context.getThemeAttrColor(android.R.attr.windowBackground))
setCenterTextColor(context.getThemeAttrColor(android.R.attr.textColorPrimary)) setCenterTextColor(context.getThemeAttrColor(android.R.attr.textColorPrimary))
@ -84,21 +84,21 @@ class GradeStatisticsFragment : BaseFragment(), GradeStatisticsView, GradeView.G
legend.textColor = context.getThemeAttrColor(android.R.attr.textColorPrimary) legend.textColor = context.getThemeAttrColor(android.R.attr.textColorPrimary)
} }
context?.let { subjectsAdapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, mutableListOf())
subjectsAdapter = ArrayAdapter(it, android.R.layout.simple_spinner_item, ArrayList<String>()) subjectsAdapter.setDropDownViewResource(R.layout.item_attendance_summary_subject)
subjectsAdapter.setDropDownViewResource(R.layout.item_attendance_summary_subject)
}
gradeStatisticsSubjects.run { with(gradeStatisticsSubjects) {
adapter = subjectsAdapter adapter = subjectsAdapter
setOnItemSelectedListener { presenter.onSubjectSelected((it as TextView).text.toString()) } setOnItemSelectedListener<TextView> { presenter.onSubjectSelected(it?.text?.toString()) }
} }
gradeStatisticsSwipe.setOnRefreshListener { presenter.onSwipeRefresh() } gradeStatisticsSwipe.setOnRefreshListener(presenter::onSwipeRefresh)
gradeStatisticsSubjectsContainer.setElevationCompat(requireContext().dpToPx(1f))
} }
override fun updateSubjects(data: ArrayList<String>) { override fun updateSubjects(data: ArrayList<String>) {
subjectsAdapter.run { with(subjectsAdapter) {
clear() clear()
addAll(data) addAll(data)
notifyDataSetChanged() notifyDataSetChanged()
@ -202,7 +202,7 @@ class GradeStatisticsFragment : BaseFragment(), GradeStatisticsView, GradeView.G
override fun onSaveInstanceState(outState: Bundle) { override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState) super.onSaveInstanceState(outState)
outState.putBoolean(GradeStatisticsFragment.SAVED_CHART_TYPE, presenter.currentIsSemester) outState.putBoolean(SAVED_CHART_TYPE, presenter.currentIsSemester)
} }
override fun onDestroyView() { override fun onDestroyView() {

View File

@ -62,7 +62,7 @@ class GradeStatisticsPresenter @Inject constructor(
view?.notifyParentRefresh() view?.notifyParentRefresh()
} }
fun onSubjectSelected(name: String) { fun onSubjectSelected(name: String?) {
Timber.i("Select grade stats subject $name") Timber.i("Select grade stats subject $name")
view?.run { view?.run {
showContent(false) showContent(false)
@ -71,8 +71,8 @@ class GradeStatisticsPresenter @Inject constructor(
showEmpty(false) showEmpty(false)
clearView() clearView()
} }
(subjects.singleOrNull { it.name == name }?.name).let { (subjects.singleOrNull { it.name == name }?.name)?.let {
if (it != currentSubjectName) loadData(currentSemesterId, name, currentIsSemester) if (it != currentSubjectName) loadData(currentSemesterId, it, currentIsSemester)
} }
} }

View File

@ -13,6 +13,7 @@ import io.github.wulkanowy.data.db.entities.Homework
import io.github.wulkanowy.ui.base.BaseFragment import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.main.MainView import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.utils.dpToPx
import io.github.wulkanowy.utils.setOnItemClickListener import io.github.wulkanowy.utils.setOnItemClickListener
import kotlinx.android.synthetic.main.fragment_homework.* import kotlinx.android.synthetic.main.fragment_homework.*
import javax.inject.Inject import javax.inject.Inject
@ -31,8 +32,7 @@ class HomeworkFragment : BaseFragment(), HomeworkView, MainView.TitledView {
fun newInstance() = HomeworkFragment() fun newInstance() = HomeworkFragment()
} }
override val titleStringId: Int override val titleStringId get() = R.string.homework_title
get() = R.string.homework_title
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_homework, container, false) return inflater.inflate(R.layout.fragment_homework, container, false)
@ -45,21 +45,21 @@ class HomeworkFragment : BaseFragment(), HomeworkView, MainView.TitledView {
} }
override fun initView() { override fun initView() {
homeworkAdapter.run { homeworkAdapter.setOnItemClickListener(presenter::onHomeworkItemSelected)
setOnItemClickListener { presenter.onHomeworkItemSelected(it) }
}
homeworkRecycler.run { with(homeworkRecycler) {
layoutManager = SmoothScrollLinearLayoutManager(context) layoutManager = SmoothScrollLinearLayoutManager(context)
adapter = homeworkAdapter adapter = homeworkAdapter
addItemDecoration(FlexibleItemDecoration(context) addItemDecoration(FlexibleItemDecoration(context)
.withDefaultDivider() .withDefaultDivider()
.withDrawDividerOnLastItem(false) .withDrawDividerOnLastItem(false))
)
} }
homeworkSwipe.setOnRefreshListener { presenter.onSwipeRefresh() }
homeworkSwipe.setOnRefreshListener(presenter::onSwipeRefresh)
homeworkPreviousButton.setOnClickListener { presenter.onPreviousDay() } homeworkPreviousButton.setOnClickListener { presenter.onPreviousDay() }
homeworkNextButton.setOnClickListener { presenter.onNextDay() } homeworkNextButton.setOnClickListener { presenter.onNextDay() }
homeworkNavContainer.setElevationCompat(requireContext().dpToPx(8f))
} }
override fun updateData(data: List<HomeworkItem>) { override fun updateData(data: List<HomeworkItem>) {
@ -110,7 +110,7 @@ class HomeworkFragment : BaseFragment(), HomeworkView, MainView.TitledView {
override fun onSaveInstanceState(outState: Bundle) { override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState) super.onSaveInstanceState(outState)
outState.putLong(HomeworkFragment.SAVED_DATE_KEY, presenter.currentDate.toEpochDay()) outState.putLong(SAVED_DATE_KEY, presenter.currentDate.toEpochDay())
} }
override fun onDestroyView() { override fun onDestroyView() {

View File

@ -16,6 +16,7 @@ import io.github.wulkanowy.ui.base.BaseFragmentPagerAdapter
import io.github.wulkanowy.ui.modules.main.MainView import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.ui.modules.message.send.SendMessageActivity import io.github.wulkanowy.ui.modules.message.send.SendMessageActivity
import io.github.wulkanowy.ui.modules.message.tab.MessageTabFragment import io.github.wulkanowy.ui.modules.message.tab.MessageTabFragment
import io.github.wulkanowy.utils.dpToPx
import io.github.wulkanowy.utils.setOnSelectPageListener import io.github.wulkanowy.utils.setOnSelectPageListener
import kotlinx.android.synthetic.main.fragment_message.* import kotlinx.android.synthetic.main.fragment_message.*
import javax.inject.Inject import javax.inject.Inject
@ -32,11 +33,9 @@ class MessageFragment : BaseFragment(), MessageView, MainView.TitledView {
fun newInstance() = MessageFragment() fun newInstance() = MessageFragment()
} }
override val titleStringId: Int override val titleStringId get() = R.string.message_title
get() = R.string.message_title
override val currentPageIndex: Int override val currentPageIndex get() = messageViewPager.currentItem
get() = messageViewPager.currentItem
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_message, container, false) return inflater.inflate(R.layout.fragment_message, container, false)
@ -48,7 +47,7 @@ class MessageFragment : BaseFragment(), MessageView, MainView.TitledView {
} }
override fun initView() { override fun initView() {
pagerAdapter.apply { with(pagerAdapter) {
containerId = messageViewPager.id containerId = messageViewPager.id
addFragmentsWithTitle(mapOf( addFragmentsWithTitle(mapOf(
MessageTabFragment.newInstance(RECEIVED) to getString(R.string.message_inbox), MessageTabFragment.newInstance(RECEIVED) to getString(R.string.message_inbox),
@ -57,12 +56,16 @@ class MessageFragment : BaseFragment(), MessageView, MainView.TitledView {
)) ))
} }
messageViewPager.run { with(messageViewPager) {
adapter = pagerAdapter adapter = pagerAdapter
offscreenPageLimit = 2 offscreenPageLimit = 2
setOnSelectPageListener { presenter.onPageSelected(it) } setOnSelectPageListener(presenter::onPageSelected)
}
with(messageTabLayout) {
setupWithViewPager(messageViewPager)
setElevationCompat(context.dpToPx(4f))
} }
messageTabLayout.setupWithViewPager(messageViewPager)
openSendMessageButton.setOnClickListener { presenter.onSendMessageButtonClicked() } openSendMessageButton.setOnClickListener { presenter.onSendMessageButtonClicked() }
} }

View File

@ -17,11 +17,13 @@ import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.main.MainView import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.ui.modules.timetable.completed.CompletedLessonsFragment import io.github.wulkanowy.ui.modules.timetable.completed.CompletedLessonsFragment
import io.github.wulkanowy.utils.dpToPx
import io.github.wulkanowy.utils.setOnItemClickListener import io.github.wulkanowy.utils.setOnItemClickListener
import kotlinx.android.synthetic.main.fragment_timetable.* import kotlinx.android.synthetic.main.fragment_timetable.*
import javax.inject.Inject import javax.inject.Inject
class TimetableFragment : BaseFragment(), TimetableView, MainView.MainChildView, MainView.TitledView { class TimetableFragment : BaseFragment(), TimetableView, MainView.MainChildView,
MainView.TitledView {
@Inject @Inject
lateinit var presenter: TimetablePresenter lateinit var presenter: TimetablePresenter
@ -35,17 +37,13 @@ class TimetableFragment : BaseFragment(), TimetableView, MainView.MainChildView,
fun newInstance() = TimetableFragment() fun newInstance() = TimetableFragment()
} }
override val titleStringId: Int override val titleStringId get() = R.string.timetable_title
get() = R.string.timetable_title
override val roomString: String override val roomString get() = getString(R.string.timetable_room)
get() = getString(R.string.timetable_room)
override val isViewEmpty: Boolean override val isViewEmpty get() = timetableAdapter.isEmpty
get() = timetableAdapter.isEmpty
override val currentStackSize: Int? override val currentStackSize get() = (activity as? MainActivity)?.currentStackSize
get() = (activity as? MainActivity)?.currentStackSize
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -63,11 +61,9 @@ class TimetableFragment : BaseFragment(), TimetableView, MainView.MainChildView,
} }
override fun initView() { override fun initView() {
timetableAdapter.run { timetableAdapter.setOnItemClickListener(presenter::onTimetableItemSelected)
setOnItemClickListener { presenter.onTimetableItemSelected(it) }
}
timetableRecycler.run { with(timetableRecycler) {
layoutManager = SmoothScrollLinearLayoutManager(context) layoutManager = SmoothScrollLinearLayoutManager(context)
adapter = timetableAdapter adapter = timetableAdapter
addItemDecoration(FlexibleItemDecoration(context) addItemDecoration(FlexibleItemDecoration(context)
@ -75,9 +71,12 @@ class TimetableFragment : BaseFragment(), TimetableView, MainView.MainChildView,
.withDrawDividerOnLastItem(false) .withDrawDividerOnLastItem(false)
) )
} }
timetableSwipe.setOnRefreshListener { presenter.onSwipeRefresh() }
timetableSwipe.setOnRefreshListener(presenter::onSwipeRefresh)
timetablePreviousButton.setOnClickListener { presenter.onPreviousDay() } timetablePreviousButton.setOnClickListener { presenter.onPreviousDay() }
timetableNextButton.setOnClickListener { presenter.onNextDay() } timetableNextButton.setOnClickListener { presenter.onNextDay() }
timetableNavContainer.setElevationCompat(requireContext().dpToPx(8f))
} }
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {

View File

@ -12,6 +12,7 @@ import io.github.wulkanowy.data.db.entities.CompletedLesson
import io.github.wulkanowy.ui.base.BaseFragment import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.main.MainView import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.utils.dpToPx
import io.github.wulkanowy.utils.getCompatDrawable import io.github.wulkanowy.utils.getCompatDrawable
import io.github.wulkanowy.utils.setOnItemClickListener import io.github.wulkanowy.utils.setOnItemClickListener
import kotlinx.android.synthetic.main.fragment_timetable_completed.* import kotlinx.android.synthetic.main.fragment_timetable_completed.*
@ -31,11 +32,9 @@ class CompletedLessonsFragment : BaseFragment(), CompletedLessonsView, MainView.
fun newInstance() = CompletedLessonsFragment() fun newInstance() = CompletedLessonsFragment()
} }
override val titleStringId: Int override val titleStringId get() = R.string.completed_lessons_title
get() = R.string.completed_lessons_title
override val isViewEmpty override val isViewEmpty get() = completedLessonsAdapter.isEmpty
get() = completedLessonsAdapter.isEmpty
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_timetable_completed, container, false) return inflater.inflate(R.layout.fragment_timetable_completed, container, false)
@ -48,17 +47,18 @@ class CompletedLessonsFragment : BaseFragment(), CompletedLessonsView, MainView.
} }
override fun initView() { override fun initView() {
completedLessonsAdapter.run { completedLessonsAdapter.setOnItemClickListener(presenter::onCompletedLessonsItemSelected)
setOnItemClickListener { presenter.onCompletedLessonsItemSelected(it) }
}
completedLessonsRecycler.run { with(completedLessonsRecycler) {
layoutManager = SmoothScrollLinearLayoutManager(context) layoutManager = SmoothScrollLinearLayoutManager(context)
adapter = completedLessonsAdapter adapter = completedLessonsAdapter
} }
completedLessonsSwipe.setOnRefreshListener { presenter.onSwipeRefresh() }
completedLessonsSwipe.setOnRefreshListener(presenter::onSwipeRefresh)
completedLessonsPreviousButton.setOnClickListener { presenter.onPreviousDay() } completedLessonsPreviousButton.setOnClickListener { presenter.onPreviousDay() }
completedLessonsNextButton.setOnClickListener { presenter.onNextDay() } completedLessonsNextButton.setOnClickListener { presenter.onNextDay() }
completedLessonsNavContainer.setElevationCompat(requireContext().dpToPx(8f))
} }
override fun updateData(data: List<CompletedLessonItem>) { override fun updateData(data: List<CompletedLessonItem>) {
@ -82,10 +82,8 @@ class CompletedLessonsFragment : BaseFragment(), CompletedLessonsView, MainView.
} }
override fun showFeatureDisabled() { override fun showFeatureDisabled() {
context?.let { completedLessonsInfo.text = getString(R.string.error_feature_disabled)
completedLessonsInfo.text = getString(R.string.error_feature_disabled) completedLessonsInfoImage.setImageDrawable(requireContext().getCompatDrawable(R.drawable.ic_all_close_circle))
completedLessonsInfoImage.setImageDrawable(it.getCompatDrawable(R.drawable.ic_all_close_circle))
}
} }
override fun showProgress(show: Boolean) { override fun showProgress(show: Boolean) {
@ -114,7 +112,7 @@ class CompletedLessonsFragment : BaseFragment(), CompletedLessonsView, MainView.
override fun onSaveInstanceState(outState: Bundle) { override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState) super.onSaveInstanceState(outState)
outState.putLong(CompletedLessonsFragment.SAVED_DATE_KEY, presenter.currentDate.toEpochDay()) outState.putLong(SAVED_DATE_KEY, presenter.currentDate.toEpochDay())
} }
override fun onDestroyView() { override fun onDestroyView() {

View File

@ -1,14 +1,13 @@
package io.github.wulkanowy.ui.modules.grade package io.github.wulkanowy.ui.widgets
import android.content.Context import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import android.view.ViewGroup import android.view.ViewGroup
import com.google.android.material.tabs.TabLayout
/** /**
* @see <a href="https://stackoverflow.com/a/50382854">Tabs don't fit to screen with tabmode=scrollable, Even with a Custom Tab Layout</a> * @see <a href="https://stackoverflow.com/a/50382854">Tabs don't fit to screen with tabmode=scrollable, Even with a Custom Tab Layout</a>
*/ */
class CustomTabLayout : TabLayout { class FittedScrollableTabLayout : MaterialTabLayout {
constructor(context: Context) : super(context) constructor(context: Context) : super(context)

View File

@ -1,11 +1,12 @@
package io.github.wulkanowy.ui.widgets package io.github.wulkanowy.ui.widgets
import android.content.Context import android.content.Context
import android.os.Build.VERSION.SDK_INT
import android.os.Build.VERSION_CODES.LOLLIPOP import android.os.Build.VERSION_CODES.LOLLIPOP
import android.util.AttributeSet import android.util.AttributeSet
import android.widget.LinearLayout import android.widget.LinearLayout
import androidx.annotation.RequiresApi
import androidx.core.view.ViewCompat import androidx.core.view.ViewCompat
import com.google.android.material.elevation.ElevationOverlayProvider
import com.google.android.material.shape.MaterialShapeDrawable import com.google.android.material.shape.MaterialShapeDrawable
class MaterialLinearLayout : LinearLayout { class MaterialLinearLayout : LinearLayout {
@ -21,11 +22,18 @@ class MaterialLinearLayout : LinearLayout {
ViewCompat.setBackground(this, drawable) ViewCompat.setBackground(this, drawable)
} }
@RequiresApi(LOLLIPOP)
override fun setElevation(elevation: Float) { override fun setElevation(elevation: Float) {
super.setElevation(elevation) super.setElevation(elevation)
if (background is MaterialShapeDrawable) { if (background is MaterialShapeDrawable) {
(background as MaterialShapeDrawable).elevation = elevation (background as MaterialShapeDrawable).elevation = elevation
} }
} }
fun setElevationCompat(elevation: Float) {
if (SDK_INT >= LOLLIPOP) {
setElevation(elevation)
} else {
setBackgroundColor(ElevationOverlayProvider(context).getSurfaceColorWithOverlayIfNeeded(elevation))
}
}
} }

View File

@ -0,0 +1,25 @@
package io.github.wulkanowy.ui.widgets
import android.content.Context
import android.os.Build.VERSION.SDK_INT
import android.os.Build.VERSION_CODES.LOLLIPOP
import android.util.AttributeSet
import com.google.android.material.elevation.ElevationOverlayProvider
import com.google.android.material.tabs.TabLayout
open class MaterialTabLayout : TabLayout {
constructor(context: Context) : super(context)
constructor(context: Context, attr: AttributeSet) : super(context, attr)
constructor(context: Context, attr: AttributeSet, defStyleAttr: Int) : super(context, attr, defStyleAttr)
fun setElevationCompat(elevation: Float) {
if (SDK_INT >= LOLLIPOP) {
setElevation(elevation)
} else {
setBackgroundColor(ElevationOverlayProvider(context).getSurfaceColorWithOverlayIfNeeded(elevation))
}
}
}

View File

@ -7,14 +7,15 @@ import android.widget.Spinner
/** /**
* @see <a href="https://stackoverflow.com/a/29602298">How to keep onItemSelected from firing off on a newly instantiated Spinner?</a> * @see <a href="https://stackoverflow.com/a/29602298">How to keep onItemSelected from firing off on a newly instantiated Spinner?</a>
*/ */
inline fun Spinner.setOnItemSelectedListener(crossinline listener: (view: View?) -> Unit) { @Suppress("UNCHECKED_CAST")
inline fun <T : View> Spinner.setOnItemSelectedListener(crossinline listener: (view: T?) -> Unit) {
onItemSelectedListener = object : AdapterView.OnItemSelectedListener { onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onNothingSelected(parent: AdapterView<*>?) {} override fun onNothingSelected(parent: AdapterView<*>?) {}
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
onItemSelectedListener = object : AdapterView.OnItemSelectedListener { onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onNothingSelected(parent: AdapterView<*>?) {} override fun onNothingSelected(parent: AdapterView<*>?) {}
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
listener(view) listener(view as T?)
} }
} }
} }

View File

@ -60,7 +60,6 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="50dp" android:layout_height="50dp"
android:layout_gravity="bottom" android:layout_gravity="bottom"
android:elevation="8dp"
android:orientation="horizontal" android:orientation="horizontal"
tools:ignore="UnusedAttribute"> tools:ignore="UnusedAttribute">

View File

@ -15,7 +15,6 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?android:windowBackground" android:background="?android:windowBackground"
android:elevation="1dp"
android:padding="5dp" android:padding="5dp"
android:visibility="invisible" android:visibility="invisible"
tools:ignore="UnusedAttribute" tools:ignore="UnusedAttribute"

View File

@ -60,7 +60,6 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="50dp" android:layout_height="50dp"
android:layout_gravity="bottom" android:layout_gravity="bottom"
android:elevation="8dp"
android:orientation="horizontal" android:orientation="horizontal"
tools:ignore="UnusedAttribute"> tools:ignore="UnusedAttribute">

View File

@ -5,12 +5,11 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<io.github.wulkanowy.ui.modules.grade.CustomTabLayout <io.github.wulkanowy.ui.widgets.FittedScrollableTabLayout
android:id="@+id/gradeTabLayout" android:id="@+id/gradeTabLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="48dp" android:layout_height="48dp"
android:background="?colorSurface" android:background="?colorSurface"
android:elevation="4dp"
android:visibility="invisible" android:visibility="invisible"
app:tabMode="scrollable" app:tabMode="scrollable"
app:tabSelectedTextColor="?colorPrimary" app:tabSelectedTextColor="?colorPrimary"

View File

@ -11,7 +11,6 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?android:windowBackground" android:background="?android:windowBackground"
android:elevation="1dp"
android:padding="5dp" android:padding="5dp"
android:visibility="invisible" android:visibility="invisible"
tools:ignore="UnusedAttribute" tools:ignore="UnusedAttribute"

View File

@ -60,7 +60,6 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="50dp" android:layout_height="50dp"
android:layout_gravity="bottom" android:layout_gravity="bottom"
android:elevation="8dp"
android:orientation="horizontal" android:orientation="horizontal"
tools:ignore="UnusedAttribute"> tools:ignore="UnusedAttribute">

View File

@ -5,12 +5,11 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<com.google.android.material.tabs.TabLayout <io.github.wulkanowy.ui.widgets.MaterialTabLayout
android:id="@+id/messageTabLayout" android:id="@+id/messageTabLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="48dp" android:layout_height="48dp"
android:background="?colorSurface" android:background="?colorSurface"
android:elevation="4dp"
android:visibility="invisible" android:visibility="invisible"
app:tabGravity="fill" app:tabGravity="fill"
app:tabIndicatorColor="?colorPrimary" app:tabIndicatorColor="?colorPrimary"

View File

@ -60,7 +60,6 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="50dp" android:layout_height="50dp"
android:layout_gravity="bottom" android:layout_gravity="bottom"
android:elevation="8dp"
android:orientation="horizontal" android:orientation="horizontal"
tools:ignore="UnusedAttribute"> tools:ignore="UnusedAttribute">

View File

@ -64,7 +64,6 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="50dp" android:layout_height="50dp"
android:layout_gravity="bottom" android:layout_gravity="bottom"
android:elevation="8dp"
android:orientation="horizontal" android:orientation="horizontal"
tools:ignore="UnusedAttribute"> tools:ignore="UnusedAttribute">