youtube motion done!

next is exoplayer damn it
This commit is contained in:
Farbod 2021-12-12 16:08:23 +04:00
parent f735a69dc2
commit 972d1497a3
20 changed files with 796 additions and 32 deletions

37
.idea/deploymentTargetDropDown.xml generated Normal file
View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetDropDown">
<runningDeviceTargetSelectedWithDropDown>
<Target>
<type value="RUNNING_DEVICE_TARGET" />
<deviceKey>
<Key>
<type value="SERIAL_NUMBER" />
<value value="3100ad43a3044300" />
</Key>
</deviceKey>
</Target>
</runningDeviceTargetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2021-12-12T11:35:38.344385Z" />
<runningDeviceTargetsSelectedWithDialog>
<Target>
<type value="RUNNING_DEVICE_TARGET" />
<deviceKey>
<Key>
<type value="SERIAL_NUMBER" />
<value value="3100ad43a3044300" />
</Key>
</deviceKey>
</Target>
<Target>
<type value="RUNNING_DEVICE_TARGET" />
<deviceKey>
<Key>
<type value="VIRTUAL_DEVICE_PATH" />
<value value="$USER_HOME$/.android/avd/Pixel_5_API_22.avd" />
</Key>
</deviceKey>
</Target>
</runningDeviceTargetsSelectedWithDialog>
</component>
</project>

8
.idea/misc.xml generated
View File

@ -3,9 +3,13 @@
<component name="DesignSurface"> <component name="DesignSurface">
<option name="filePathToZoomLevelMap"> <option name="filePathToZoomLevelMap">
<map> <map>
<entry key="app/src/main/res/layout/activity_main.xml" value="0.11911231884057971" /> <entry key="app/src/main/res/drawable/ic_close.xml" value="0.17135416666666667" />
<entry key="app/src/main/res/layout/fragment_home.xml" value="0.1" /> <entry key="app/src/main/res/drawable/ic_play.xml" value="0.17135416666666667" />
<entry key="app/src/main/res/layout/activity_main.xml" value="0.1" />
<entry key="app/src/main/res/layout/activity_player.xml" value="0.1" />
<entry key="app/src/main/res/layout/fragment_home.xml" value="0.16" />
<entry key="app/src/main/res/layout/fragment_library.xml" value="0.11956521739130435" /> <entry key="app/src/main/res/layout/fragment_library.xml" value="0.11956521739130435" />
<entry key="app/src/main/res/layout/fragment_player.xml" value="0.15520833333333334" />
<entry key="app/src/main/res/layout/fragment_subscriptions.xml" value="0.1" /> <entry key="app/src/main/res/layout/fragment_subscriptions.xml" value="0.1" />
<entry key="app/src/main/res/layout/trending_row.xml" value="0.33" /> <entry key="app/src/main/res/layout/trending_row.xml" value="0.33" />
<entry key="app/src/main/res/menu/bottom_menu.xml" value="0.15520833333333334" /> <entry key="app/src/main/res/menu/bottom_menu.xml" value="0.15520833333333334" />

View File

@ -12,7 +12,7 @@ android {
targetSdk 31 targetSdk 31
versionCode 1 versionCode 1
versionName "1.0" versionName "1.0"
multiDexEnabled true
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
} }
@ -21,6 +21,7 @@ android {
minifyEnabled false minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
} }
} }
compileOptions { compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_1_8
@ -46,4 +47,7 @@ dependencies {
implementation 'com.google.code.gson:gson:2.8.9' implementation 'com.google.code.gson:gson:2.8.9'
implementation 'com.squareup.picasso:picasso:2.8' implementation 'com.squareup.picasso:picasso:2.8'
implementation 'de.hdodenhof:circleimageview:3.1.0' implementation 'de.hdodenhof:circleimageview:3.1.0'
implementation 'com.google.android.exoplayer:exoplayer:2.16.1'
implementation("androidx.multidex:multidex:2.0.1")
} }

View File

