Search Recyclerview layouts

This commit is contained in:
rimthekid 2022-01-20 15:58:59 +04:00
parent f5aebe4b13
commit b03920d816
13 changed files with 365 additions and 54 deletions

View File

@ -12,7 +12,7 @@
</deviceKey> </deviceKey>
</Target> </Target>
</targetSelectedWithDropDown> </targetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2021-12-17T12:50:01.440166Z" /> <timeTargetWasSelectedWithDropDown value="2022-01-20T11:48:34.927750Z" />
<runningDeviceTargetsSelectedWithDialog> <runningDeviceTargetsSelectedWithDialog>
<Target> <Target>
<type value="RUNNING_DEVICE_TARGET" /> <type value="RUNNING_DEVICE_TARGET" />

3
.idea/misc.xml generated
View File

@ -9,15 +9,18 @@
<entry key="app/src/main/res/layout-land/fragment_player.xml" value="0.1" /> <entry key="app/src/main/res/layout-land/fragment_player.xml" value="0.1" />
<entry key="app/src/main/res/layout/activity_main.xml" value="0.1" /> <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/activity_player.xml" value="0.1" />
<entry key="app/src/main/res/layout/channel_search_row.xml" value="0.33" />
<entry key="app/src/main/res/layout/exo_styled_player_control_view.xml" value="0.12" /> <entry key="app/src/main/res/layout/exo_styled_player_control_view.xml" value="0.12" />
<entry key="app/src/main/res/layout/fragment_home.xml" value="0.16" /> <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.1" /> <entry key="app/src/main/res/layout/fragment_player.xml" value="0.1" />
<entry key="app/src/main/res/layout/fragment_search.xml" value="0.25" /> <entry key="app/src/main/res/layout/fragment_search.xml" value="0.25" />
<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/playlist_search_row.xml" value="0.33" />
<entry key="app/src/main/res/layout/styled_quality_list.xml" value="0.15520833333333334" /> <entry key="app/src/main/res/layout/styled_quality_list.xml" value="0.15520833333333334" />
<entry key="app/src/main/res/layout/styled_quality_list_item.xml" value="0.15520833333333334" /> <entry key="app/src/main/res/layout/styled_quality_list_item.xml" value="0.15520833333333334" />
<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/layout/video_search_row.xml" value="0.25" />
<entry key="app/src/main/res/menu/action_bar.xml" value="0.2" /> <entry key="app/src/main/res/menu/action_bar.xml" value="0.2" />
<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" />
<entry key="app/src/main/res/xml-land/player_scene.xml" value="0.13139329805996472" /> <entry key="app/src/main/res/xml-land/player_scene.xml" value="0.13139329805996472" />

View File

