forked from recloudstream/cloudstream
UI
This commit is contained in:
parent
0fa16e3bbc
commit
719b60db26
18 changed files with 530 additions and 21 deletions
|
@ -26,5 +26,10 @@
|
|||
<option name="name" value="maven" />
|
||||
<option name="url" value="https://jitpack.io" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="maven" />
|
||||
<option name="name" value="maven" />
|
||||
<option name="url" value="https://github.com/psiegman/mvn-repo/raw/master/releases" />
|
||||
</remote-repository>
|
||||
</component>
|
||||
</project>
|
|
@ -34,6 +34,9 @@ android {
|
|||
}
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
url 'https://github.com/psiegman/mvn-repo/raw/master/releases'
|
||||
}
|
||||
maven { url 'https://jitpack.io' }
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,14 @@ object APIHolder {
|
|||
ShiroProvider()
|
||||
)
|
||||
|
||||
fun getApiFromName(apiName: String): MainAPI {
|
||||
for (api in apis) {
|
||||
if (apiName == api.name)
|
||||
return api
|
||||
}
|
||||
return apis[defProvider]
|
||||
}
|
||||
|
||||
fun Activity.getApiSettings(): HashSet<String> {
|
||||
val settingsManager = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
|
||||
|
@ -39,11 +47,11 @@ abstract class MainAPI {
|
|||
return null
|
||||
}
|
||||
|
||||
open fun load(url: String): Any? { //LoadResponse
|
||||
open fun load(slug: String): Any? { //LoadResponse
|
||||
return null
|
||||
}
|
||||
|
||||
open fun loadLinks(url: String, id: Int): Boolean {
|
||||
open fun loadLinks(data: Any, id: Int): Boolean {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
@ -51,8 +59,7 @@ abstract class MainAPI {
|
|||
fun MainAPI.fixUrl(url: String): String {
|
||||
if (url.startsWith('/')) {
|
||||
return mainUrl + url
|
||||
}
|
||||
else if(!url.startsWith("http") && !url.startsWith("//")) {
|
||||
} else if (!url.startsWith("http") && !url.startsWith("//")) {
|
||||
return "$mainUrl/$url"
|
||||
}
|
||||
return url
|
||||
|
@ -90,7 +97,8 @@ enum class TvType {
|
|||
|
||||
interface SearchResponse {
|
||||
val name: String
|
||||
val url: String
|
||||
val url: String // PUBLIC URL FOR OPEN IN APP
|
||||
val slug: String // USED FOR INTERNAL DATA
|
||||
val apiName: String
|
||||
val type: TvType
|
||||
val posterUrl: String?
|
||||
|
@ -100,6 +108,7 @@ interface SearchResponse {
|
|||
data class AnimeSearchResponse(
|
||||
override val name: String,
|
||||
override val url: String,
|
||||
override val slug: String,
|
||||
override val apiName: String,
|
||||
override val type: TvType,
|
||||
|
||||
|
@ -115,6 +124,7 @@ data class AnimeSearchResponse(
|
|||
data class MovieSearchResponse(
|
||||
override val name: String,
|
||||
override val url: String,
|
||||
override val slug: String,
|
||||
override val apiName: String,
|
||||
override val type: TvType,
|
||||
|
||||
|
@ -125,6 +135,7 @@ data class MovieSearchResponse(
|
|||
data class TvSeriesSearchResponse(
|
||||
override val name: String,
|
||||
override val url: String,
|
||||
override val slug: String,
|
||||
override val apiName: String,
|
||||
override val type: TvType,
|
||||
|
||||
|
|
|
@ -8,6 +8,26 @@ import androidx.navigation.ui.AppBarConfiguration
|
|||
import androidx.navigation.ui.setupWithNavController
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
private fun AppCompatActivity.backPressed(): Boolean {
|
||||
val currentFragment = supportFragmentManager.fragments.last {
|
||||
it.isVisible
|
||||
}
|
||||
|
||||
if (currentFragment != null && supportFragmentManager.fragments.size > 2) {
|
||||
//MainActivity.showNavbar()
|
||||
supportFragmentManager.beginTransaction()
|
||||
.setCustomAnimations(R.anim.enter_anim, R.anim.exit_anim, R.anim.pop_enter, R.anim.pop_exit)
|
||||
.remove(currentFragment)
|
||||
.commitAllowingStateLoss()
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
if (backPressed()) return
|
||||
super.onBackPressed()
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
|
|
@ -3,7 +3,9 @@ package com.lagradost.cloudstream3
|
|||
import android.app.Activity
|
||||
import android.content.res.Resources
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.lagradost.cloudstream3.ui.result.ResultFragment
|
||||
|
||||
object UIHelper {
|
||||
val Int.toPx: Int get() = (this * Resources.getSystem().displayMetrics.density).toInt()
|
||||
|
@ -11,16 +13,16 @@ object UIHelper {
|
|||
val Int.toDp: Int get() = (this / Resources.getSystem().displayMetrics.density).toInt()
|
||||
val Float.toDp: Float get() = (this / Resources.getSystem().displayMetrics.density)
|
||||
|
||||
fun Activity.loadResult(url: String, apiName: String) {
|
||||
/*this.runOnUiThread {
|
||||
fun AppCompatActivity.loadResult(url: String, slug: String, apiName: String) {
|
||||
this.runOnUiThread {
|
||||
this.supportFragmentManager.beginTransaction()
|
||||
.setCustomAnimations(R.anim.enter_anim, R.anim.exit_anim, R.anim.pop_enter, R.anim.pop_exit)
|
||||
.add(R.id.homeRoot, ResultFragment().newInstance(url, apiName))
|
||||
.add(R.id.homeRoot, ResultFragment().newInstance(url, slug, apiName))
|
||||
.commit()
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
private fun Activity.getStatusBarHeight(): Int {
|
||||
fun Activity.getStatusBarHeight(): Int {
|
||||
var result = 0
|
||||
val resourceId = resources.getIdentifier("status_bar_height", "dimen", "android")
|
||||
if (resourceId > 0) {
|
||||
|
|
|
@ -152,6 +152,7 @@ class ShiroProvider : MainAPI() {
|
|||
returnValue.add(AnimeSearchResponse(
|
||||
i.english ?: i.canonicalTitle,
|
||||
"$mainUrl/${i.slug}",
|
||||
i.slug,
|
||||
this.name,
|
||||
type,
|
||||
"https://cdn.shiro.is/${i.image}",
|
||||
|
@ -165,9 +166,9 @@ class ShiroProvider : MainAPI() {
|
|||
return returnValue
|
||||
}
|
||||
|
||||
override fun load(url: String): Any? {
|
||||
override fun load(slug: String): Any? {
|
||||
if (!autoLoadToken()) return null
|
||||
val rurl = "https://tapi.shiro.is/anime/slug/${url}?token=${token}"
|
||||
val rurl = "https://tapi.shiro.is/anime/slug/${slug}?token=${token}"
|
||||
val response = khttp.get(rurl, timeout = 120.0)
|
||||
val mapped = response.let { mapper.readValue<AnimePage>(it.text) }
|
||||
val data = mapped.data
|
||||
|
@ -183,7 +184,7 @@ class ShiroProvider : MainAPI() {
|
|||
data.english,
|
||||
data.japanese,
|
||||
data.canonicalTitle ?: data.name.replace("Dubbed", ""),
|
||||
url,
|
||||
"$mainUrl/${slug}",
|
||||
this.name,
|
||||
getType(data.type ?: ""),
|
||||
"https://cdn.shiro.is/${data.image}",
|
||||
|
@ -197,6 +198,5 @@ class ShiroProvider : MainAPI() {
|
|||
null,
|
||||
null,
|
||||
)
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
package com.lagradost.cloudstream3.ui.result
|
||||
|
||||
import android.app.Activity
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.APIHolder.getApiFromName
|
||||
import kotlinx.android.synthetic.main.result_episode.view.*
|
||||
|
||||
|
||||
class EpisodeAdapter(
|
||||
activity: Activity,
|
||||
animeList: ArrayList<ResultEpisode>,
|
||||
resView: RecyclerView,
|
||||
) :
|
||||
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
var cardList = animeList
|
||||
private var activity: Activity = activity
|
||||
var resView: RecyclerView? = resView
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return CardViewHolder(
|
||||
LayoutInflater.from(parent.context).inflate(R.layout.result_episode, parent, false),
|
||||
activity,
|
||||
resView!!
|
||||
)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
when (holder) {
|
||||
is CardViewHolder -> {
|
||||
holder.bind(cardList[position])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return cardList.size
|
||||
}
|
||||
|
||||
class CardViewHolder
|
||||
constructor(itemView: View, _activity: Activity, resView: RecyclerView) : RecyclerView.ViewHolder(itemView) {
|
||||
val activity = _activity
|
||||
val episode_view_procentage: View = itemView.episode_view_procentage
|
||||
val episode_view_procentage_off: View = itemView.episode_view_procentage_off
|
||||
val episode_text: TextView = itemView.episode_text
|
||||
val episode_extra: ImageView = itemView.episode_extra
|
||||
val episode_play: ImageView = itemView.episode_play
|
||||
|
||||
fun bind(card: ResultEpisode) {
|
||||
episode_text.text = card.name ?: "Episode ${card.episode}"
|
||||
|
||||
fun setWidth(v: View, procentage: Float) {
|
||||
val param = LinearLayout.LayoutParams(
|
||||
v.layoutParams.width,
|
||||
v.layoutParams.height,
|
||||
procentage
|
||||
)
|
||||
v.layoutParams = param
|
||||
}
|
||||
setWidth(episode_view_procentage, card.watchProgress)
|
||||
setWidth(episode_view_procentage_off, 1 - card.watchProgress)
|
||||
|
||||
episode_play.setOnClickListener {
|
||||
getApiFromName(card.apiName).loadLinks(card.data, card.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,21 +1,63 @@
|
|||
package com.lagradost.cloudstream3.ui.result
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.view.marginBottom
|
||||
import androidx.core.view.marginLeft
|
||||
import androidx.core.view.marginRight
|
||||
import androidx.core.view.marginTop
|
||||
import androidx.core.widget.NestedScrollView
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.model.GlideUrl
|
||||
import com.bumptech.glide.request.RequestOptions.bitmapTransform
|
||||
import com.lagradost.cloudstream3.AnimeLoadResponse
|
||||
import com.lagradost.cloudstream3.LoadResponse
|
||||
import com.lagradost.cloudstream3.R
|
||||
import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar
|
||||
import com.lagradost.cloudstream3.UIHelper.getStatusBarHeight
|
||||
import com.lagradost.cloudstream3.mvvm.Resource
|
||||
import com.lagradost.cloudstream3.mvvm.observe
|
||||
import jp.wasabeef.glide.transformations.BlurTransformation
|
||||
import kotlinx.android.synthetic.main.fragment_result.*
|
||||
import kotlinx.android.synthetic.main.fragment_search.*
|
||||
|
||||
|
||||
const val MAX_SYNO_LENGH = 600
|
||||
|
||||
data class ResultEpisode(
|
||||
val name: String?,
|
||||
val episode: Int,
|
||||
val data: Any,
|
||||
val apiName: String,
|
||||
val id: Int,
|
||||
val watchProgress: Float, // 0-1
|
||||
)
|
||||
|
||||
class ResultFragment : Fragment() {
|
||||
fun newInstance(url: String, slug: String, apiName: String) =
|
||||
ResultFragment().apply {
|
||||
arguments = Bundle().apply {
|
||||
putString("url", url)
|
||||
putString("slug", slug)
|
||||
putString("apiName", apiName)
|
||||
}
|
||||
}
|
||||
|
||||
private lateinit var viewModel: ResultViewModel
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
savedInstanceState: Bundle?,
|
||||
): View? {
|
||||
viewModel =
|
||||
ViewModelProvider(this).get(ResultViewModel::class.java)
|
||||
|
@ -23,7 +65,121 @@ class ResultFragment : Fragment() {
|
|||
return inflater.inflate(R.layout.fragment_result, container, false)
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
activity?.fixPaddingStatusbar(result_scroll)
|
||||
activity?.fixPaddingStatusbar(result_barstatus)
|
||||
// activity?.fixPaddingStatusbar(result_toolbar)
|
||||
|
||||
val url = arguments?.getString("url")
|
||||
val slug = arguments?.getString("slug")
|
||||
val apiName = arguments?.getString("apiName")
|
||||
|
||||
result_scroll.setOnScrollChangeListener(NestedScrollView.OnScrollChangeListener { _, _, scrollY, _, oldScrollY ->
|
||||
if(result_poster_blur == null) return@OnScrollChangeListener
|
||||
result_poster_blur.alpha = maxOf(0f, (0.3f - scrollY / 1000f))
|
||||
result_barstatus.alpha = scrollY / 200f
|
||||
result_barstatus.visibility = if(scrollY > 0) View.VISIBLE else View.GONE
|
||||
})
|
||||
|
||||
result_toolbar.setNavigationIcon(R.drawable.ic_baseline_arrow_back_24)
|
||||
result_toolbar.setNavigationOnClickListener {
|
||||
activity?.onBackPressed()
|
||||
}
|
||||
|
||||
observe(viewModel.resultResponse) { data ->
|
||||
when (data) {
|
||||
is Resource.Success -> {
|
||||
val d = data.value
|
||||
if (d is LoadResponse) {
|
||||
result_bookmark_button.text = "Watching"
|
||||
|
||||
if (d.year != null) {
|
||||
result_year.visibility = View.VISIBLE
|
||||
result_year.text = d.year.toString()
|
||||
} else {
|
||||
result_year.visibility = View.GONE
|
||||
}
|
||||
|
||||
if (d.posterUrl != null) {
|
||||
val glideUrl =
|
||||
GlideUrl(d.posterUrl)
|
||||
context!!.let {
|
||||
/*
|
||||
Glide.with(it)
|
||||
.load(glideUrl)
|
||||
.into(result_poster)*/
|
||||
|
||||
Glide.with(it)
|
||||
.load(glideUrl)
|
||||
.apply(bitmapTransform(BlurTransformation(10, 3)))
|
||||
.into(result_poster_blur)
|
||||
}
|
||||
}
|
||||
|
||||
val adapter: RecyclerView.Adapter<RecyclerView.ViewHolder>? = activity?.let {
|
||||
EpisodeAdapter(
|
||||
it,
|
||||
ArrayList(),
|
||||
result_episodes,
|
||||
)
|
||||
}
|
||||
|
||||
result_episodes.adapter = adapter
|
||||
result_episodes.layoutManager = GridLayoutManager(context, 1)
|
||||
|
||||
if (d is AnimeLoadResponse) {
|
||||
val preferEnglish = true
|
||||
val titleName = (if (preferEnglish) d.engName else d.japName) ?: d.name
|
||||
result_title.text = titleName
|
||||
result_toolbar.title = titleName
|
||||
|
||||
if (d.plot != null) {
|
||||
var syno = d.plot
|
||||
if (syno.length > MAX_SYNO_LENGH) {
|
||||
syno = syno.substring(0, MAX_SYNO_LENGH) + "..."
|
||||
}
|
||||
result_descript.setOnClickListener {
|
||||
val builder: AlertDialog.Builder = AlertDialog.Builder(requireContext())
|
||||
builder.setMessage(d.plot).setTitle("Synopsis")
|
||||
.show()
|
||||
}
|
||||
result_descript.text = syno
|
||||
} else {
|
||||
result_descript.text = "No Plot found"
|
||||
}
|
||||
|
||||
result_tags.text = (d.tags ?: ArrayList()).joinToString(separator = " | ")
|
||||
val isDub = d.dubEpisodes != null && d.dubEpisodes.size > 0
|
||||
val dataList = (if (isDub) d.dubEpisodes else d.subEpisodes)
|
||||
if (dataList != null && apiName != null) {
|
||||
val episodes = ArrayList<ResultEpisode>()
|
||||
for ((index, i) in dataList.withIndex()) {
|
||||
episodes.add(ResultEpisode(
|
||||
null, // TODO ADD NAMES
|
||||
index + 1, //TODO MAKE ABLE TO NOT HAVE SOME EPISODE
|
||||
i,
|
||||
apiName,
|
||||
(slug + index).hashCode(),
|
||||
(index * 0.1f),//TODO TEST; REMOVE
|
||||
))
|
||||
}
|
||||
(result_episodes.adapter as EpisodeAdapter).cardList = episodes
|
||||
(result_episodes.adapter as EpisodeAdapter).notifyDataSetChanged()
|
||||
}
|
||||
} else {
|
||||
result_title.text = d.name
|
||||
}
|
||||
}
|
||||
}
|
||||
is Resource.Failure -> {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (viewModel.resultResponse.value == null && apiName != null && slug != null)
|
||||
viewModel.load(slug, apiName)
|
||||
}
|
||||
}
|
|
@ -1,7 +1,25 @@
|
|||
package com.lagradost.cloudstream3.ui.result
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.lagradost.cloudstream3.APIHolder
|
||||
import com.lagradost.cloudstream3.APIHolder.getApiFromName
|
||||
import com.lagradost.cloudstream3.MainAPI
|
||||
import com.lagradost.cloudstream3.mvvm.Resource
|
||||
import com.lagradost.cloudstream3.mvvm.safeApiCall
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class ResultViewModel : ViewModel() {
|
||||
private val _resultResponse: MutableLiveData<Resource<Any?>> = MutableLiveData()
|
||||
val resultResponse: LiveData<Resource<Any?>> get() = _resultResponse
|
||||
|
||||
fun load(url: String, apiName:String) = viewModelScope.launch {
|
||||
val data = safeApiCall {
|
||||
getApiFromName(apiName).load(url)
|
||||
}
|
||||
|
||||
_resultResponse.postValue(data)
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ import android.view.ViewGroup
|
|||
import android.widget.FrameLayout
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.model.GlideUrl
|
||||
|
@ -105,7 +106,7 @@ class SearchAdapter(
|
|||
}
|
||||
|
||||
bg.setOnClickListener {
|
||||
activity.loadResult(card.url, card.apiName)
|
||||
(activity as AppCompatActivity).loadResult(card.url, card.slug, card.apiName)
|
||||
}
|
||||
|
||||
when (card) {
|
||||
|
|
7
app/src/main/res/drawable/background_shadow.xml
Normal file
7
app/src/main/res/drawable/background_shadow.xml
Normal file
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<gradient
|
||||
android:angle="-90"
|
||||
android:startColor="@color/transparent"
|
||||
android:endColor="@color/bitDarkerGrayBackground"/>
|
||||
</shape>
|
BIN
app/src/main/res/drawable/example_poster.jpg
Normal file
BIN
app/src/main/res/drawable/example_poster.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 61 KiB |
5
app/src/main/res/drawable/ic_baseline_arrow_back_24.xml
Normal file
5
app/src/main/res/drawable/ic_baseline_arrow_back_24.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<vector android:autoMirrored="true" android:height="24dp"
|
||||
android:tint="#FFFFFF" android:viewportHeight="24"
|
||||
android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/>
|
||||
</vector>
|
5
app/src/main/res/drawable/ic_baseline_more_vert_24.xml
Normal file
5
app/src/main/res/drawable/ic_baseline_more_vert_24.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M12,8c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2zM12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM12,16c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2z"/>
|
||||
</vector>
|
5
app/src/main/res/drawable/ic_baseline_play_arrow_24.xml
Normal file
5
app/src/main/res/drawable/ic_baseline_play_arrow_24.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M8,5v14l11,-7z"/>
|
||||
</vector>
|
|
@ -1,6 +1,138 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:id="@+id/result_root"
|
||||
android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:background="@color/bitDarkerGrayBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
>
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/result_barstatus"
|
||||
android:background="@color/grayBackground"
|
||||
android:layout_width="match_parent"
|
||||
android:alpha="0"
|
||||
tools:alpha="1"
|
||||
android:layout_height="wrap_content">
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/result_toolbar"
|
||||
android:paddingTop="@dimen/navbarHeight"
|
||||
app:title="Perfect Run"
|
||||
app:layout_scrollFlags="scroll|enterAlways"
|
||||
android:layout_width="match_parent" android:layout_height="wrap_content">
|
||||
</com.google.android.material.appbar.MaterialToolbar>
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
<FrameLayout android:layout_width="match_parent" android:layout_height="200dp">
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="centerCrop"
|
||||
android:alpha="0.3"
|
||||
tools:src="@drawable/example_poster"
|
||||
android:background="@color/darkBackground"
|
||||
android:id="@+id/result_poster_blur"
|
||||
android:contentDescription=""/>
|
||||
<ImageView android:src="@drawable/background_shadow" android:layout_gravity="bottom"
|
||||
android:layout_width="match_parent" android:layout_height="100dp">
|
||||
|
||||
</ImageView>
|
||||
</FrameLayout>
|
||||
<androidx.core.widget.NestedScrollView android:id="@+id/result_scroll" android:layout_width="match_parent" android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_marginTop="100dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<GridLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content">
|
||||
<LinearLayout android:gravity="center_vertical" android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="wrap_content">
|
||||
<TextView
|
||||
tools:text="The Perfect Run"
|
||||
android:id="@+id/result_title"
|
||||
android:textSize="15sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/textColor" android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
</TextView>
|
||||
<TextView
|
||||
android:id="@+id/result_year"
|
||||
tools:text="2021"
|
||||
android:textSize="15sp"
|
||||
android:textColor="@color/textColor" android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
</TextView>
|
||||
</LinearLayout>
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:layout_gravity="end"
|
||||
app:cornerRadius="1000dp"
|
||||
android:id="@+id/result_bookmark_button"
|
||||
tools:text="Bookmark"
|
||||
app:rippleColor="@color/colorPrimary"
|
||||
app:strokeColor="@color/colorPrimary"
|
||||
android:textColor="@color/textColor"
|
||||
android:textAllCaps="false"
|
||||
android:backgroundTint="@color/colorPrimary"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="45dp">
|
||||
</com.google.android.material.button.MaterialButton>
|
||||
</GridLayout>
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/result_tags"
|
||||
android:layout_marginTop="10dp"
|
||||
tools:text="Adventure | Fantasy World | Comedy | Ecchi | Action | Science Fiction | Fantasy"
|
||||
android:gravity="center"
|
||||
android:layout_width="match_parent" android:layout_height="wrap_content">
|
||||
</TextView>
|
||||
|
||||
<TextView
|
||||
android:layout_marginTop="10dp"
|
||||
android:id="@+id/result_descript"
|
||||
tools:text="Ryan Quicksave Romano is an eccentric adventurer with a strange power: he can create a save-point in time and redo his life whenever he dies. Arriving in New Rome, the glitzy capital of sin of a rebuilding Europe, he finds the city torn between mega-corporations, sponsored heroes, superpowered criminals, and true monsters. It's a time of chaos, where potions can grant the power to rule the world and dangers lurk everywhere. "
|
||||
android:layout_width="match_parent" android:layout_height="wrap_content">
|
||||
|
||||
</TextView>
|
||||
<TextView
|
||||
android:textColor="@color/textColor"
|
||||
android:layout_marginTop="10dp"
|
||||
android:id="@+id/result_episodes_text"
|
||||
tools:text="8 Episodes"
|
||||
android:gravity="start"
|
||||
android:layout_width="match_parent" android:layout_height="wrap_content">
|
||||
</TextView>
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
tools:listitem="@layout/result_episode"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/result_episodes"
|
||||
/>
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
<!--
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="150dp"
|
||||
app:cardCornerRadius="@dimen/roundedImageRadius"
|
||||
android:elevation="10dp"
|
||||
>
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="centerCrop"
|
||||
android:id="@+id/result_poster"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
tools:src="@drawable/example_poster"
|
||||
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/search_poster_descript"/>
|
||||
</androidx.cardview.widget.CardView>-->
|
||||
|
||||
</FrameLayout>
|
63
app/src/main/res/layout/result_episode.xml
Normal file
63
app/src/main/res/layout/result_episode.xml
Normal file
|
@ -0,0 +1,63 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.cardview.widget.CardView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
app:cardCornerRadius="@dimen/roundedImageRadius"
|
||||
app:cardBackgroundColor="@color/itemBackground"
|
||||
android:layout_marginBottom="2dp"
|
||||
>
|
||||
<!-- IDK BUT THIS DOES NOT SEAM LIKE A GOOD WAY OF DOING IT -->
|
||||
<LinearLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:orientation="horizontal">
|
||||
<View
|
||||
android:layout_weight="0.5"
|
||||
android:id="@+id/episode_view_procentage"
|
||||
android:alpha="0.2"
|
||||
android:background="@color/colorPrimary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent">
|
||||
</View>
|
||||
<View
|
||||
android:id="@+id/episode_view_procentage_off"
|
||||
android:layout_weight="0.10"
|
||||
android:alpha="0"
|
||||
android:background="@color/transparent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent">
|
||||
</View>
|
||||
</LinearLayout>
|
||||
|
||||
<GridLayout android:layout_width="match_parent" android:layout_height="match_parent">
|
||||
<ImageView
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:id="@+id/episode_play"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:src="@drawable/ic_baseline_play_arrow_24"
|
||||
android:contentDescription="@string/episode_play_descript"/>
|
||||
<TextView
|
||||
android:id="@+id/episode_text"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_gravity="center_vertical" android:gravity="center_vertical" tools:text="Episode 1"
|
||||
android:textColor="@color/textColor" android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent">
|
||||
</TextView>
|
||||
<ImageView
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:id="@+id/episode_extra"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:layout_gravity="center_vertical|end"
|
||||
android:src="@drawable/ic_baseline_more_vert_24"
|
||||
android:contentDescription="@string/episode_more_options_descript"/>
|
||||
</GridLayout>
|
||||
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
|
@ -10,4 +10,6 @@
|
|||
<string name="search_poster_descript">Poster</string>
|
||||
<string name="no_data">No Data</string>
|
||||
<string name="shadow_descript">Shadow</string>
|
||||
<string name="episode_more_options_descript">More Options</string>
|
||||
<string name="episode_play_descript">Play Episode</string>
|
||||
</resources>
|
Loading…
Reference in a new issue