@ -1,7 +1,9 @@
<?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="xyz.btcland.libretube"> package="xyz.btcland.libretube">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.INTERNET" />
<application <application
android:allowBackup="true" android:allowBackup="true"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
@ -9,6 +11,11 @@
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.LibreTube"> android:theme="@style/Theme.LibreTube">
<activity
android:name=".Player"
android:exported="false"
android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen"
/>
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:exported="true"> android:exported="true">

View File

@ -6,9 +6,7 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ProgressBar import android.widget.ProgressBar
import android.widget.TextView
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.google.gson.GsonBuilder import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken import com.google.gson.reflect.TypeToken
@ -97,8 +95,8 @@ class Home : Fragment() {
val body = response.body!!.string() val body = response.body!!.string()
println(body) println(body)
val gson = GsonBuilder().create() val gson = GsonBuilder().create()
val itemType = object : TypeToken<List<Trending>>() {}.type val itemType = object : TypeToken<List<Video>>() {}.type
val trendingList = gson.fromJson<List<Trending>>(body, itemType) val trendingList = gson.fromJson<List<Video>>(body, itemType)
runOnUiThread { runOnUiThread {
progressBar.visibility = View.GONE progressBar.visibility = View.GONE
recyclerView.adapter = TrendingAdapter(trendingList) recyclerView.adapter = TrendingAdapter(trendingList)

View File

@ -2,6 +2,8 @@ package xyz.btcland.libretube
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle import android.os.Bundle
import android.widget.FrameLayout
import androidx.fragment.app.Fragment
import com.google.android.material.bottomnavigation.BottomNavigationView import com.google.android.material.bottomnavigation.BottomNavigationView
import androidx.navigation.findNavController import androidx.navigation.findNavController
import androidx.navigation.ui.setupWithNavController import androidx.navigation.ui.setupWithNavController
@ -13,5 +15,7 @@ class MainActivity : AppCompatActivity() {
val bottomNavigationView = findViewById<BottomNavigationView>(R.id.bottomNav) val bottomNavigationView = findViewById<BottomNavigationView>(R.id.bottomNav)
val navController = findNavController(R.id.fragment) val navController = findNavController(R.id.fragment)
bottomNavigationView.setupWithNavController(navController) bottomNavigationView.setupWithNavController(navController)
} }
} }

View File

@ -0,0 +1,14 @@
package xyz.btcland.libretube
import android.app.Activity
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
class Player : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_player)
val videoId=intent.getStringExtra("videoId")
println(videoId)
}
}

View File

@ -0,0 +1,114 @@
package xyz.btcland.libretube
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.constraintlayout.motion.widget.MotionLayout
import androidx.constraintlayout.widget.ConstraintSet
import kotlin.math.abs
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"
/**
* A simple [Fragment] subclass.
* Use the [PlayerFragment.newInstance] factory method to
* create an instance of this fragment.
*/
class PlayerFragment : Fragment() {
// TODO: Rename and change types of parameters
private var videoId: String? = null
private var param2: String? = null
private var lastProgress: Float = 0.toFloat()
private var sId: Int=0
private var eId: Int=0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
videoId = it.getString("videoId")
param2 = it.getString(ARG_PARAM2)
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_player, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val playerMotionLayout = view.findViewById<SingleViewTouchableMotionLayout>(R.id.playerMotionLayout)
view.findViewById<TextView>(R.id.textTest).text = videoId
playerMotionLayout.addTransitionListener(object: MotionLayout.TransitionListener {
override fun onTransitionStarted(
motionLayout: MotionLayout?,
startId: Int,
endId: Int
) {
}
override fun onTransitionChange(motionLayout: MotionLayout?, startId: Int, endId: Int, progress: Float) {
val mainActivity = activity as MainActivity
val mainMotionLayout = mainActivity.findViewById<MotionLayout>(R.id.mainMotionLayout)
mainMotionLayout.progress = abs(progress)
eId=endId
sId=startId
}
override fun onTransitionCompleted(motionLayout: MotionLayout?, currentId: Int) {
println(currentId)
val mainActivity = activity as MainActivity
val mainMotionLayout = mainActivity.findViewById<MotionLayout>(R.id.mainMotionLayout)
if (currentId==eId) {
mainMotionLayout.progress = 1.toFloat()
}else if(currentId==sId){
mainMotionLayout.progress = 0.toFloat()
}
}
override fun onTransitionTrigger(
motionLayout: MotionLayout?,
triggerId: Int,
positive: Boolean,
progress: Float
) {
}
})
playerMotionLayout.progress=1.toFloat()
playerMotionLayout.transitionToStart()
}
companion object {
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment PlayerFragment.
*/
// TODO: Rename and change types and number of parameters
@JvmStatic
fun newInstance(param1: String, param2: String) =
PlayerFragment().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
putString(ARG_PARAM2, param2)
}
}
}
}

