Skip to content

Commit

Permalink
Add MonthHeight example for the year calendar
Browse files Browse the repository at this point in the history
  • Loading branch information
kizitonwose committed Jul 30, 2024
1 parent fd1f276 commit 7a3ca08
Show file tree
Hide file tree
Showing 6 changed files with 243 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ class CalendarViewOptionsAdapter(val onClick: (ExampleItem) -> Unit) :
R.string.example_9_subtitle,
horizontal,
) { Example9Fragment() },
ExampleItem(
R.string.example_10_title,
R.string.example_10_subtitle,
horizontal,
) { Example10Fragment() },
)

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HomeOptionsViewHolder {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
package com.kizitonwose.calendar.sample.view

import android.os.Bundle
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import android.widget.TextView
import androidx.appcompat.widget.Toolbar
import androidx.core.view.children
import androidx.core.view.updatePaddingRelative
import com.kizitonwose.calendar.core.CalendarDay
import com.kizitonwose.calendar.core.CalendarMonth
import com.kizitonwose.calendar.core.DayPosition
import com.kizitonwose.calendar.core.firstDayOfWeekFromLocale
import com.kizitonwose.calendar.sample.R
import com.kizitonwose.calendar.sample.databinding.Example10FragmentBinding
import com.kizitonwose.calendar.sample.databinding.Example9CalendarDayBinding
import com.kizitonwose.calendar.sample.databinding.Example9CalendarMonthHeaderBinding
import com.kizitonwose.calendar.sample.shared.displayText
import com.kizitonwose.calendar.view.MarginValues
import com.kizitonwose.calendar.view.MonthDayBinder
import com.kizitonwose.calendar.view.MonthHeaderFooterBinder
import com.kizitonwose.calendar.view.ViewContainer
import java.time.LocalDate
import java.time.Year

class Example10Fragment : BaseFragment(R.layout.example_10_fragment), HasToolbar, HasBackButton {
override val toolbar: Toolbar
get() = binding.exTenToolbar

override val titleRes: Int = R.string.example_10_title

private lateinit var binding: Example10FragmentBinding

private var selectedDate: LocalDate? = null

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setHasOptionsMenu(true)
binding = Example10FragmentBinding.bind(view)
val config = requireContext().resources.configuration
val isTablet = config.smallestScreenWidthDp >= 600

configureBinders(isTablet)

binding.exTenToolbar.updatePaddingRelative(end = dpToPx(if (isTablet) 42 else 6, requireContext()))

binding.exTenCalendar.apply {
val currentYear = Year.now()
monthVerticalSpacing = dpToPx(20, requireContext())
monthHorizontalSpacing = dpToPx(if (isTablet) 52 else 10, requireContext())
yearMargins = MarginValues(
vertical = dpToPx(if (isTablet) 20 else 6, requireContext()),
horizontal = dpToPx(if (isTablet) 52 else 14, requireContext()),
)
yearScrollListener = { year ->
binding.exTenToolbar.title = year.year.value.toString()
}
setup(
currentYear.minusYears(100),
currentYear.plusYears(100),
firstDayOfWeekFromLocale(),
)
scrollToYear(currentYear)
}
}

private fun configureBinders(isTablet: Boolean) {
val calendarView = binding.exTenCalendar

class DayViewContainer(view: View) : ViewContainer(view) {
// Will be set when this container is bound. See the dayBinder.
lateinit var day: CalendarDay
val textView = Example9CalendarDayBinding.bind(view).exNineDayText.apply {
textSize = if (isTablet) 10f else 9f
}

init {
textView.setOnClickListener {
if (day.position == DayPosition.MonthDate) {
if (selectedDate == day.date) {
selectedDate = null
calendarView.notifyDayChanged(day)
} else {
val oldDate = selectedDate
selectedDate = day.date
calendarView.notifyDateChanged(day.date)
oldDate?.let { calendarView.notifyDateChanged(oldDate) }
}
}
}
}
}

calendarView.dayBinder = object : MonthDayBinder<DayViewContainer> {
override fun create(view: View) = DayViewContainer(view)
override fun bind(container: DayViewContainer, data: CalendarDay) {
container.day = data
val textView = container.textView
textView.text = data.date.dayOfMonth.toString()

if (data.position == DayPosition.MonthDate) {
textView.makeVisible()
when (data.date) {
selectedDate -> {
textView.setTextColorRes(R.color.example_2_white)
textView.setBackgroundResource(R.drawable.example_2_selected_bg)
}

else -> {
textView.setTextColorRes(R.color.example_2_black)
textView.background = null
}
}
} else {
textView.makeInVisible()
}
}
}

val monthNameTypeFace = Typeface.semiBold(requireContext())

class MonthViewContainer(view: View) : ViewContainer(view) {
val bind = Example9CalendarMonthHeaderBinding.bind(view)
val textView = bind.exNineMonthHeaderText.apply {
setTypeface(monthNameTypeFace)
textSize = if (isTablet) 16f else 14f
updatePaddingRelative(start = dpToPx(if (isTablet) 10 else 6, requireContext()))
}
val legendLayout = bind.legendLayout.root
}

val legendTypeface = Typeface.medium(requireContext())

calendarView.monthHeaderBinder =
object : MonthHeaderFooterBinder<MonthViewContainer> {
override fun create(view: View) = MonthViewContainer(view)
override fun bind(container: MonthViewContainer, data: CalendarMonth) {
container.textView.text = data.yearMonth.month.displayText(short = false)
// Setup each header day text if we have not done that already.
if (container.legendLayout.tag == null) {
container.legendLayout.tag = true
val daysOfWeek = data.weekDays.first().map { it.date.dayOfWeek }
container.legendLayout.children.map { it as TextView }
.forEachIndexed { index, tv ->
tv.text = daysOfWeek[index].displayText(uppercase = true, narrow = true)
tv.setTextColorRes(R.color.example_3_black)
tv.textSize = if (isTablet) 14f else 11f
tv.setTypeface(legendTypeface)
}
}
}
}

}

override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.example_10_menu, menu)
}

