add media fragment, add stream parsing
This commit is contained in:
parent
c473fce19a
commit
818981190d
|
@ -38,7 +38,8 @@ dependencies {
|
||||||
implementation 'androidx.core:core-ktx:1.3.2'
|
implementation 'androidx.core:core-ktx:1.3.2'
|
||||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||||
implementation 'com.google.android.material:material:1.2.1'
|
implementation 'com.google.android.material:material:1.2.1'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
|
implementation 'com.google.code.gson:gson:2.8.6'
|
||||||
|
implementation 'androidx.constraintlayout:constraintlayout:2.0.2'
|
||||||
implementation 'androidx.navigation:navigation-fragment:2.3.0'
|
implementation 'androidx.navigation:navigation-fragment:2.3.0'
|
||||||
implementation 'androidx.navigation:navigation-ui:2.3.0'
|
implementation 'androidx.navigation:navigation-ui:2.3.0'
|
||||||
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
|
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
|
||||||
|
@ -49,6 +50,7 @@ dependencies {
|
||||||
implementation 'com.github.bumptech.glide:glide:4.11.0'
|
implementation 'com.github.bumptech.glide:glide:4.11.0'
|
||||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||||
implementation 'androidx.recyclerview:recyclerview:1.1.0'
|
implementation 'androidx.recyclerview:recyclerview:1.1.0'
|
||||||
|
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
|
||||||
|
|
||||||
testImplementation 'junit:junit:4.12'
|
testImplementation 'junit:junit:4.12'
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="org.mosad.teapod">
|
package="org.mosad.teapod">
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
|
|
|
@ -1,35 +1,88 @@
|
||||||
package org.mosad.teapod
|
package org.mosad.teapod
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.view.MenuItem
|
||||||
import com.google.android.material.bottomnavigation.BottomNavigationView
|
import com.google.android.material.bottomnavigation.BottomNavigationView
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.navigation.findNavController
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.navigation.ui.AppBarConfiguration
|
import androidx.fragment.app.commit
|
||||||
import androidx.navigation.ui.setupActionBarWithNavController
|
import kotlinx.android.synthetic.main.activity_main.*
|
||||||
import androidx.navigation.ui.setupWithNavController
|
|
||||||
import kotlinx.coroutines.GlobalScope
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import org.mosad.teapod.parser.AoDParser
|
import org.mosad.teapod.parser.AoDParser
|
||||||
|
import org.mosad.teapod.ui.MediaFragment
|
||||||
|
import org.mosad.teapod.ui.account.AccountFragment
|
||||||
|
import org.mosad.teapod.ui.home.HomeFragment
|
||||||
|
import org.mosad.teapod.ui.library.LibraryFragment
|
||||||
|
import org.mosad.teapod.ui.search.SearchFragment
|
||||||
|
import org.mosad.teapod.util.GUIMedia
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemSelectedListener {
|
||||||
|
|
||||||
|
private var activeFragment: Fragment = HomeFragment() // the currently active fragment, home at the start
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_main)
|
setContentView(R.layout.activity_main)
|
||||||
val navView: BottomNavigationView = findViewById(R.id.nav_view)
|
val navView: BottomNavigationView = findViewById(R.id.nav_view)
|
||||||
|
navView.setOnNavigationItemSelectedListener(this)
|
||||||
val navController = findNavController(R.id.nav_host_fragment)
|
|
||||||
// Passing each menu ID as a set of Ids because each
|
|
||||||
// menu should be considered as top level destinations.
|
|
||||||
val appBarConfiguration = AppBarConfiguration(setOf(
|
|
||||||
R.id.navigation_home, R.id.navigation_library, R.id.navigation_search))
|
|
||||||
setupActionBarWithNavController(navController, appBarConfiguration)
|
|
||||||
navView.setupWithNavController(navController)
|
|
||||||
|
|
||||||
load()
|
load()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onBackPressed() {
|
||||||
|
if (supportFragmentManager.backStackEntryCount > 0) {
|
||||||
|
supportFragmentManager.popBackStack()
|
||||||
|
} else {
|
||||||
|
if (activeFragment !is HomeFragment) {
|
||||||
|
nav_view.selectedItemId = R.id.navigation_home
|
||||||
|
} else {
|
||||||
|
super.onBackPressed()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNavigationItemSelected(item: MenuItem): Boolean {
|
||||||
|
val ret = when (item.itemId) {
|
||||||
|
R.id.navigation_home -> {
|
||||||
|
activeFragment = HomeFragment()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
R.id.navigation_library -> {
|
||||||
|
activeFragment = LibraryFragment()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
R.id.navigation_search -> {
|
||||||
|
activeFragment = SearchFragment()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
R.id.navigation_account -> {
|
||||||
|
activeFragment = AccountFragment()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
|
||||||
|
supportFragmentManager.commit {
|
||||||
|
replace(R.id.nav_host_fragment, activeFragment)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
private fun load() {
|
private fun load() {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun showDetailFragment(media: GUIMedia) {
|
||||||
|
val streams = AoDParser().loadStreams(media.link) // load the streams for the selected media
|
||||||
|
|
||||||
|
val mediaFragment = MediaFragment(media, streams)
|
||||||
|
supportFragmentManager.commit {
|
||||||
|
add(R.id.nav_host_fragment, mediaFragment, "MediaFragment")
|
||||||
|
addToBackStack(null)
|
||||||
|
show(mediaFragment)
|
||||||
|
}
|
||||||
|
|
||||||
|
println("visible !!!: " + mediaFragment.isVisible)
|
||||||
|
println(supportFragmentManager.backStackEntryCount)
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
package org.mosad.teapod.parser
|
package org.mosad.teapod.parser
|
||||||
|
|
||||||
|
import com.google.gson.JsonParser
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import org.json.JSONObject
|
|
||||||
import org.jsoup.Connection
|
import org.jsoup.Connection
|
||||||
import org.jsoup.Jsoup
|
import org.jsoup.Jsoup
|
||||||
import org.mosad.teapod.util.GUIMedia
|
import org.mosad.teapod.util.GUIMedia
|
||||||
|
@ -15,8 +15,12 @@ class AoDParser {
|
||||||
private val login = ""
|
private val login = ""
|
||||||
private val pwd = ""
|
private val pwd = ""
|
||||||
|
|
||||||
private var sessionCookies = mutableMapOf<String, String>()
|
companion object {
|
||||||
private var loginSuccess = false
|
private var sessionCookies = mutableMapOf<String, String>()
|
||||||
|
private var loginSuccess = false
|
||||||
|
|
||||||
|
val mediaList = arrayListOf<GUIMedia>()
|
||||||
|
}
|
||||||
|
|
||||||
private fun login() = runBlocking {
|
private fun login() = runBlocking {
|
||||||
|
|
||||||
|
@ -63,14 +67,14 @@ class AoDParser {
|
||||||
if (sessionCookies.isEmpty()) login()
|
if (sessionCookies.isEmpty()) login()
|
||||||
|
|
||||||
withContext(Dispatchers.Default) {
|
withContext(Dispatchers.Default) {
|
||||||
val res = Jsoup.connect("$baseURL/animes")
|
val resAnimes = Jsoup.connect("$baseURL/animes")
|
||||||
.cookies(sessionCookies)
|
.cookies(sessionCookies)
|
||||||
.get()
|
.get()
|
||||||
|
|
||||||
//println(res)
|
//println(resAnimes)
|
||||||
|
|
||||||
val animes = arrayListOf<GUIMedia>()
|
mediaList.clear()
|
||||||
res.select("div.animebox").forEach {
|
resAnimes.select("div.animebox").forEach {
|
||||||
val media = GUIMedia(
|
val media = GUIMedia(
|
||||||
it.select("h3.animebox-title").text(),
|
it.select("h3.animebox-title").text(),
|
||||||
it.select("p.animebox-image").select("img").attr("src"),
|
it.select("p.animebox-image").select("img").attr("src"),
|
||||||
|
@ -78,25 +82,27 @@ class AoDParser {
|
||||||
it.select("p.animebox-link").select("a").attr("href")
|
it.select("p.animebox-link").select("a").attr("href")
|
||||||
)
|
)
|
||||||
|
|
||||||
animes.add(media)
|
mediaList.add(media)
|
||||||
}
|
}
|
||||||
|
|
||||||
println("got ${animes.size} anime")
|
println("got ${mediaList.size} anime")
|
||||||
|
|
||||||
return@withContext animes
|
return@withContext mediaList
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadDetails(mediaPath: String) = runBlocking {
|
/**
|
||||||
|
* load streams for the media path
|
||||||
|
*/
|
||||||
|
fun loadStreams(mediaPath: String): List<String> = runBlocking {
|
||||||
if (sessionCookies.isEmpty()) login()
|
if (sessionCookies.isEmpty()) login()
|
||||||
|
|
||||||
if (!loginSuccess) {
|
if (!loginSuccess) {
|
||||||
println("please log in")
|
println("please log in") // TODO
|
||||||
return@runBlocking
|
return@runBlocking listOf()
|
||||||
}
|
}
|
||||||
|
|
||||||
withContext(Dispatchers.Default) {
|
withContext(Dispatchers.Default) {
|
||||||
println(baseURL + mediaPath)
|
|
||||||
|
|
||||||
val res = Jsoup.connect(baseURL + mediaPath)
|
val res = Jsoup.connect(baseURL + mediaPath)
|
||||||
.cookies(sessionCookies)
|
.cookies(sessionCookies)
|
||||||
|
@ -105,19 +111,20 @@ class AoDParser {
|
||||||
//println(res)
|
//println(res)
|
||||||
|
|
||||||
val playlists = res.select("input.streamstarter_html5").eachAttr("data-playlist")
|
val playlists = res.select("input.streamstarter_html5").eachAttr("data-playlist")
|
||||||
println(playlists.first())
|
|
||||||
|
|
||||||
val csrfToken = res.select("meta[name=csrf-token]").attr("content")
|
val csrfToken = res.select("meta[name=csrf-token]").attr("content")
|
||||||
println("csrf token is: $csrfToken")
|
|
||||||
|
|
||||||
loadStreamInfo(playlists.first(), csrfToken)
|
//println("first entry: ${playlists.first()}")
|
||||||
|
//println("csrf token is: $csrfToken")
|
||||||
|
|
||||||
|
return@withContext loadStreamInfo(playlists.first(), csrfToken)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadStreamInfo(playlistPath: String, csrfToken: String) = runBlocking {
|
/**
|
||||||
|
* load the playlist path and parse it, read the stream info from json
|
||||||
|
*/
|
||||||
|
private fun loadStreamInfo(playlistPath: String, csrfToken: String): List<String> = runBlocking {
|
||||||
withContext(Dispatchers.Default) {
|
withContext(Dispatchers.Default) {
|
||||||
println(baseURL + playlistPath)
|
|
||||||
|
|
||||||
val headers = mutableMapOf(
|
val headers = mutableMapOf(
|
||||||
Pair("Accept", "application/json, text/javascript, */*; q=0.01"),
|
Pair("Accept", "application/json, text/javascript, */*; q=0.01"),
|
||||||
Pair("Accept-Language", "de,en-US;q=0.7,en;q=0.3"),
|
Pair("Accept-Language", "de,en-US;q=0.7,en;q=0.3"),
|
||||||
|
@ -126,7 +133,6 @@ class AoDParser {
|
||||||
Pair("X-Requested-With", "XMLHttpRequest"),
|
Pair("X-Requested-With", "XMLHttpRequest"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
val res = Jsoup.connect(baseURL + playlistPath)
|
val res = Jsoup.connect(baseURL + playlistPath)
|
||||||
.ignoreContentType(true)
|
.ignoreContentType(true)
|
||||||
.cookies(sessionCookies)
|
.cookies(sessionCookies)
|
||||||
|
@ -135,16 +141,15 @@ class AoDParser {
|
||||||
|
|
||||||
//println(res.body())
|
//println(res.body())
|
||||||
|
|
||||||
// TODO replace with gson
|
// TODO if it's a series there sources for each episode
|
||||||
val jsonObject = JSONObject(res.body())
|
val sources = JsonParser.parseString(res.body()).asJsonObject
|
||||||
val sourcesObject = jsonObject.getJSONArray("playlist").get(0).toString()
|
.get("playlist").asJsonArray.first().asJsonObject
|
||||||
|
.get("sources").asJsonArray
|
||||||
|
|
||||||
val sourcesArray = JSONObject(sourcesObject).getJSONArray("sources")
|
return@withContext sources.toList().map {
|
||||||
|
it.asJsonObject.get("file").toString()
|
||||||
for (i in 0 until sourcesArray.length()) {
|
|
||||||
println(sourcesArray[i].toString())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
package org.mosad.teapod.ui
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
import kotlinx.android.synthetic.main.fragment_media.*
|
||||||
|
import org.mosad.teapod.R
|
||||||
|
import org.mosad.teapod.util.GUIMedia
|
||||||
|
|
||||||
|
class MediaFragment(val media: GUIMedia, val streams: List<String>) : Fragment() {
|
||||||
|
|
||||||
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||||
|
return inflater.inflate(R.layout.fragment_media, container, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
// load poster
|
||||||
|
Glide.with(requireContext()).load(media.posterLink).into(image_poster)
|
||||||
|
text_title.text = media.title
|
||||||
|
text_desc.text = media.shortDesc
|
||||||
|
|
||||||
|
println("media streams: $streams")
|
||||||
|
|
||||||
|
initActions()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initActions() {
|
||||||
|
button_play.setOnClickListener { onClickButtonPlay() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onClickButtonPlay() {
|
||||||
|
println("play ${streams.first()}")
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -27,6 +27,6 @@ class HomeFragment : Fragment() {
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
println("created!!!!")
|
println("HomeFragment created")
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -5,10 +5,13 @@ 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.fragment.app.commit
|
||||||
import kotlinx.android.synthetic.main.fragment_library.*
|
import kotlinx.android.synthetic.main.fragment_library.*
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
|
import org.mosad.teapod.MainActivity
|
||||||
import org.mosad.teapod.R
|
import org.mosad.teapod.R
|
||||||
import org.mosad.teapod.parser.AoDParser
|
import org.mosad.teapod.parser.AoDParser
|
||||||
|
import org.mosad.teapod.ui.MediaFragment
|
||||||
import org.mosad.teapod.util.CustomAdapter
|
import org.mosad.teapod.util.CustomAdapter
|
||||||
import org.mosad.teapod.util.GUIMedia
|
import org.mosad.teapod.util.GUIMedia
|
||||||
|
|
||||||
|
@ -19,6 +22,7 @@ class LibraryFragment : Fragment() {
|
||||||
private var mediaList = arrayListOf<GUIMedia>()
|
private var mediaList = arrayListOf<GUIMedia>()
|
||||||
private lateinit var adapter : CustomAdapter
|
private lateinit var adapter : CustomAdapter
|
||||||
|
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||||
return inflater.inflate(R.layout.fragment_library, container, false)
|
return inflater.inflate(R.layout.fragment_library, container, false)
|
||||||
}
|
}
|
||||||
|
@ -27,7 +31,11 @@ class LibraryFragment : Fragment() {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
GlobalScope.launch {
|
GlobalScope.launch {
|
||||||
mediaList = parser.listAnimes()
|
if (AoDParser.mediaList.isEmpty()) {
|
||||||
|
AoDParser().listAnimes()
|
||||||
|
}
|
||||||
|
|
||||||
|
mediaList = AoDParser.mediaList
|
||||||
|
|
||||||
// create and set the adapter, needs context
|
// create and set the adapter, needs context
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
|
@ -43,14 +51,33 @@ class LibraryFragment : Fragment() {
|
||||||
private fun initActions() {
|
private fun initActions() {
|
||||||
list_library.setOnItemClickListener { parent, view, position, id ->
|
list_library.setOnItemClickListener { parent, view, position, id ->
|
||||||
println("selected item is: ${mediaList[position]}")
|
println("selected item is: ${mediaList[position]}")
|
||||||
showDetailFragment(mediaList[position])
|
//showDetailFragment(mediaList[position])
|
||||||
|
|
||||||
|
val mainActivity = activity as MainActivity
|
||||||
|
mainActivity.showDetailFragment(mediaList[position])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showDetailFragment(media: GUIMedia) {
|
private fun showDetailFragment(media: GUIMedia) {
|
||||||
parser.loadDetails(media.link)
|
val streams = parser.loadStreams(media.link) // load the streams for the selected media
|
||||||
|
println("done: $streams")
|
||||||
|
|
||||||
println("done")
|
// TODO create detail fragment
|
||||||
|
val mediaFragment = MediaFragment(media, streams)
|
||||||
|
|
||||||
|
activity?.supportFragmentManager?.commit {
|
||||||
|
add(mediaFragment, "MediaFragment")
|
||||||
|
addToBackStack(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
// activity?.supportFragmentManager?.beginTransaction()?.let {
|
||||||
|
// it.replace(mContainer.id, mediaFragment, "MediaFragment")
|
||||||
|
// it.addToBackStack("MediaFragment")
|
||||||
|
// it.commit()
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
println("done!!!")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,22 +1,23 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.constraintlayout.widget.ConstraintLayout 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"
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
tools:context=".ui.account.AccountFragment">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/text_account"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
android:layout_marginStart="8dp"
|
android:background="#fafafa"
|
||||||
android:layout_marginTop="8dp"
|
tools:context=".ui.account.AccountFragment">
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:textAlignment="center"
|
<TextView
|
||||||
android:textSize="20sp"
|
android:id="@+id/text_account"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
android:layout_width="match_parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
android:layout_height="wrap_content"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
android:layout_marginStart="8dp"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:textSize="20sp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -4,6 +4,7 @@
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:background="#fafafa"
|
||||||
tools:context=".ui.home.HomeFragment">
|
tools:context=".ui.home.HomeFragment">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:background="#fafafa"
|
||||||
tools:context=".ui.library.LibraryFragment">
|
tools:context=".ui.library.LibraryFragment">
|
||||||
|
|
||||||
<ListView
|
<ListView
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="#fafafa"
|
||||||
|
tools:context=".ui.MediaFragment">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/image_poster"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="108dp"
|
||||||
|
android:layout_marginTop="40dp"
|
||||||
|
android:src="@drawable/ic_launcher_background"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/button_play"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:layout_marginStart="7dp"
|
||||||
|
android:layout_marginTop="25dp"
|
||||||
|
android:layout_marginEnd="7dp"
|
||||||
|
android:text="Play"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/image_poster" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text_title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="19dp"
|
||||||
|
android:layout_marginStart="7dp"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:layout_marginEnd="7dp"
|
||||||
|
android:text="TextView"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/button_play" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text_desc"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="17dp"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:layout_marginEnd="17dp"
|
||||||
|
android:text="TextView"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/text_title" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
</FrameLayout>
|
|
@ -4,6 +4,7 @@
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:background="#fafafa"
|
||||||
tools:context=".ui.search.SearchFragment">
|
tools:context=".ui.search.SearchFragment">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
|
Loading…
Reference in New Issue