View File

@ -0,0 +1,115 @@
package xyz.btcland.libretube
import android.content.Context
import android.graphics.Rect
import android.util.AttributeSet
import android.util.Log
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.View
import androidx.constraintlayout.motion.widget.MotionLayout
import androidx.recyclerview.widget.RecyclerView
/**
*
* Created by Arman Chatikyan on 05 Sep 2018
*
*/
class SingleViewTouchableMotionLayout(context: Context, attributeSet: AttributeSet? = null) : MotionLayout(context, attributeSet) {
private val viewToDetectTouch by lazy {
findViewById<View>(R.id.main_container) //TODO move to Attributes
}
private val viewRect = Rect()
private var touchStarted = false
private val transitionListenerList = mutableListOf<TransitionListener?>()
init {
addTransitionListener(object : MotionLayout.TransitionListener {
override fun onTransitionStarted(
motionLayout: MotionLayout?,
startId: Int,
endId: Int
) {
}
override fun onTransitionChange(p0: MotionLayout?, p1: Int, p2: Int, p3: Float) {
}
override fun onTransitionCompleted(p0: MotionLayout?, p1: Int) {
touchStarted = false
}
override fun onTransitionTrigger(
motionLayout: MotionLayout?,
triggerId: Int,
positive: Boolean,
progress: Float
) {
}
})
super.setTransitionListener(object : MotionLayout.TransitionListener {
override fun onTransitionStarted(
motionLayout: MotionLayout?,
startId: Int,
endId: Int
) {
}
override fun onTransitionChange(p0: MotionLayout?, p1: Int, p2: Int, p3: Float) {
transitionListenerList.filterNotNull()
.forEach { it.onTransitionChange(p0, p1, p2, p3) }
}
override fun onTransitionCompleted(p0: MotionLayout?, p1: Int) {
transitionListenerList.filterNotNull()
.forEach { it.onTransitionCompleted(p0, p1) }
}
override fun onTransitionTrigger(
motionLayout: MotionLayout?,
triggerId: Int,
positive: Boolean,
progress: Float
) {
}
})
}
override fun setTransitionListener(listener: TransitionListener?) {
addTransitionListener(listener)
}
override fun addTransitionListener(listener: TransitionListener?) {
transitionListenerList += listener
}
private val gestureDetector = GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() {
override fun onSingleTapConfirmed(e: MotionEvent?): Boolean {
transitionToEnd()
return false
}
})
override fun onTouchEvent(event: MotionEvent): Boolean {
//gestureDetector.onTouchEvent(event)
when (event.actionMasked) {
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
touchStarted = false
return super.onTouchEvent(event)
}
}
if (!touchStarted) {
viewToDetectTouch.getHitRect(viewRect)
touchStarted = viewRect.contains(event.x.toInt(), event.y.toInt())
}
return touchStarted && super.onTouchEvent(event)
}
}

View File

@ -1,14 +0,0 @@
package xyz.btcland.libretube
data class Trending(
val url: String,
val title: String,
val thumbnail: String,
val uploaderName: String,
val uploaderUrl:String,
val uploaderAvatar:String,
val uploadedDate: String,
val duration: Int,
val views: Int,
val uploaderVerified: Boolean
)

View File

