mirror of
https://github.com/szkolny-eu/szkolny-android.git
synced 2024-11-24 19:04:38 -06:00
[Timetable] Add SwipeToRefresh. Select start&end hours based on lesson ranges.
This commit is contained in:
parent
a3e5f824c8
commit
37ea65e3fc
@ -169,7 +169,7 @@ dependencies {
|
|||||||
|
|
||||||
implementation 'com.github.kuba2k2:RecyclerTabLayout:700f980584'
|
implementation 'com.github.kuba2k2:RecyclerTabLayout:700f980584'
|
||||||
|
|
||||||
implementation 'com.github.kuba2k2:Tachyon:bbd421f994'
|
implementation 'com.github.kuba2k2:Tachyon:551943a6b5'
|
||||||
}
|
}
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
@ -4,7 +4,9 @@ import android.Manifest
|
|||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
|
import android.content.res.Resources
|
||||||
import android.graphics.Typeface
|
import android.graphics.Typeface
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.*
|
import android.text.*
|
||||||
@ -13,9 +15,10 @@ import android.text.style.StrikethroughSpan
|
|||||||
import android.text.style.StyleSpan
|
import android.text.style.StyleSpan
|
||||||
import android.util.LongSparseArray
|
import android.util.LongSparseArray
|
||||||
import android.util.SparseArray
|
import android.util.SparseArray
|
||||||
|
import android.util.TypedValue
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.*
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
import androidx.core.util.forEach
|
import androidx.core.util.forEach
|
||||||
import androidx.lifecycle.LifecycleOwner
|
import androidx.lifecycle.LifecycleOwner
|
||||||
@ -446,3 +449,49 @@ fun <T> LiveData<T>.observeOnce(lifecycleOwner: LifecycleOwner, observer: Observ
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a value in dp to pixels.
|
||||||
|
*/
|
||||||
|
val Int.dp: Int
|
||||||
|
get() = (this * Resources.getSystem().displayMetrics.density).toInt()
|
||||||
|
/**
|
||||||
|
* Convert a value in pixels to dp.
|
||||||
|
*/
|
||||||
|
val Int.px: Int
|
||||||
|
get() = (this / Resources.getSystem().displayMetrics.density).toInt()
|
||||||
|
|
||||||
|
@ColorInt
|
||||||
|
fun @receiver:AttrRes Int.resolveAttr(context: Context?): Int {
|
||||||
|
val typedValue = TypedValue()
|
||||||
|
context?.theme?.resolveAttribute(this, typedValue, true)
|
||||||
|
return typedValue.data
|
||||||
|
}
|
||||||
|
@ColorInt
|
||||||
|
fun @receiver:ColorRes Int.resolveColor(context: Context): Int {
|
||||||
|
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
context.resources.getColor(this, context.theme)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
context.resources.getColor(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fun @receiver:DrawableRes Int.resolveDrawable(context: Context): Drawable {
|
||||||
|
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
context.resources.getDrawable(this, context.theme)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
context.resources.getDrawable(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun View.findParentById(targetId: Int): View? {
|
||||||
|
if (id == targetId) {
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
val viewParent = this.parent ?: return null
|
||||||
|
if (viewParent is View) {
|
||||||
|
return viewParent.findParentById(targetId)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
@ -5,12 +5,14 @@ import android.content.Context
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.IntentFilter
|
import android.content.IntentFilter
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.viewpager.widget.ViewPager
|
import androidx.viewpager.widget.ViewPager
|
||||||
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
|
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
|
||||||
|
import kotlinx.coroutines.*
|
||||||
import pl.szczodrzynski.edziennik.App
|
import pl.szczodrzynski.edziennik.App
|
||||||
import pl.szczodrzynski.edziennik.MainActivity
|
import pl.szczodrzynski.edziennik.MainActivity
|
||||||
import pl.szczodrzynski.edziennik.R
|
import pl.szczodrzynski.edziennik.R
|
||||||
@ -18,16 +20,25 @@ import pl.szczodrzynski.edziennik.api.v2.LOGIN_TYPE_LIBRUS
|
|||||||
import pl.szczodrzynski.edziennik.databinding.FragmentTimetableV2Binding
|
import pl.szczodrzynski.edziennik.databinding.FragmentTimetableV2Binding
|
||||||
import pl.szczodrzynski.edziennik.utils.Themes
|
import pl.szczodrzynski.edziennik.utils.Themes
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
|
||||||
class TimetableFragment : Fragment() {
|
class TimetableFragment : Fragment(), CoroutineScope {
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "TimetableFragment"
|
private const val TAG = "TimetableFragment"
|
||||||
const val ACTION_SCROLL_TO_DATE = "pl.szczodrzynski.edziennik.timetable.SCROLL_TO_DATE"
|
const val ACTION_SCROLL_TO_DATE = "pl.szczodrzynski.edziennik.timetable.SCROLL_TO_DATE"
|
||||||
|
const val DEFAULT_START_HOUR = 6
|
||||||
|
const val DEFAULT_END_HOUR = 19
|
||||||
|
var pageSelection: Date? = null
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var app: App
|
private lateinit var app: App
|
||||||
private lateinit var activity: MainActivity
|
private lateinit var activity: MainActivity
|
||||||
private lateinit var b: FragmentTimetableV2Binding
|
private lateinit var b: FragmentTimetableV2Binding
|
||||||
|
|
||||||
|
private lateinit var job: Job
|
||||||
|
override val coroutineContext: CoroutineContext
|
||||||
|
get() = job + Dispatchers.Main
|
||||||
|
|
||||||
private var fabShown = false
|
private var fabShown = false
|
||||||
private val items = mutableListOf<Date>()
|
private val items = mutableListOf<Date>()
|
||||||
|
|
||||||
@ -36,11 +47,13 @@ class TimetableFragment : Fragment() {
|
|||||||
if (context == null)
|
if (context == null)
|
||||||
return null
|
return null
|
||||||
app = activity.application as App
|
app = activity.application as App
|
||||||
|
job = Job()
|
||||||
context!!.theme.applyStyle(Themes.appTheme, true)
|
context!!.theme.applyStyle(Themes.appTheme, true)
|
||||||
if (app.profile == null)
|
if (app.profile == null)
|
||||||
return inflater.inflate(R.layout.fragment_loading, container, false)
|
return inflater.inflate(R.layout.fragment_loading, container, false)
|
||||||
// activity, context and profile is valid
|
// activity, context and profile is valid
|
||||||
b = FragmentTimetableV2Binding.inflate(inflater)
|
b = FragmentTimetableV2Binding.inflate(inflater)
|
||||||
|
b.refreshLayout.setParent(activity.swipeRefreshLayout)
|
||||||
return b.root
|
return b.root
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,48 +75,65 @@ class TimetableFragment : Fragment() {
|
|||||||
activity.unregisterReceiver(broadcastReceiver)
|
activity.unregisterReceiver(broadcastReceiver)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { launch {
|
||||||
// TODO check if app, activity, b can be null
|
// TODO check if app, activity, b can be null
|
||||||
if (app.profile == null || !isAdded)
|
if (app.profile == null || !isAdded)
|
||||||
return
|
return@launch
|
||||||
|
|
||||||
if (app.profile.loginStoreType == LOGIN_TYPE_LIBRUS && app.profile.getLoginData("timetableNotPublic", false)) {
|
if (app.profile.loginStoreType == LOGIN_TYPE_LIBRUS && app.profile.getLoginData("timetableNotPublic", false)) {
|
||||||
b.timetableLayout.visibility = View.GONE
|
b.timetableLayout.visibility = View.GONE
|
||||||
b.timetableNotPublicLayout.visibility = View.VISIBLE
|
b.timetableNotPublicLayout.visibility = View.VISIBLE
|
||||||
return
|
return@launch
|
||||||
}
|
}
|
||||||
b.timetableLayout.visibility = View.VISIBLE
|
b.timetableLayout.visibility = View.VISIBLE
|
||||||
b.timetableNotPublicLayout.visibility = View.GONE
|
b.timetableNotPublicLayout.visibility = View.GONE
|
||||||
|
|
||||||
items.clear()
|
|
||||||
|
|
||||||
val monthDayCount = listOf(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
|
|
||||||
|
|
||||||
val today = Date.getToday().value
|
val today = Date.getToday().value
|
||||||
val yearStart = app.profile.dateSemester1Start?.clone() ?: return
|
var startHour = DEFAULT_START_HOUR
|
||||||
val yearEnd = app.profile.dateYearEnd ?: return
|
var endHour = DEFAULT_END_HOUR
|
||||||
while (yearStart.value <= yearEnd.value) {
|
val deferred = async(Dispatchers.Default) {
|
||||||
items += yearStart.clone()
|
items.clear()
|
||||||
var maxDays = monthDayCount[yearStart.month-1]
|
|
||||||
if (yearStart.month == 2 && yearStart.isLeap)
|
|
||||||
maxDays++
|
|
||||||
yearStart.day++
|
|
||||||
if (yearStart.day > maxDays) {
|
|
||||||
yearStart.day = 1
|
|
||||||
yearStart.month++
|
|
||||||
}
|
|
||||||
if (yearStart.month > 12) {
|
|
||||||
yearStart.month = 1
|
|
||||||
yearStart.year++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val pagerAdapter = TimetablePagerAdapter(fragmentManager ?: return, items)
|
val monthDayCount = listOf(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
|
||||||
|
|
||||||
|
val yearStart = app.profile.dateSemester1Start?.clone() ?: return@async
|
||||||
|
val yearEnd = app.profile.dateYearEnd ?: return@async
|
||||||
|
while (yearStart.value <= yearEnd.value) {
|
||||||
|
items += yearStart.clone()
|
||||||
|
var maxDays = monthDayCount[yearStart.month-1]
|
||||||
|
if (yearStart.month == 2 && yearStart.isLeap)
|
||||||
|
maxDays++
|
||||||
|
yearStart.day++
|
||||||
|
if (yearStart.day > maxDays) {
|
||||||
|
yearStart.day = 1
|
||||||
|
yearStart.month++
|
||||||
|
}
|
||||||
|
if (yearStart.month > 12) {
|
||||||
|
yearStart.month = 1
|
||||||
|
yearStart.year++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val lessonRanges = app.db.lessonRangeDao().getAllNow(App.profileId)
|
||||||
|
startHour = lessonRanges.map { it.startTime.hour }.min() ?: DEFAULT_START_HOUR
|
||||||
|
endHour = lessonRanges.map { it.endTime.hour }.max()?.plus(1) ?: DEFAULT_END_HOUR
|
||||||
|
}
|
||||||
|
deferred.await()
|
||||||
|
|
||||||
|
val pagerAdapter = TimetablePagerAdapter(
|
||||||
|
fragmentManager ?: return@launch,
|
||||||
|
items,
|
||||||
|
startHour,
|
||||||
|
endHour
|
||||||
|
)
|
||||||
b.viewPager.offscreenPageLimit = 2
|
b.viewPager.offscreenPageLimit = 2
|
||||||
b.viewPager.adapter = pagerAdapter
|
b.viewPager.adapter = pagerAdapter
|
||||||
b.viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
|
b.viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
|
||||||
override fun onPageScrollStateChanged(state: Int) {
|
override fun onPageScrollStateChanged(state: Int) {
|
||||||
|
if (b.refreshLayout != null) {
|
||||||
|
Log.d(TAG, "State $state")
|
||||||
|
b.refreshLayout.isEnabled = state == ViewPager.SCROLL_STATE_IDLE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
|
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
|
||||||
@ -111,6 +141,7 @@ class TimetableFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onPageSelected(position: Int) {
|
override fun onPageSelected(position: Int) {
|
||||||
|
pageSelection = items[position]
|
||||||
activity.navView.bottomBar.fabEnable = items[position].value != today
|
activity.navView.bottomBar.fabEnable = items[position].value != today
|
||||||
if (activity.navView.bottomBar.fabEnable && !fabShown) {
|
if (activity.navView.bottomBar.fabEnable && !fabShown) {
|
||||||
activity.gainAttentionFAB()
|
activity.gainAttentionFAB()
|
||||||
@ -123,10 +154,10 @@ class TimetableFragment : Fragment() {
|
|||||||
b.tabLayout.setCurrentItem(items.indexOfFirst { it.value == today }, false)
|
b.tabLayout.setCurrentItem(items.indexOfFirst { it.value == today }, false)
|
||||||
|
|
||||||
//activity.navView.bottomBar.fabEnable = true
|
//activity.navView.bottomBar.fabEnable = true
|
||||||
activity.navView.bottomBar.fabExtendedText = getString(pl.szczodrzynski.edziennik.R.string.timetable_today)
|
activity.navView.bottomBar.fabExtendedText = getString(R.string.timetable_today)
|
||||||
activity.navView.bottomBar.fabIcon = CommunityMaterial.Icon.cmd_calendar_today
|
activity.navView.bottomBar.fabIcon = CommunityMaterial.Icon.cmd_calendar_today
|
||||||
activity.navView.setFabOnClickListener(View.OnClickListener {
|
activity.navView.setFabOnClickListener(View.OnClickListener {
|
||||||
b.tabLayout.setCurrentItem(items.indexOfFirst { it.value == today }, true)
|
b.tabLayout.setCurrentItem(items.indexOfFirst { it.value == today }, true)
|
||||||
})
|
})
|
||||||
}
|
}}
|
||||||
}
|
}
|
@ -8,7 +8,12 @@ import pl.szczodrzynski.edziennik.ui.modules.timetable.v2.day.TimetableDayFragme
|
|||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Week
|
import pl.szczodrzynski.edziennik.utils.models.Week
|
||||||
|
|
||||||
class TimetablePagerAdapter(val fragmentManager: FragmentManager, val items: List<Date>) : FragmentStatePagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
|
class TimetablePagerAdapter(
|
||||||
|
fragmentManager: FragmentManager,
|
||||||
|
private val items: List<Date>,
|
||||||
|
private val startHour: Int,
|
||||||
|
private val endHour: Int
|
||||||
|
) : FragmentStatePagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "TimetablePagerAdapter"
|
private const val TAG = "TimetablePagerAdapter"
|
||||||
}
|
}
|
||||||
@ -21,6 +26,8 @@ class TimetablePagerAdapter(val fragmentManager: FragmentManager, val items: Lis
|
|||||||
return TimetableDayFragment().apply {
|
return TimetableDayFragment().apply {
|
||||||
arguments = Bundle().apply {
|
arguments = Bundle().apply {
|
||||||
putInt("date", items[position].value)
|
putInt("date", items[position].value)
|
||||||
|
putInt("startHour", startHour)
|
||||||
|
putInt("endHour", endHour)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*return TimetableDayFragment().apply {
|
/*return TimetableDayFragment().apply {
|
||||||
|
@ -7,42 +7,97 @@ import android.util.Log
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.widget.FrameLayout
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
import androidx.asynclayoutinflater.view.AsyncLayoutInflater
|
||||||
|
import androidx.core.view.setPadding
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
import com.linkedin.android.tachyon.DayView
|
import com.linkedin.android.tachyon.DayView
|
||||||
|
import com.linkedin.android.tachyon.DayViewConfig
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
import pl.szczodrzynski.edziennik.*
|
import pl.szczodrzynski.edziennik.*
|
||||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_TIMETABLE
|
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_TIMETABLE
|
||||||
import pl.szczodrzynski.edziennik.api.v2.LOGIN_TYPE_LIBRUS
|
import pl.szczodrzynski.edziennik.api.v2.LOGIN_TYPE_LIBRUS
|
||||||
import pl.szczodrzynski.edziennik.api.v2.events.task.EdziennikTask
|
import pl.szczodrzynski.edziennik.api.v2.events.task.EdziennikTask
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson
|
import pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.timetable.LessonFull
|
import pl.szczodrzynski.edziennik.data.db.modules.timetable.LessonFull
|
||||||
import pl.szczodrzynski.edziennik.databinding.FragmentTimetableV2DayBinding
|
|
||||||
import pl.szczodrzynski.edziennik.databinding.TimetableLessonBinding
|
import pl.szczodrzynski.edziennik.databinding.TimetableLessonBinding
|
||||||
|
import pl.szczodrzynski.edziennik.databinding.TimetableNoTimetableBinding
|
||||||
import pl.szczodrzynski.edziennik.ui.dialogs.timetable.LessonDetailsDialog
|
import pl.szczodrzynski.edziennik.ui.dialogs.timetable.LessonDetailsDialog
|
||||||
|
import pl.szczodrzynski.edziennik.ui.modules.timetable.v2.TimetableFragment.Companion.DEFAULT_END_HOUR
|
||||||
|
import pl.szczodrzynski.edziennik.ui.modules.timetable.v2.TimetableFragment.Companion.DEFAULT_START_HOUR
|
||||||
|
import pl.szczodrzynski.edziennik.utils.ListenerScrollView
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
import pl.szczodrzynski.navlib.getColorFromAttr
|
import pl.szczodrzynski.navlib.getColorFromAttr
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import kotlin.coroutines.CoroutineContext
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
class TimetableDayFragment() : Fragment() {
|
class TimetableDayFragment : Fragment(), CoroutineScope {
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "TimetableDayFragment"
|
private const val TAG = "TimetableDayFragment"
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var app: App
|
private lateinit var app: App
|
||||||
private lateinit var activity: MainActivity
|
private lateinit var activity: MainActivity
|
||||||
private lateinit var b: FragmentTimetableV2DayBinding
|
private lateinit var inflater: AsyncLayoutInflater
|
||||||
|
|
||||||
|
private lateinit var job: Job
|
||||||
|
override val coroutineContext: CoroutineContext
|
||||||
|
get() = job + Dispatchers.Main
|
||||||
|
|
||||||
private lateinit var date: Date
|
private lateinit var date: Date
|
||||||
|
private var startHour = DEFAULT_START_HOUR
|
||||||
|
private var endHour = DEFAULT_END_HOUR
|
||||||
|
private var firstEventMinute = 24*60
|
||||||
|
|
||||||
|
// find SwipeRefreshLayout in the hierarchy
|
||||||
|
private val refreshLayout by lazy { view?.findParentById(R.id.refreshLayout) }
|
||||||
|
// the day ScrollView
|
||||||
|
private val dayScrollDelegate = lazy {
|
||||||
|
val dayScroll = ListenerScrollView(context!!)
|
||||||
|
dayScroll.layoutParams = FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
|
||||||
|
dayScroll.setOnRefreshLayoutEnabledListener { enabled ->
|
||||||
|
refreshLayout?.isEnabled = enabled
|
||||||
|
}
|
||||||
|
dayScroll
|
||||||
|
}
|
||||||
|
private val dayScroll by dayScrollDelegate
|
||||||
|
// the lesson DayView
|
||||||
|
private val dayView by lazy {
|
||||||
|
val dayView = DayView(context!!, DayViewConfig(
|
||||||
|
startHour = startHour,
|
||||||
|
endHour = endHour,
|
||||||
|
dividerHeight = 1.dp,
|
||||||
|
halfHourHeight = 60.dp,
|
||||||
|
hourDividerColor = R.attr.hourDividerColor.resolveAttr(context),
|
||||||
|
halfHourDividerColor = R.attr.halfHourDividerColor.resolveAttr(context),
|
||||||
|
hourLabelWidth = 40.dp,
|
||||||
|
hourLabelMarginEnd = 10.dp,
|
||||||
|
eventMargin = 2.dp
|
||||||
|
), true)
|
||||||
|
dayView.setPadding(10.dp)
|
||||||
|
dayScroll.layoutParams = FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||||
|
dayScroll.addView(dayView)
|
||||||
|
dayView
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||||
activity = (getActivity() as MainActivity?) ?: return null
|
activity = (getActivity() as MainActivity?) ?: return null
|
||||||
if (context == null)
|
if (context == null)
|
||||||
return null
|
return null
|
||||||
app = activity.application as App
|
app = activity.application as App
|
||||||
b = FragmentTimetableV2DayBinding.inflate(inflater)
|
job = Job()
|
||||||
|
this.inflater = AsyncLayoutInflater(context!!)
|
||||||
date = arguments?.getInt("date")?.let { Date.fromValue(it) } ?: Date.getToday()
|
date = arguments?.getInt("date")?.let { Date.fromValue(it) } ?: Date.getToday()
|
||||||
return b.root
|
startHour = arguments?.getInt("startHour") ?: DEFAULT_START_HOUR
|
||||||
|
endHour = arguments?.getInt("endHour") ?: DEFAULT_END_HOUR
|
||||||
|
return FrameLayout(activity).apply {
|
||||||
|
layoutParams = FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
@ -52,45 +107,42 @@ class TimetableDayFragment() : Fragment() {
|
|||||||
|
|
||||||
Log.d(TAG, "onViewCreated, date=$date")
|
Log.d(TAG, "onViewCreated, date=$date")
|
||||||
|
|
||||||
// Inflate a label view for each hour the day view will display
|
// observe lesson database
|
||||||
val hourLabelViews = ArrayList<View>()
|
|
||||||
for (i in b.day.startHour..b.day.endHour) {
|
|
||||||
val hourLabelView = layoutInflater.inflate(R.layout.timetable_hour_label, b.day, false) as TextView
|
|
||||||
hourLabelView.text = "$i:00"
|
|
||||||
hourLabelViews.add(hourLabelView)
|
|
||||||
}
|
|
||||||
b.day.setHourLabelViews(hourLabelViews)
|
|
||||||
|
|
||||||
app.db.timetableDao().getForDate(App.profileId, date).observe(this, Observer<List<LessonFull>> { lessons ->
|
app.db.timetableDao().getForDate(App.profileId, date).observe(this, Observer<List<LessonFull>> { lessons ->
|
||||||
buildLessonViews(lessons)
|
processLessonList(lessons)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildLessonViews(lessons: List<LessonFull>) {
|
private fun processLessonList(lessons: List<LessonFull>) {
|
||||||
|
// no lessons - timetable not downloaded yet
|
||||||
if (lessons.isEmpty()) {
|
if (lessons.isEmpty()) {
|
||||||
b.dayScroll.visibility = View.GONE
|
inflater.inflate(R.layout.timetable_no_timetable, view as FrameLayout) { view, _, parent ->
|
||||||
b.noTimetableLayout.visibility = View.VISIBLE
|
parent?.removeAllViews()
|
||||||
b.noLessonsLayout.visibility = View.GONE
|
parent?.addView(view)
|
||||||
val weekStart = date.clone().stepForward(0, 0, -date.weekDay).stringY_m_d
|
val b = TimetableNoTimetableBinding.bind(view)
|
||||||
b.noTimetableSync.onClick {
|
val weekStart = date.clone().stepForward(0, 0, -date.weekDay).stringY_m_d
|
||||||
it.isEnabled = false
|
b.noTimetableSync.onClick {
|
||||||
EdziennikTask.syncProfile(
|
it.isEnabled = false
|
||||||
profileId = App.profileId,
|
EdziennikTask.syncProfile(
|
||||||
viewIds = listOf(
|
profileId = App.profileId,
|
||||||
DRAWER_ITEM_TIMETABLE to 0
|
viewIds = listOf(
|
||||||
),
|
DRAWER_ITEM_TIMETABLE to 0
|
||||||
arguments = JsonObject(
|
),
|
||||||
"weekStart" to weekStart
|
arguments = JsonObject(
|
||||||
)
|
"weekStart" to weekStart
|
||||||
).enqueue(activity)
|
)
|
||||||
|
).enqueue(activity)
|
||||||
|
}
|
||||||
|
b.noTimetableWeek.setText(R.string.timetable_no_timetable_week, weekStart)
|
||||||
}
|
}
|
||||||
b.noTimetableWeek.setText(R.string.timetable_no_timetable_week, weekStart)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// one lesson indicating a day without lessons
|
||||||
if (lessons.size == 1 && lessons[0].type == Lesson.TYPE_NO_LESSONS) {
|
if (lessons.size == 1 && lessons[0].type == Lesson.TYPE_NO_LESSONS) {
|
||||||
b.dayScroll.visibility = View.GONE
|
inflater.inflate(R.layout.timetable_no_lessons, view as FrameLayout) { view, _, parent ->
|
||||||
b.noTimetableLayout.visibility = View.GONE
|
parent?.removeAllViews()
|
||||||
b.noLessonsLayout.visibility = View.VISIBLE
|
parent?.addView(view)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,23 +153,37 @@ class TimetableDayFragment() : Fragment() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
b.dayScroll.visibility = View.VISIBLE
|
// clear the root view and add the ScrollView
|
||||||
b.noTimetableLayout.visibility = View.GONE
|
(view as FrameLayout).removeAllViews()
|
||||||
b.noLessonsLayout.visibility = View.GONE
|
(view as FrameLayout).addView(dayScroll)
|
||||||
|
|
||||||
var firstEventMinute = 24*60
|
// Inflate a label view for each hour the day view will display
|
||||||
|
val hourLabelViews = ArrayList<View>()
|
||||||
|
for (i in dayView.startHour..dayView.endHour) {
|
||||||
|
val hourLabelView = layoutInflater.inflate(R.layout.timetable_hour_label, dayView, false) as TextView
|
||||||
|
hourLabelView.text = "$i:00"
|
||||||
|
hourLabelViews.add(hourLabelView)
|
||||||
|
}
|
||||||
|
dayView.setHourLabelViews(hourLabelViews)
|
||||||
|
|
||||||
|
buildLessonViews(lessons)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildLessonViews(lessons: List<LessonFull>) {
|
||||||
|
if (!isAdded)
|
||||||
|
return
|
||||||
|
|
||||||
val eventViews = mutableListOf<View>()
|
val eventViews = mutableListOf<View>()
|
||||||
val eventTimeRanges = mutableListOf<DayView.EventTimeRange>()
|
val eventTimeRanges = mutableListOf<DayView.EventTimeRange>()
|
||||||
|
|
||||||
// Reclaim all of the existing event views so we can reuse them if needed, this process
|
// Reclaim all of the existing event views so we can reuse them if needed, this process
|
||||||
// can be useful if your day view is hosted in a recycler view for example
|
// can be useful if your day view is hosted in a recycler view for example
|
||||||
val recycled = b.day.removeEventViews()
|
val recycled = dayView.removeEventViews()
|
||||||
var remaining = recycled?.size ?: 0
|
var remaining = recycled?.size ?: 0
|
||||||
|
|
||||||
val arrowRight = " → "
|
val arrowRight = " → "
|
||||||
val bullet = " • "
|
val bullet = " • "
|
||||||
val colorSecondary = getColorFromAttr(activity, android.R.attr.textColorSecondary)
|
val colorSecondary = android.R.attr.textColorSecondary.resolveAttr(activity)
|
||||||
|
|
||||||
for (lesson in lessons) {
|
for (lesson in lessons) {
|
||||||
val startTime = lesson.displayStartTime ?: continue
|
val startTime = lesson.displayStartTime ?: continue
|
||||||
@ -127,7 +193,7 @@ class TimetableDayFragment() : Fragment() {
|
|||||||
|
|
||||||
// Try to recycle an existing event view if there are enough left, otherwise inflate
|
// Try to recycle an existing event view if there are enough left, otherwise inflate
|
||||||
// a new one
|
// a new one
|
||||||
val eventView = (if (remaining > 0) recycled?.get(--remaining) else layoutInflater.inflate(R.layout.timetable_lesson, b.day, false))
|
val eventView = (if (remaining > 0) recycled?.get(--remaining) else layoutInflater.inflate(R.layout.timetable_lesson, dayView, false))
|
||||||
?: continue
|
?: continue
|
||||||
val lb = TimetableLessonBinding.bind(eventView)
|
val lb = TimetableLessonBinding.bind(eventView)
|
||||||
eventViews += eventView
|
eventViews += eventView
|
||||||
@ -274,9 +340,16 @@ class TimetableDayFragment() : Fragment() {
|
|||||||
eventTimeRanges.add(DayView.EventTimeRange(startMinute, endMinute))
|
eventTimeRanges.add(DayView.EventTimeRange(startMinute, endMinute))
|
||||||
}
|
}
|
||||||
|
|
||||||
val minuteHeight = (b.day.getHourTop(1) - b.day.getHourTop(0)).toFloat() / 60f
|
dayView.setEventViews(eventViews, eventTimeRanges)
|
||||||
val firstEventTop = (firstEventMinute - b.day.startHour * 60) * minuteHeight
|
val firstEventTop = (firstEventMinute - dayView.startHour * 60) * dayView.minuteHeight
|
||||||
b.day.setEventViews(eventViews, eventTimeRanges)
|
dayScroll.scrollTo(0, firstEventTop.toInt())
|
||||||
b.dayScroll.scrollTo(0, firstEventTop.toInt())
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
if (dayScrollDelegate.isInitialized()) {
|
||||||
|
val firstEventTop = (firstEventMinute - dayView.startHour * 60) * dayView.minuteHeight
|
||||||
|
dayScroll.scrollTo(0, firstEventTop.toInt())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2019-11-16.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.utils
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.MotionEvent
|
||||||
|
import android.widget.ScrollView
|
||||||
|
|
||||||
|
class ListenerScrollView(
|
||||||
|
context: Context,
|
||||||
|
attrs: AttributeSet? = null
|
||||||
|
) : ScrollView(context, attrs) {
|
||||||
|
|
||||||
|
private var onScrollChangedListener: ((v: ListenerScrollView, scrollX: Int, scrollY: Int, oldScrollX: Int, oldScrollY: Int) -> Unit)? = null
|
||||||
|
private var onRefreshLayoutEnabledListener: ((enabled: Boolean) -> Unit)? = null
|
||||||
|
private var refreshLayoutEnabled = true
|
||||||
|
|
||||||
|
init {
|
||||||
|
setOnTouchListener { _, event ->
|
||||||
|
if (event.action == MotionEvent.ACTION_UP) {
|
||||||
|
refreshLayoutEnabled = scrollY < 10
|
||||||
|
onRefreshLayoutEnabledListener?.invoke(refreshLayoutEnabled)
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onScrollChanged(l: Int, t: Int, oldl: Int, oldt: Int) {
|
||||||
|
onScrollChangedListener?.invoke(this, l, t, oldl, oldt)
|
||||||
|
if (t > 10 && refreshLayoutEnabled) {
|
||||||
|
refreshLayoutEnabled = false
|
||||||
|
onRefreshLayoutEnabledListener?.invoke(refreshLayoutEnabled)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setOnScrollChangedListener(l: ((v: ListenerScrollView, scrollX: Int, scrollY: Int, oldScrollX: Int, oldScrollY: Int) -> Unit)?) {
|
||||||
|
onScrollChangedListener = l
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setOnRefreshLayoutEnabledListener(l: ((enabled: Boolean) -> Unit)?) {
|
||||||
|
onRefreshLayoutEnabledListener = l
|
||||||
|
}
|
||||||
|
}
|
@ -2,89 +2,96 @@
|
|||||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
<FrameLayout
|
|
||||||
|
<pl.szczodrzynski.edziennik.utils.SwipeRefreshLayoutNoIndicator
|
||||||
|
android:id="@+id/refreshLayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
<FrameLayout
|
||||||
android:id="@+id/timetableLayout"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent">
|
||||||
tools:visibility="gone">
|
|
||||||
|
|
||||||
<com.google.android.material.appbar.AppBarLayout
|
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
android:layout_width="match_parent"
|
android:id="@+id/timetableLayout"
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="?colorSurface"
|
|
||||||
style="@style/Widget.MaterialComponents.AppBarLayout.Surface">
|
|
||||||
|
|
||||||
<com.nshmura.recyclertablayout.RecyclerTabLayout
|
|
||||||
android:id="@+id/tabLayout"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="48dp"
|
|
||||||
android:background="@color/colorSurface_6dp"
|
|
||||||
app:rtl_tabTextAppearance="@style/rtl_RecyclerTabLayout.Tab"
|
|
||||||
app:rtl_tabIndicatorColor="?colorPrimary"
|
|
||||||
app:rtl_tabMinWidth="90dp"
|
|
||||||
app:rtl_tabMaxWidth="300dp"
|
|
||||||
app:rtl_tabSelectedTextColor="?colorPrimary"
|
|
||||||
app:rtl_tabPaddingStart="16dp"
|
|
||||||
app:rtl_tabPaddingEnd="16dp"
|
|
||||||
app:rtl_tabPaddingTop="12dp"
|
|
||||||
app:rtl_tabPaddingBottom="12dp"/>
|
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
|
||||||
|
|
||||||
<androidx.viewpager.widget.ViewPager
|
|
||||||
android:id="@+id/viewPager"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
|
tools:visibility="gone">
|
||||||
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
|
style="@style/Widget.MaterialComponents.AppBarLayout.Surface"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?colorSurface">
|
||||||
|
|
||||||
<LinearLayout
|
<com.nshmura.recyclertablayout.RecyclerTabLayout
|
||||||
android:id="@+id/timetableNotPublicLayout"
|
android:id="@+id/tabLayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="48dp"
|
||||||
android:orientation="vertical"
|
android:background="@color/colorSurface_6dp"
|
||||||
android:visibility="gone"
|
app:rtl_tabIndicatorColor="?colorPrimary"
|
||||||
android:gravity="center"
|
app:rtl_tabMaxWidth="300dp"
|
||||||
tools:visibility="visible">
|
app:rtl_tabMinWidth="90dp"
|
||||||
|
app:rtl_tabPaddingBottom="12dp"
|
||||||
|
app:rtl_tabPaddingEnd="16dp"
|
||||||
|
app:rtl_tabPaddingStart="16dp"
|
||||||
|
app:rtl_tabPaddingTop="12dp"
|
||||||
|
app:rtl_tabSelectedTextColor="?colorPrimary"
|
||||||
|
app:rtl_tabTextAppearance="@style/rtl_RecyclerTabLayout.Tab" />
|
||||||
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
<ImageView
|
<androidx.viewpager.widget.ViewPager
|
||||||
android:layout_width="wrap_content"
|
android:id="@+id/viewPager"
|
||||||
android:layout_height="wrap_content"
|
android:layout_width="match_parent"
|
||||||
app:srcCompat="@drawable/ic_no_timetable" />
|
android:layout_height="match_parent"
|
||||||
|
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
|
||||||
|
|
||||||
<TextView
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:fontFamily="sans-serif-light"
|
|
||||||
android:text="@string/timetable_not_public_title"
|
|
||||||
android:textSize="24sp" />
|
|
||||||
|
|
||||||
<TextView
|
<LinearLayout
|
||||||
android:layout_width="wrap_content"
|
android:id="@+id/timetableNotPublicLayout"
|
||||||
android:layout_height="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_height="match_parent"
|
||||||
android:layout_marginStart="32dp"
|
|
||||||
android:layout_marginEnd="32dp"
|
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:text="@string/timetable_not_public_text"
|
android:orientation="vertical"
|
||||||
android:textSize="16sp" />
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible">
|
||||||
|
|
||||||
<TextView
|
<ImageView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="16dp"
|
app:srcCompat="@drawable/ic_no_timetable" />
|
||||||
android:layout_marginStart="32dp"
|
|
||||||
android:layout_marginEnd="32dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="@string/timetable_not_public_hint"
|
|
||||||
android:textSize="14sp" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:fontFamily="sans-serif-light"
|
||||||
|
android:text="@string/timetable_not_public_title"
|
||||||
|
android:textSize="24sp" />
|
||||||
|
|
||||||
</FrameLayout>
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="32dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:layout_marginEnd="32dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="@string/timetable_not_public_text"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="32dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:layout_marginEnd="32dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="@string/timetable_not_public_hint"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
</pl.szczodrzynski.edziennik.utils.SwipeRefreshLayoutNoIndicator>
|
||||||
</layout>
|
</layout>
|
@ -28,126 +28,5 @@
|
|||||||
tools:visibility="gone"/>
|
tools:visibility="gone"/>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/noLessonsLayout"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:visibility="gone"
|
|
||||||
android:gravity="center"
|
|
||||||
tools:visibility="gone">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:srcCompat="@drawable/ic_timetable" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:fontFamily="sans-serif-light"
|
|
||||||
android:text="@string/timetable_no_lessons_title"
|
|
||||||
android:textSize="24sp" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/freeDayLayout"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:visibility="gone"
|
|
||||||
android:gravity="center"
|
|
||||||
tools:visibility="gone">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:srcCompat="@drawable/ic_sunbed" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:fontFamily="sans-serif-light"
|
|
||||||
android:text="@string/timetable_free_day_title"
|
|
||||||
android:textSize="24sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:text="@string/timetable_free_day_text"
|
|
||||||
android:textSize="14sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/freeDayText"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="32dp"
|
|
||||||
android:layout_marginEnd="32dp"
|
|
||||||
android:gravity="center"
|
|
||||||
tools:text="Dzień wolny dla szkoły z puli dyrektorskiej z okazji obchodów Światowego Dnia Wtorku w mieście Poznań i na przedmieśiach"
|
|
||||||
android:textSize="16sp" />
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/freeDayShowTimetable"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:text="@string/timetable_free_day_show" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/noTimetableLayout"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:visibility="gone"
|
|
||||||
android:gravity="center"
|
|
||||||
tools:visibility="visible">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:srcCompat="@drawable/ic_sync" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:fontFamily="sans-serif-light"
|
|
||||||
android:text="@string/timetable_no_timetable_title"
|
|
||||||
android:textSize="24sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:layout_marginStart="32dp"
|
|
||||||
android:layout_marginEnd="32dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="@string/timetable_no_timetable_text"
|
|
||||||
android:textSize="16sp" />
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/noTimetableSync"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:text="@string/timetable_no_timetable_sync" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/noTimetableWeek"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
tools:text="@string/timetable_no_timetable_week"
|
|
||||||
android:textSize="12sp"
|
|
||||||
android:textStyle="italic"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
</layout>
|
</layout>
|
47
app/src/main/res/layout/timetable_free_day.xml
Normal file
47
app/src/main/res/layout/timetable_free_day.xml
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (c) Kuba Szczodrzyński 2019-11-15.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/freeDayLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:drawableTop="@drawable/ic_sunbed"
|
||||||
|
android:drawablePadding="16dp"
|
||||||
|
android:fontFamily="sans-serif-light"
|
||||||
|
android:text="@string/timetable_free_day_title"
|
||||||
|
android:textSize="24sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:text="@string/timetable_free_day_text"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/freeDayText"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="32dp"
|
||||||
|
android:layout_marginEnd="32dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:textSize="16sp"
|
||||||
|
tools:text="Dzień wolny dla szkoły z puli dyrektorskiej z okazji obchodów Światowego Dnia Wtorku w mieście Poznań i na przedmieśiach" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/freeDayShowTimetable"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:text="@string/timetable_free_day_show" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
14
app/src/main/res/layout/timetable_no_lessons.xml
Normal file
14
app/src/main/res/layout/timetable_no_lessons.xml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (c) Kuba Szczodrzyński 2019-11-15.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:drawableTop="@drawable/ic_timetable"
|
||||||
|
android:drawablePadding="16dp"
|
||||||
|
android:fontFamily="sans-serif-light"
|
||||||
|
android:text="@string/timetable_no_lessons_title"
|
||||||
|
android:textSize="24sp" />
|
50
app/src/main/res/layout/timetable_no_timetable.xml
Normal file
50
app/src/main/res/layout/timetable_no_timetable.xml
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
~ Copyright (c) Kuba Szczodrzyński 2019-11-15.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/noTimetableLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:drawableTop="@drawable/ic_sync"
|
||||||
|
android:drawablePadding="16dp"
|
||||||
|
android:fontFamily="sans-serif-light"
|
||||||
|
android:text="@string/timetable_no_timetable_title"
|
||||||
|
android:textSize="24sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="32dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:layout_marginEnd="32dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="@string/timetable_no_timetable_text"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/noTimetableSync"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:text="@string/timetable_no_timetable_sync" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/noTimetableWeek"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:textStyle="italic"
|
||||||
|
tools:text="@string/timetable_no_timetable_week" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</layout>
|
@ -101,6 +101,8 @@
|
|||||||
<item name="timetable_lesson_change_color">#ffb300</item>
|
<item name="timetable_lesson_change_color">#ffb300</item>
|
||||||
<item name="timetable_lesson_shifted_source_color">#A1887F</item>
|
<item name="timetable_lesson_shifted_source_color">#A1887F</item>
|
||||||
<item name="timetable_lesson_shifted_target_color">#4caf50</item>
|
<item name="timetable_lesson_shifted_target_color">#4caf50</item>
|
||||||
|
<item name="hourDividerColor">#b0b0b0</item>
|
||||||
|
<item name="halfHourDividerColor">#e0e0e0</item>
|
||||||
</style>
|
</style>
|
||||||
<style name="AppTheme.Dark" parent="NavView.Dark">
|
<style name="AppTheme.Dark" parent="NavView.Dark">
|
||||||
<item name="colorPrimary">#64b5f6</item>
|
<item name="colorPrimary">#64b5f6</item>
|
||||||
@ -131,6 +133,8 @@
|
|||||||
<item name="timetable_lesson_change_color">#ffb300</item>
|
<item name="timetable_lesson_change_color">#ffb300</item>
|
||||||
<item name="timetable_lesson_shifted_source_color">#A1887F</item>
|
<item name="timetable_lesson_shifted_source_color">#A1887F</item>
|
||||||
<item name="timetable_lesson_shifted_target_color">#4caf50</item>
|
<item name="timetable_lesson_shifted_target_color">#4caf50</item>
|
||||||
|
<item name="hourDividerColor">#7fffffff</item>
|
||||||
|
<item name="halfHourDividerColor">#40ffffff</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user