override fun onOptionsItemSelected(item: MenuItem): Boolean {
val visibleYear = binding.exTenCalendar.findFirstVisibleYear()?.year
?: return super.onOptionsItemSelected(item)
return when (item.itemId) {
R.id.menuItemPrevious -> {
binding.exTenCalendar.smoothScrollToYear(visibleYear.minusYears(1))
true
}

R.id.menuItemNext -> {
binding.exTenCalendar.smoothScrollToYear(visibleYear.plusYears(1))
true
}

else -> super.onOptionsItemSelected(item)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ class Example9Fragment : BaseFragment(R.layout.example_9_fragment), HasToolbar,

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setHasOptionsMenu(true)
binding = Example9FragmentBinding.bind(view)
val config = requireContext().resources.configuration
val isTablet = config.smallestScreenWidthDp >= 600
Expand Down
38 changes: 38 additions & 0 deletions sample/src/main/res/layout/example_10_fragment.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:background="@color/white"
android:clickable="true"
android:focusable="true"
android:orientation="vertical"
tools:context=".view.Example10Fragment">

<com.google.android.material.appbar.AppBarLayout
android:id="@+id/exTenAppBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">

<androidx.appcompat.widget.Toolbar
android:id="@+id/exTenToolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:popupTheme="@style/AppTheme.PopupOverlay"
app:title="@string/example_10_title" />

</com.google.android.material.appbar.AppBarLayout>

<com.kizitonwose.calendar.view.YearCalendarView
android:id="@+id/exTenCalendar"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:cv_dayViewResource="@layout/example_9_calendar_day"
app:cv_monthHeaderResource="@layout/example_9_calendar_month_header"
app:cv_orientation="horizontal"
app:cv_scrollPaged="true"
app:cv_monthHeight="fill"
app:cv_daySize="square" />
</LinearLayout>
19 changes: 19 additions & 0 deletions sample/src/main/res/menu/example_10_menu.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<menu 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">

<item
android:id="@+id/menuItemPrevious"
android:icon="@drawable/ic_chevron_left"
android:title=""
app:iconTint="@color/white"
app:showAsAction="always"
tools:ignore="AlwaysShowAction" />
<item
android:id="@+id/menuItemNext"
android:icon="@drawable/ic_chevron_right"
android:title=""
app:iconTint="@color/white"
app:showAsAction="always" />
</menu>
2 changes: 2 additions & 0 deletions sample/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
<string name="example_8_subtitle">Fullscreen calendar, header and footer views, paged horizontal scrolling, shows the \"Rectangle\" DaySize option.</string>
<string name="example_9_title">Example 9</string>
<string name="example_9_subtitle">Vertical year calendar - Hidden past months with continuous scroll. Best suited for large screens.</string>
<string name="example_10_title">Example 10</string>
<string name="example_10_subtitle">Horizontal year calendar - Paged scrolling, shows the \"Fill\" implementation of MonthHeight property. Best suited for large screens.</string>
<string name="save">Save</string>
<string name="close">Close</string>
<string name="example_3_input_dialog_title">Enter event title</string>
Expand Down

0 comments on commit 7a3ca08

Please sign in to comment.