My other application is made with this library : https://github.com/axellaffite/ut3_calendar
Step 1. Add the Jitpack repository to you build file :
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
Step 2. Add the Yoda dependency to your project Gradle file :
You must replace version_number
with this version : .
implementation 'com.github.axellaffite:yoda:version_number'
This library provides functionalities to display a timetable.
Let's see together how to use it !
Ensure you have implemented the library correctly.
You must create a layout where you'll store the Day view.
The Day view will expand to fit it's content so you may want to include it into a ScrollView.
[...]
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
<com.elzozor.yoda.Day
android:id="@+id/day_yoda"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</ScrollView>
[...]
There a 4 options that are available on the Day component :
- start : Defines the start hour of the Day
- end : Defines the start hour of the Day
- fit : Defines how the Day will fit the Events hours
- display : Defines how the Day will expand its height
- hoursFormat : Defines how the hours are displayed
Fit defines how the Day component will adapt its hours to the Event ones. There are 3 options available :
- AUTO : Will fit the hours to the Event ones. For example if the earlier hour is 8 and the latest is 10, the Day hours will start at 8 and end at 11 (end + 1).
- BOUNDS_ADAPTIVE : Will fit the hours to the parameters start and end but will expand them if there are Events that are not in that bound.
- BOUNDS_STRICT : Will fit the hours to the parameters start and end not matter if there are Events that do not fit in it.
Once you've created the layout that will store your events, you should provide a view that will display them.
The Yoda library is actually made in such a way that it provides functionalities to find the proper events positions but you must provide a way to show them.
So go ahead and create yours !
Here is a very basic example :
<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/EventCardView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="@android:color/white"
android:textSize="14sp"
android:textStyle="bold" />
And here is the class associated with it :
[A package]
[Some imports]
class EventCardView(context: Context,
attrs: AttributeSet?)
: TextView(context, attrs) {
constructor(context: Context) : this(context, null)
init {
inflate(context, R.layout.event, this)
}
fun setEvent(event: Event) {
this.event = event
setText(event.title)
}
}
As you may have seen, the setEvents function takes two parameters, a LifecycleCoroutineScope
and a list of EventWrapper.
We will get into the first parameter later, for now, let's focus on the second one.
As it takes an EventWrapper, you must provide a class that extends this one.
Three functions must be overriden as they are abstract.
Here is an example :
[A package]
[Some imports]
data class Event (
val begin : Date,
val end : Date,
val title : String,
val description : String) : EventWrapper()
{
override fun begin() = begin
override fun end() = end
override fun isAllDay() = (begin == end)
}
You can now simply pass a list of your Event class to the setEvents
function of the Day layout !
You must provide a way for the Day layout to build the views, otherwise it will throw an Exception.
You do it by assigning the variables to a value.
lateinit var dayBuilder: (Context, EventWrapper, Int, Int, Int, Int) -> Pair<Boolean, View>
This function defines how the Events views must be constructed. The parameters are :
- A context given by the function
- An EventWrapper that contains the current event to build
- x, y, w, h which are the position and size of the EventView.
The return of this function is a Pair that contains in first argument if the constraints have been set on the returned View ( position and size ) and in second argument the constructed view.
lateinit var allDayBuilder: (List<EventWrapper>) -> View
This function constructs the "all day view" where are display the events that are affiliated to the entire day and not only to a specific time.
Put another way, there are the EventWrappers that returns true to the isAllDay()
function.
lateinit var emptyDayBuilder: () -> View
This function simply construct the view that is displayed when the day is empty. Simply do want you want !
Here are some examples :
// day_yoda is the view that we are accessing by it's id.
// Here is an exemple where we don't set the layout params
day_yoda.dayBuilder = { context, event, x, y, width, height ->
Pair(false, EventCardView(context).apply {
setBackgroundColor(Color.parseColor(randomColor()))
setEvent(event as Event)
})
}
// And here is an exemple where we set the layout params
day_yoda.setViewBuilder { context, event, x, y, width, height ->
Pair(true, EventCardView(context).apply {
setBackgroundColor(Color.parseColor(randomColor()))
setEvent(event as Event)
val params = RelativeLayout.LayoutParams(width, height)
params.leftMargin = x
params.topMargin = y
layoutParams = params
})
}
// Creates a vertical LinearLayout that
// contains multiple EventCardViews
day_yoda.allDayBuilder = { eventList ->
LinearLayout(context).apply {
eventList.forEach { event ->
addView(
EventCardView(context).apply {
setBackgroundColor(Color.parseColor(randomColor()))
setEvent(event as Event)
layoutParams = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT
)
}
)
}
orientation = LinearLayout.VERTICAL
layoutParams = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT
)
}
}
// Simply display a message to say
// that the day is empty.
day_yoda.emptyDayBuilder = {
TextView(context).apply {
gravity = Gravity.CENTER
text = "Nothing to show today !"
}
}
You can now use the setEvents
function just like this :
lifecycleScope.launchWhenResumed {
day_yoda.setEvents(myEventList, container_view.height)
}
The Yoda library will now display the events into the Day layout in a background thread which will stop when your application is paused.
The viewLifecycleOwner.lifecycleScope is the lifecycleScope of you fragment view.