@ -13,8 +13,8 @@ import androidx.recyclerview.widget.RecyclerView
import okhttp3.* import okhttp3.*
import retrofit2.HttpException import retrofit2.HttpException
import xyz.btcland.libretube.adapters.TrendingAdapter
import java.io.IOException import java.io.IOException
import java.lang.Exception
// TODO: Rename parameter arguments, choose names that match // TODO: Rename parameter arguments, choose names that match
@ -54,7 +54,6 @@ class Home : Fragment() {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
val recyclerView = view.findViewById<RecyclerView>(R.id.recview) val recyclerView = view.findViewById<RecyclerView>(R.id.recview)
recyclerView.layoutManager = GridLayoutManager(view.context, resources.getInteger(R.integer.grid_items)) recyclerView.layoutManager = GridLayoutManager(view.context, resources.getInteger(R.integer.grid_items))
val progressbar = view.findViewById<ProgressBar>(R.id.progressBar) val progressbar = view.findViewById<ProgressBar>(R.id.progressBar)
fetchJson(progressbar,recyclerView) fetchJson(progressbar,recyclerView)
@ -82,31 +81,7 @@ class Home : Fragment() {
} }
private fun fetchJson(progressBar: ProgressBar, recyclerView: RecyclerView) { private fun fetchJson(progressBar: ProgressBar, recyclerView: RecyclerView) {
//val client = OkHttpClient()
fun run() { fun run() {
/* val request = Request.Builder()
.url("http://piped-api.alefvanoon.xyz/trending?region=US")
.build()
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
e.printStackTrace()
}
override fun onResponse(call: Call, response: Response) {
response.use {
if (!response.isSuccessful) throw IOException("Unexpected code $response")
val body = response.body!!.string()
println(body)
val gson = GsonBuilder().create()
val itemType = object : TypeToken<List<Video>>() {}.type
val trendingList = gson.fromJson<List<Video>>(body, itemType)
runOnUiThread {
progressBar.visibility = View.GONE
recyclerView.adapter = TrendingAdapter(trendingList)
}
}
}
})*/
lifecycleScope.launchWhenCreated { lifecycleScope.launchWhenCreated {
val response = try { val response = try {
RetrofitInstance.api.getTrending("US") RetrofitInstance.api.getTrending("US")
@ -127,7 +102,7 @@ class Home : Fragment() {
run() run()
} }
fun Fragment?.runOnUiThread(action: () -> Unit) { private fun Fragment?.runOnUiThread(action: () -> Unit) {
this ?: return this ?: return
if (!isAdded) return // Fragment not attached to an Activity if (!isAdded) return // Fragment not attached to an Activity
activity?.runOnUiThread(action) activity?.runOnUiThread(action)

View File

@ -11,10 +11,13 @@ import android.view.ViewGroup
import android.widget.ArrayAdapter import android.widget.ArrayAdapter
import android.widget.AutoCompleteTextView import android.widget.AutoCompleteTextView
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import retrofit2.HttpException import retrofit2.HttpException
import xyz.btcland.libretube.adapters.SearchAdapter
import java.io.IOException import java.io.IOException
// TODO: Rename parameter arguments, choose names that match // TODO: Rename parameter arguments, choose names that match
@ -51,6 +54,8 @@ class SearchFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
val recyclerView = view.findViewById<RecyclerView>(R.id.search_recycler)
recyclerView.layoutManager = GridLayoutManager(view.context, 1)
val autoTextView = view.findViewById<AutoCompleteTextView>(R.id.autoCompleteTextView) val autoTextView = view.findViewById<AutoCompleteTextView>(R.id.autoCompleteTextView)
autoTextView.addTextChangedListener(object : TextWatcher { autoTextView.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged( override fun beforeTextChanged(
@ -64,10 +69,10 @@ class SearchFragment : Fragment() {
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
if(s!! != ""){ if(s!! != ""){
lifecycleScope.launchWhenCreated { GlobalScope.launch {
fetchSuggestions(s.toString(), autoTextView) fetchSuggestions(s.toString(), autoTextView)
delay(2000) delay(2000)
fetchSearch(s.toString()) fetchSearch(s.toString(),recyclerView)
} }
} }
} }
@ -77,10 +82,6 @@ class SearchFragment : Fragment() {
} }
}) })
} }
private fun fetchSuggestions(query: String, autoTextView: AutoCompleteTextView){ private fun fetchSuggestions(query: String, autoTextView: AutoCompleteTextView){
@ -99,7 +100,7 @@ class SearchFragment : Fragment() {
autoTextView.setAdapter(adapter) autoTextView.setAdapter(adapter)
} }
} }
private fun fetchSearch(query: String){ private fun fetchSearch(query: String, recyclerView: RecyclerView){
lifecycleScope.launchWhenCreated { lifecycleScope.launchWhenCreated {
val response = try { val response = try {
RetrofitInstance.api.getSearchResults(query, "all") RetrofitInstance.api.getSearchResults(query, "all")
@ -112,8 +113,11 @@ class SearchFragment : Fragment() {
return@launchWhenCreated return@launchWhenCreated
} }
if(response.items!!.isNotEmpty()){ if(response.items!!.isNotEmpty()){
print(response!!.items!![0]) runOnUiThread {
recyclerView.adapter = SearchAdapter(response.items)
}
} }
} }
} }
companion object { companion object {

View File

@ -0,0 +1,110 @@
package xyz.btcland.libretube.adapters
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import android.widget.VideoView
import androidx.appcompat.app.AppCompatActivity
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.recyclerview.widget.RecyclerView
import com.squareup.picasso.Picasso
import xyz.btcland.libretube.PlayerFragment
import xyz.btcland.libretube.R
import xyz.btcland.libretube.obj.SearchItem
import xyz.btcland.libretube.obj.StreamItem
import xyz.btcland.libretube.videoViews
class SearchAdapter(private val searchItems: List<SearchItem>): RecyclerView.Adapter<CustomViewHolder1>() {
override fun getItemCount(): Int {
return searchItems.size
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomViewHolder1 {
val layout = when (viewType) {
0 -> R.layout.video_search_row
1 -> R.layout.channel_search_row
2 -> R.layout.playlist_search_row
else -> throw IllegalArgumentException("Invalid type")
}
val layoutInflater = LayoutInflater.from(parent.context)
val cell = layoutInflater.inflate(layout,parent,false)
return CustomViewHolder1(cell)
}
override fun onBindViewHolder(holder: CustomViewHolder1, position: Int) {
holder.bind(searchItems[position])
}
override fun getItemViewType(position: Int): Int {
return when {
searchItems[position].url!!.startsWith("/watch",false) -> 0
searchItems[position].url!!.startsWith("/channel",false) -> 1
searchItems[position].url!!.startsWith("/playlist",false) -> 2
else -> 3
}
}
}
class CustomViewHolder1(private val v: View): RecyclerView.ViewHolder(v){
private fun bindWatch(item: SearchItem) {
val thumbnailImage = v.findViewById<ImageView>(R.id.search_thumbnail)
Picasso.get().load(item.thumbnail).into(thumbnailImage)
val channelImage = v.findViewById<ImageView>(R.id.search_channel_image)
Picasso.get().load(item.uploaderAvatar).into(channelImage)
val title = v.findViewById<TextView>(R.id.search_description)
title.text = item.title
val views = v.findViewById<TextView>(R.id.search_views)
views.text = item.views.videoViews() +""+item.uploadedDate
val channelName = v.findViewById<TextView>(R.id.search_channel_name)
channelName.text = item.uploaderName
v.setOnClickListener{
var bundle = Bundle()
bundle.putString("videoId",item.url!!.replace("/watch?v=",""))
var frag = PlayerFragment()
frag.arguments = bundle
val activity = v.context as AppCompatActivity
activity.supportFragmentManager.beginTransaction()
.remove(PlayerFragment())
.commit()
activity.supportFragmentManager.beginTransaction()
.replace(R.id.container, frag)
.commitNow()
}
}
private fun bindChannel(item: SearchItem) {
val channelImage = v.findViewById<ImageView>(R.id.search_channel_image)
Picasso.get().load(item.thumbnail).into(channelImage)
val channelName = v.findViewById<TextView>(R.id.search_channel_name)
channelName.text = item.name
val channelViews = v.findViewById<TextView>(R.id.search_views)
channelViews.text = item.subscribers.videoViews() + "subscribers • "+ item.videos + " videos"
//todo sub button
}
private fun bindPlaylist(item: SearchItem) {
val playlistImage = v.findViewById<ImageView>(R.id.search_thumbnail)
Picasso.get().load(item.thumbnail).into(playlistImage)
val playlistNumber = v.findViewById<TextView>(R.id.search_playlist_number)
playlistNumber.text = item.videos.toString()
val playlistName = v.findViewById<TextView>(R.id.search_description)
playlistName.text = item.name
val playlistChannelName = v.findViewById<TextView>(R.id.search_name)
playlistChannelName.text = item.uploaderName
val playlistVideosNumber = v.findViewById<TextView>(R.id.search_playlist_videos)
playlistVideosNumber.text = item.videos.toString()+" videos"
}
fun bind(searchItem: SearchItem) {
when {
searchItem.url!!.startsWith("/watch",false) -> bindWatch(searchItem)
searchItem.url!!.startsWith("/channel",false) -> bindChannel(searchItem)
searchItem.url!!.startsWith("/playlist",false) -> bindPlaylist(searchItem)
else -> {
}
}
}
}

View File

@ -1,4 +1,4 @@
package xyz.btcland.libretube package xyz.btcland.libretube.adapters
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
@ -9,7 +9,10 @@ import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity 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 xyz.btcland.libretube.PlayerFragment
import xyz.btcland.libretube.R
import xyz.btcland.libretube.obj.StreamItem import xyz.btcland.libretube.obj.StreamItem
import xyz.btcland.libretube.videoViews
class TrendingAdapter(private val videoFeed: List<StreamItem>): RecyclerView.Adapter<CustomViewHolder>() { class TrendingAdapter(private val videoFeed: List<StreamItem>): RecyclerView.Adapter<CustomViewHolder>() {
override fun getItemCount(): Int { override fun getItemCount(): Int {
@ -30,13 +33,11 @@ class TrendingAdapter(private val videoFeed: List<StreamItem>): RecyclerView.Ada
val channelImage = holder.v.findViewById<ImageView>(R.id.channel_image) val channelImage = holder.v.findViewById<ImageView>(R.id.channel_image)
channelImage.setOnClickListener{ channelImage.setOnClickListener{
println("channel clicked") println("channel clicked")
//TODO
} }
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{ 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() var bundle = Bundle()
bundle.putString("videoId",trending.url!!.replace("/watch?v=","")) bundle.putString("videoId",trending.url!!.replace("/watch?v=",""))
var frag = PlayerFragment() var frag = PlayerFragment()

View File

@ -2,16 +2,17 @@ package xyz.btcland.libretube.obj
data class SearchItem( data class SearchItem(
var url: String?, var url: String?,
var title: String?,
var thumbnail: String?, var thumbnail: String?,
var uploaderName: String?, var uploaderName: String?,
//Video only attributes
var title: String?,
var uploaderUrl: String?, var uploaderUrl: String?,
var uploaderAvatar: String?, var uploaderAvatar: String?,
var uploadedDate: String?, var uploadedDate: String?,
var duration: Long?, var duration: Long?,
var views: Long?, var views: Long?,
var uploaderVerified: Boolean?, var uploaderVerified: Boolean?,
//Channel and Playlist attributes //Channel and Playlist attributes
var name: String? = null, var name: String? = null,
var description: String? = null, var description: String? = null,
var subscribers: Long? = -1, var subscribers: Long? = -1,

View 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="M4,10h12v2L4,12zM4,6h12v2L4,8zM4,14h8v2L4,16zM14,14v6l5,-3z"/>
</vector>

View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:layout_marginBottom="16dp"
>
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/search_channel_image"
android:layout_width="130dp"
android:layout_height="130dp"
android:layout_marginStart="32dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/search_channel_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="24dp"
android:text="TextView"
android:textColor="#000000"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/search_channel_image"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/search_views"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="8dp"
android:text="TextView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/search_channel_image"
app:layout_constraintTop_toBottomOf="@+id/search_channel_name" />
<Button
android:id="@+id/search_sub_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:background="#00FFFFFF"
android:text="@string/subscribe"
android:textColor="#DC1212"
app:layout_constraintStart_toEndOf="@+id/search_channel_image"
app:layout_constraintTop_toBottomOf="@+id/search_views" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -10,33 +10,22 @@
android:id="@+id/autoCompleteTextView" android:id="@+id/autoCompleteTextView"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="7dp" android:layout_marginTop="7dp"
android:hint="@string/search_hint" android:hint="@string/search_hint"
android:imeOptions="actionSearch" android:imeOptions="actionSearch"
android:inputType="text" android:inputType="text"
android:maxLines="1" android:maxLines="1"
android:minHeight="48dp" android:minHeight="48dp"
app:layout_constraintEnd_toStartOf="@+id/imageView_Search" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/imageView_Search"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="7dp"
android:src="@drawable/ic_search2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/search_recycler" android:id="@+id/search_recycler"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
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"

View File

@ -0,0 +1,96 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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="8dp"
android:layout_marginBottom="16dp"
>
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent=".5"/>
<ImageView
android:id="@+id/search_thumbnail"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="16:9"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0"
app:layout_constraintEnd_toStartOf="@+id/guideline"
tools:srcCompat="@tools:sample/backgrounds/scenic" />
<RelativeLayout
android:layout_width="100dp"
android:layout_height="0dp"
android:background="#CC000000"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/guideline"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0"
>
<TextView
android:id="@+id/search_playlist_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="10"
android:textColor="#ECE4E4"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
/>
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@drawable/ic_playlist"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_below="@+id/search_playlist_number"
/>
</RelativeLayout>
<TextView
android:id="@+id/search_description"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginBottom="2dp"
android:text="TextView"
android:textColor="#000000"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/search_thumbnail"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/search_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:text="TextView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/search_thumbnail"
app:layout_constraintTop_toBottomOf="@+id/search_description" />
<TextView
android:id="@+id/search_playlist_videos"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="TextView"
android:layout_marginStart="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/guideline"
app:layout_constraintTop_toBottomOf="@+id/search_name" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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="8dp"
android:layout_marginBottom="16dp"
android:id="@+id/video_search"
>
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent=".5"/>
<ImageView
android:id="@+id/search_thumbnail"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="16:9"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0"
app:layout_constraintEnd_toStartOf="@+id/guideline"
tools:srcCompat="@tools:sample/backgrounds/scenic" />
<TextView
android:id="@+id/search_description"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:text="TextView"
android:textColor="#000000"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/search_thumbnail"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/search_views"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:text="TextView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/search_thumbnail"
app:layout_constraintTop_toBottomOf="@+id/search_description" />
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/search_channel_image"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintStart_toStartOf="@+id/guideline"
app:layout_constraintTop_toBottomOf="@+id/search_views" />
<TextView
android:id="@+id/search_channel_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:text="TextView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/search_channel_image"
app:layout_constraintTop_toBottomOf="@+id/search_views" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -4,4 +4,5 @@
<string name="hello_blank_fragment">Hello blank fragment</string> <string name="hello_blank_fragment">Hello blank fragment</string>
<string name="choose_quality_dialog">Choose Quality:</string> <string name="choose_quality_dialog">Choose Quality:</string>
<string name="search_hint">Search</string> <string name="search_hint">Search</string>
<string name="subscribe">SUBSCRIBE</string>
</resources> </resources>