@ -1,18 +1,21 @@
package xyz.btcland.libretube package xyz.btcland.libretube
import android.content.Intent
import android.os.Bundle
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.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.squareup.picasso.Picasso import com.squareup.picasso.Picasso
import java.math.BigDecimal import java.math.BigDecimal
import java.math.RoundingMode import java.math.RoundingMode
class TrendingAdapter(private val trendingFeed: List<Trending>): RecyclerView.Adapter<CustomViewHolder>() { class TrendingAdapter(private val videoFeed: List<Video>): RecyclerView.Adapter<CustomViewHolder>() {
override fun getItemCount(): Int { override fun getItemCount(): Int {
return trendingFeed.size return videoFeed.size
} }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomViewHolder {
@ -22,17 +25,34 @@ class TrendingAdapter(private val trendingFeed: List<Trending>): RecyclerView.Ad
} }
override fun onBindViewHolder(holder: CustomViewHolder, position: Int) { override fun onBindViewHolder(holder: CustomViewHolder, position: Int) {
val trending = trendingFeed[position] val trending = videoFeed[position]
holder.v.findViewById<TextView>(R.id.textView_title).text = trending.title holder.v.findViewById<TextView>(R.id.textView_title).text = trending.title
holder.v.findViewById<TextView>(R.id.textView_channel).text = trending.uploaderName +""+ videoViews(trending.views)+""+trending.uploadedDate holder.v.findViewById<TextView>(R.id.textView_channel).text = trending.uploaderName +""+ videoViews(trending.views)+""+trending.uploadedDate
val thumbnailImage = holder.v.findViewById<ImageView>(R.id.thumbnail) val thumbnailImage = holder.v.findViewById<ImageView>(R.id.thumbnail)
val channelImage = holder.v.findViewById<ImageView>(R.id.channel_image) val channelImage = holder.v.findViewById<ImageView>(R.id.channel_image)
channelImage.setOnClickListener{
println("channel clicked")
}
Picasso.get().load(trending.thumbnail).into(thumbnailImage) Picasso.get().load(trending.thumbnail).into(thumbnailImage)
Picasso.get().load(trending.uploaderAvatar).into(channelImage) Picasso.get().load(trending.uploaderAvatar).into(channelImage)
holder.v.setOnClickListener{
//val intent = Intent(holder.v.context, Player::class.java)
//intent.putExtra("videoId",trending.url.replace("/watch?v=",""))
//holder.v.context.startActivity(intent)
var bundle = Bundle()
bundle.putString("videoId",trending.url.replace("/watch?v=",""))
var frag = PlayerFragment()
frag.arguments = bundle
val activity = holder.v.context as AppCompatActivity
activity.supportFragmentManager.beginTransaction()
.add(R.id.container, frag)
.commitNow()
}
} }
} }
class CustomViewHolder(val v: View): RecyclerView.ViewHolder(v){ class CustomViewHolder(val v: View): RecyclerView.ViewHolder(v){
init {
}
} }
fun videoViews(views: Int): String{ fun videoViews(views: Int): String{
when { when {

View File

@ -1,6 +1,14 @@
package xyz.btcland.libretube package xyz.btcland.libretube
data class Video( data class Video(
val id: Int, val url: String,
val title: String,
val thumbnail: String,
val uploaderName: String,
val uploaderUrl:String,
val uploaderAvatar:String,
val uploadedDate: String,
val duration: Int,
val views: Int,
val uploaderVerified: Boolean
) )

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/black"
android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/>
</vector>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/black"
android:pathData="M8,5v14l11,-7z"/>
</vector>

View File

@ -1,10 +1,13 @@
<?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.motion.widget.MotionLayout 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_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context=".MainActivity"> app:layoutDescription="@xml/activity_main_scene"
tools:context=".MainActivity"
android:id="@+id/mainMotionLayout"
>
<com.google.android.material.bottomnavigation.BottomNavigationView <com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottomNav" android:id="@+id/bottomNav"
@ -14,7 +17,7 @@
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:menu="@menu/bottom_menu"/> app:menu="@menu/bottom_menu" />
<fragment <fragment
android:id="@+id/fragment" android:id="@+id/fragment"
@ -26,4 +29,15 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/nav" /> app:navGraph="@navigation/nav" />
</androidx.constraintlayout.widget.ConstraintLayout>
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:elevation="20dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:background="@android:color/transparent"
/>
</androidx.constraintlayout.motion.widget.MotionLayout>

View File

@ -0,0 +1,96 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.motion.widget.MotionLayout 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"
app:layoutDescription="@xml/activity_player_scene"
tools:context=".Player"
android:background="#00ffffff"
>
<ScrollView
android:id="@+id/scrollView2"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/main_container">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="fuckkkkkkkkkkkkkkkkkkkkkkkkkkkkk"/>
</LinearLayout>
</ScrollView>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/main_container"
android:layout_width="match_parent"
android:layout_height="250dp"
android:background="#10000000"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</androidx.constraintlayout.widget.ConstraintLayout>
<com.google.android.exoplayer2.ui.PlayerView
android:id="@+id/player"
android:layout_width="match_parent"
android:layout_height="0dp"
android:scaleType="centerCrop"
app:layout_constraintBottom_toBottomOf="@id/main_container"
app:layout_constraintStart_toStartOf="@id/main_container"
app:layout_constraintTop_toTopOf="@id/main_container"
/>
<ImageView
android:id="@+id/close_imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:alpha="0"
app:layout_constraintBottom_toBottomOf="@id/main_container"
app:layout_constraintEnd_toEndOf="@id/main_container"
app:layout_constraintTop_toTopOf="@id/main_container"
android:src="@drawable/ic_close"
/>
<ImageView
android:id="@+id/play_imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="24dp"
android:alpha="0"
app:layout_constraintBottom_toBottomOf="@+id/close_imageView"
app:layout_constraintEnd_toStartOf="@+id/close_imageView"
app:layout_constraintTop_toTopOf="@+id/close_imageView"
android:src="@drawable/ic_play"
/>
<TextView
android:id="@+id/title_textView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="12dp"
android:alpha="0"
android:ellipsize="end"
android:maxLines="1"
android:text="This is very very very very long title"
app:layout_constraintBottom_toBottomOf="@+id/play_imageView"
app:layout_constraintEnd_toStartOf="@+id/play_imageView"
app:layout_constraintStart_toEndOf="@+id/player"
app:layout_constraintTop_toTopOf="@+id/play_imageView" />
</androidx.constraintlayout.motion.widget.MotionLayout>

View File

@ -0,0 +1,99 @@
<?xml version="1.0" encoding="utf-8"?>
<xyz.btcland.libretube.SingleViewTouchableMotionLayout 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"
app:layoutDescription="@xml/player_scene"
tools:context=".PlayerFragment"
android:background="@android:color/transparent"
android:id="@+id/playerMotionLayout"
>
<ScrollView
android:id="@+id/scrollView2"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/main_container"
android:background="@color/white"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/textTest"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="fuckkkkkkkkkkkkkkkkkkkkkkkkkkkkk"/>
</LinearLayout>
</ScrollView>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/main_container"
android:layout_width="match_parent"
android:layout_height="350dp"
android:background="#EBFFFFFF"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</androidx.constraintlayout.widget.ConstraintLayout>
<com.google.android.exoplayer2.ui.PlayerView
android:id="@+id/player"
android:layout_width="match_parent"
android:layout_height="0dp"
android:scaleType="centerCrop"
app:layout_constraintBottom_toBottomOf="@id/main_container"
app:layout_constraintStart_toStartOf="@id/main_container"
app:layout_constraintTop_toTopOf="@id/main_container"
/>
<ImageView
android:id="@+id/close_imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:alpha="0"
app:layout_constraintBottom_toBottomOf="@id/main_container"
app:layout_constraintEnd_toEndOf="@id/main_container"
app:layout_constraintTop_toTopOf="@id/main_container"
android:src="@drawable/ic_close"
/>
<ImageView
android:id="@+id/play_imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="24dp"
android:alpha="0"
android:src="@drawable/ic_play"
app:layout_constraintBottom_toBottomOf="@+id/close_imageView"
app:layout_constraintEnd_toStartOf="@+id/close_imageView"
app:layout_constraintTop_toTopOf="@+id/close_imageView" />
<TextView
android:id="@+id/title_textView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="12dp"
android:alpha="0"
android:ellipsize="end"
android:maxLines="1"
android:text="This is very very very very long title"
app:layout_constraintBottom_toBottomOf="@+id/play_imageView"
app:layout_constraintEnd_toStartOf="@+id/play_imageView"
app:layout_constraintStart_toEndOf="@+id/player"
app:layout_constraintTop_toTopOf="@+id/play_imageView" />
</xyz.btcland.libretube.SingleViewTouchableMotionLayout>

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<MotionScene
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:motion="http://schemas.android.com/apk/res-auto">
<Transition
motion:constraintSetEnd="@+id/end"
motion:constraintSetStart="@id/start"
motion:duration="10"
motion:layoutDuringTransition="honorRequest"
>
<KeyFrameSet>
<KeyAttribute
motion:motionTarget="@+id/bottomNav"
motion:framePosition="0"
android:translationY="0dp" />
<KeyAttribute
motion:motionTarget="@+id/bottomNav"
motion:framePosition="75"
android:translationY="55dp" />
<KeyAttribute
motion:motionTarget="@+id/container"
motion:framePosition="50"
android:scaleY="1" />
<KeyAttribute
motion:motionTarget="@+id/container"
motion:framePosition="100"
android:scaleY="0.86" />
</KeyFrameSet>
</Transition>
<ConstraintSet android:id="@+id/start">
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
</ConstraintSet>
</MotionScene>

View File

@ -0,0 +1,91 @@
<?xml version="1.0" encoding="utf-8"?>
<MotionScene
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:motion="http://schemas.android.com/apk/res-auto">
<Transition
motion:constraintSetEnd="@+id/end"
motion:constraintSetStart="@id/start"
motion:duration="1000">
<KeyFrameSet>
<KeyAttribute
motion:motionTarget="@+id/close_imageView"
motion:framePosition="90"
android:alpha="0" />
<KeyAttribute
motion:motionTarget="@+id/play_imageView"
motion:framePosition="90"
android:alpha="0" />
<KeyAttribute
motion:motionTarget="@+id/title_textView"
motion:framePosition="95"
android:alpha="0" />
</KeyFrameSet>
<OnSwipe
motion:touchAnchorId="@+id/main_container"
motion:dragDirection="dragDown"
motion:touchAnchorSide="bottom" />
</Transition>
<ConstraintSet android:id="@+id/start">
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
<Constraint
android:id="@+id/scrollView2"
motion:layout_constraintEnd_toEndOf="parent"
android:layout_width="0dp"
android:layout_height="1dp"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintTop_toBottomOf="@+id/main_container"
motion:layout_constraintHorizontal_bias="0.5"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintVertical_bias="1.0" />
<Constraint
android:id="@+id/main_container"
motion:layout_constraintEnd_toEndOf="parent"
android:layout_width="match_parent"
android:layout_height="54dp"
motion:layout_constraintHorizontal_bias="0.5"
motion:layout_constraintTop_toTopOf="parent"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintVertical_bias="1.0" />
<Constraint
android:id="@+id/player"
android:layout_width="100dp"
android:layout_height="0dp"
motion:layout_constraintBottom_toBottomOf="@id/main_container"
motion:layout_constraintTop_toTopOf="@id/main_container"
motion:layout_constraintStart_toStartOf="@id/main_container" />
<Constraint
android:id="@+id/close_imageView"
motion:layout_constraintEnd_toEndOf="@id/main_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
motion:layout_constraintBottom_toBottomOf="@id/main_container"
android:layout_marginEnd="16dp"
android:alpha="1"
motion:layout_constraintTop_toTopOf="@id/main_container" />
<Constraint
android:id="@+id/play_imageView"
motion:layout_constraintEnd_toStartOf="@+id/close_imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
motion:layout_constraintBottom_toBottomOf="@+id/close_imageView"
android:layout_marginEnd="24dp"
android:alpha="1"
motion:layout_constraintTop_toTopOf="@+id/close_imageView" />
<Constraint
android:id="@+id/title_textView"
motion:layout_constraintEnd_toStartOf="@+id/play_imageView"
motion:layout_constraintStart_toEndOf="@+id/player"
android:layout_width="0dp"
android:layout_height="wrap_content"
motion:layout_constraintBottom_toBottomOf="@+id/play_imageView"
android:layout_marginEnd="12dp"
android:alpha="1"
android:layout_marginStart="8dp"
motion:layout_constraintTop_toTopOf="@+id/play_imageView" />
</ConstraintSet>
</MotionScene>

View File

@ -0,0 +1,96 @@
<?xml version="1.0" encoding="utf-8"?>
<MotionScene
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:motion="http://schemas.android.com/apk/res-auto">
<Transition
motion:constraintSetEnd="@+id/end"
motion:constraintSetStart="@id/start"
motion:duration="10"
motion:motionInterpolator="easeInOut"
>
<KeyFrameSet>
<KeyAttribute
motion:motionTarget="@+id/close_imageView"
motion:framePosition="90"
android:alpha="0" />
<KeyAttribute
motion:motionTarget="@+id/play_imageView"
motion:framePosition="90"
android:alpha="0" />
<KeyAttribute
motion:motionTarget="@+id/title_textView"
motion:framePosition="95"
android:alpha="0" />
</KeyFrameSet>
<OnSwipe
motion:touchAnchorId="@+id/main_container"
motion:dragDirection="dragDown"
motion:touchAnchorSide="bottom"
motion:maxAcceleration="40"
motion:dragScale="6"
/>
</Transition>
<ConstraintSet android:id="@+id/start">
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
<Constraint
android:id="@+id/scrollView2"
motion:layout_constraintEnd_toEndOf="parent"
android:layout_width="0dp"
android:layout_height="1dp"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintTop_toBottomOf="@+id/main_container"
motion:layout_constraintHorizontal_bias="0.5"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintVertical_bias="1.0" />
<Constraint
android:id="@+id/main_container"
motion:layout_constraintEnd_toEndOf="parent"
android:layout_width="match_parent"
android:layout_height="54dp"
motion:layout_constraintHorizontal_bias="0.5"
motion:layout_constraintTop_toTopOf="parent"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintVertical_bias="1.0" />
<Constraint
android:id="@+id/player"
android:layout_width="100dp"
android:layout_height="0dp"
motion:layout_constraintBottom_toBottomOf="@id/main_container"
motion:layout_constraintTop_toTopOf="@id/main_container"
motion:layout_constraintStart_toStartOf="@id/main_container" />
<Constraint
android:id="@+id/close_imageView"
motion:layout_constraintEnd_toEndOf="@id/main_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
motion:layout_constraintBottom_toBottomOf="@id/main_container"
android:layout_marginEnd="16dp"
android:alpha="1"
motion:layout_constraintTop_toTopOf="@id/main_container" />
<Constraint
android:id="@+id/play_imageView"
motion:layout_constraintEnd_toStartOf="@+id/close_imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
motion:layout_constraintBottom_toBottomOf="@+id/close_imageView"
android:layout_marginEnd="24dp"
android:alpha="1"
motion:layout_constraintTop_toTopOf="@+id/close_imageView" />
<Constraint
android:id="@+id/title_textView"
motion:layout_constraintEnd_toStartOf="@+id/play_imageView"
motion:layout_constraintStart_toEndOf="@+id/player"
android:layout_width="0dp"
android:layout_height="wrap_content"
motion:layout_constraintBottom_toBottomOf="@+id/play_imageView"
android:layout_marginEnd="12dp"
android:alpha="1"
android:layout_marginStart="8dp"
motion:layout_constraintTop_toTopOf="@+id/play_imageView" />
</ConstraintSet>
</MotionScene>