Commit 103984c5 authored by Filip Wiesner's avatar Filip Wiesner

Expandable News card (WIP)

parent 829f1079
package com.cvut.blackbird.flows.tasks
import android.annotation.TargetApi
import android.animation.LayoutTransition
import android.content.Context
import android.content.res.ColorStateList
import android.graphics.Color
import android.os.Build
import android.text.Html
import android.util.TypedValue
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams.*
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.StaggeredGridLayoutManager
import com.cvut.blackbird.R
import com.cvut.blackbird.extensions.courseAbbr
import com.cvut.blackbird.extensions.lastIndexOfNumber
import com.cvut.blackbird.extensions.setVisible
import com.cvut.blackbird.model.entities.Event
import com.cvut.blackbird.model.entities.EventType
import com.cvut.blackbird.model.entities.News
import com.cvut.blackbird.support.kolor.Kolor
import kotlinx.android.synthetic.main.exam_list_row.view.*
import kotlinx.android.synthetic.main.tasks_news.view.*
import kotlinx.android.synthetic.main.tasks_pinned.view.*
import org.joda.time.DateTime
import org.joda.time.Days
import org.joda.time.Minutes
import android.view.animation.AnimationUtils
import android.widget.LinearLayout
import android.widget.TextView
import androidx.cardview.widget.CardView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.isGone
import androidx.core.view.marginTop
import com.cvut.blackbird.extensions.*
import kotlinx.android.synthetic.main.tasks_news_layout.view.*
sealed class Task(val id: Int)
data class ExamTask(val event: Event): Task(event.id)
data class PinnedTask(val event: Event): Task(event.id)
data class NewsTask(val news: News): Task(news.title.hashCode())
data class NewsTask(val news: List<News>): Task(news.hashCode()) {
public var lastClickedStory: News? = null
}
class TasksListAdapter(private val clickListener: (Task) -> Unit): ListAdapter<Task, TaskViewHolder>(
object : DiffUtil.ItemCallback<Task>() {
......@@ -61,7 +70,7 @@ class TasksListAdapter(private val clickListener: (Task) -> Unit): ListAdapter<T
PINNED -> PinnedViewHolder(LayoutInflater.from(parent.context)
.inflate(R.layout.tasks_pinned, parent, false), parent.context)
NEWS -> NewsViewHolder(LayoutInflater.from(parent.context)
.inflate(R.layout.tasks_news, parent, false), parent.context)
.inflate(R.layout.tasks_news_layout, parent, false), parent.context)
else -> throw Exception("This view type is not implemented")
}
}
......@@ -128,10 +137,13 @@ class PinnedViewHolder(view: View, context: Context) : TaskViewHolder(view, cont
override fun bind(task: Task, clickListener: (Task) -> Unit) {
val pinnedEvent = (task as? PinnedTask)?.event ?: throw TypeCastException("You have to pass pinnedTask to PinnedViewHolder dumbass")
view.pin_eventAbbr.background = when {
pinnedEvent.eventType == EventType.LECTURE -> context.resources.getDrawable(R.drawable.ic_timetable_lecture, context.theme)
pinnedEvent.eventType == EventType.TUTORIAL -> context.resources.getDrawable(R.drawable.ic_timetable_tutorial, context.theme)
else -> context.resources.getDrawable(R.drawable.ic_timetable_info, context.theme)
view.pin_eventAbbr.background = when(pinnedEvent.eventType) {
EventType.LECTURE ->
context.resources.getDrawable(R.drawable.ic_timetable_lecture, context.theme)
EventType.TUTORIAL ->
context.resources.getDrawable(R.drawable.ic_timetable_tutorial, context.theme)
else ->
context.resources.getDrawable(R.drawable.ic_timetable_info, context.theme)
}
view.pin_eventAbbr.text = pinnedEvent.linked?.course?.courseAbbr ?: "-"
......@@ -150,16 +162,50 @@ class PinnedViewHolder(view: View, context: Context) : TaskViewHolder(view, cont
class NewsViewHolder(view: View, context: Context) : TaskViewHolder(view, context) {
override fun bind(task: Task, clickListener: (Task) -> Unit) {
val news = (task as? NewsTask)?.news ?: throw TypeCastException("You have to pass NewsTask to NewsViewHolder dumbass")
val newsTask = (task as? NewsTask) ?: throw TypeCastException("You have to pass NewsTask to NewsViewHolder dumbass")
val news = newsTask.news.asReversed()
// (view as CardView).layoutTransition.enableTransitionType(LayoutTransition.CHANGING)
// view.news_storiesLayout.layoutTransition.enableTransitionType(LayoutTransition.CHANGING)
fun onStoryClicked(news: News) {
newsTask.lastClickedStory = news
clickListener(task)
}
view.news_title.text = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Html.fromHtml(news.title, Html.FROM_HTML_MODE_COMPACT)
} else Html.fromHtml(news.title)
view.news_header.setHtmlText(news.first().title)
view.news_header.setOnClickListener { onStoryClicked(news.first()) }
val storyLayout = view.news_storiesLayout
for (story in news.takeLast(news.size - 1)) {
storyLayout.addView(TextView(context).apply {
layoutParams = LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT).apply {
setMargins(0,8.dpToPx, 0,0) }
setHtmlText(story.title)
setTextSize(TypedValue.COMPLEX_UNIT_SP, 16f)
setTextColor(Color.WHITE)
// (itemView.layoutParams as StaggeredGridLayoutManager.LayoutParams)
// .isFullSpan = true
setOnClickListener { onStoryClicked(story) }
})
}
view.news_expandBtn.setOnClickListener {
if (storyLayout.isGone) {
storyLayout.setVisible()
} else {
storyLayout.setGone()
}
}
(itemView.layoutParams as StaggeredGridLayoutManager.LayoutParams)
.isFullSpan = true
view.setOnClickListener { clickListener(task) }
}
fun TextView.setHtmlText(text: String) = setText(
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Html.fromHtml(text, Html.FROM_HTML_MODE_COMPACT)
} else Html.fromHtml(text)
)
}
......@@ -52,20 +52,13 @@ class TasksFragment : Fragment() {
when (it) {
is PinnedTask -> goToEventDetail(it.event)
is ExamTask -> goToEventDetail(it.event)
is NewsTask -> goToNews(it.news)
is NewsTask -> goToNews(it.lastClickedStory)
}
}
examsRecyclerView.adapter = taskAdapter
examsRecyclerView.layoutManager = StaggeredGridLayoutManager(2, RecyclerView.VERTICAL)
}
private fun goToNews(news: News) {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(news.link))
if (activity != null && intent.resolveActivity(activity!!.packageManager) != null) {
startActivity(intent)
}
}
private fun setupBinding() {
bind(viewModel.tasks) toPassValueTo taskAdapter::submitList
......@@ -78,4 +71,12 @@ class TasksFragment : Fragment() {
eventViewModel.eventDetail.postValue(event)
findMainNav()?.navigate(R.id.toEventDetail)
}
private fun goToNews(news: News?) {
if (news == null) return
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(news.link))
if (activity != null && intent.resolveActivity(activity!!.packageManager) != null) {
startActivity(intent)
}
}
}
......@@ -54,7 +54,7 @@ class TasksViewModel : ViewModel() {
val resultTasks = ArrayList<Task>()
if (pinned != null) for (item in pinned) resultTasks.add(PinnedTask(item))
if (exams != null) for (item in exams) resultTasks.add(ExamTask(item))
if (news != null) for (item in news) resultTasks.add(NewsTask(item))
if (news != null && news.isNotEmpty()) resultTasks.add(NewsTask(news))
resultTasks as List<Task>
}
......
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView 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="wrap_content"
android:layout_margin="3dp"
android:elevation="4dp"
app:cardCornerRadius="18dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/news_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/newsIc"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginStart="8dp"
android:layout_marginTop="12dp"
android:tint="@android:color/white"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_newspaper" />
<TextView
android:id="@+id/news_header"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:textColor="@android:color/white"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/newsIc"
app:layout_constraintTop_toTopOf="parent"
tools:text="A header article that will be at the top, attracting user attention" />
<LinearLayout
android:id="@+id/news_storiesLayout"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:orientation="vertical"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/news_header">
</LinearLayout>
<Button
android:id="@+id/news_expandBtn"
style="@style/Widget.MaterialComponents.Button.TextButton.Dialog"
android:layout_width="wrap_content"
android:layout_height="35dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:text="MORE NEWS"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/news_storiesLayout"
app:layout_constraintVertical_bias="1.0" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment