1.完成推荐页预览功能以及交互

This commit is contained in:
raoqian 2025-09-23 18:24:35 +08:00
parent 848537d35b
commit a532d67a7a
14 changed files with 565 additions and 161 deletions

View File

@ -18,4 +18,15 @@
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
#-renamesourcefileattribute SourceFile
# glide 的混淆代码
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
**[] $VALUES;
public *;
}
# banner 的混淆代码
-keep class com.youth.banner.** {
*;
}

View File

@ -44,12 +44,12 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>() {
}
mViewModel.historysData_home.observe(this) {
if (it.data?.list?.get(0) != null) {
if (it?.data?.list?.get(0) != null) {
binding.llHistory.visibility = View.VISIBLE
binding.tvHisTitle.text = it.data.list[0].name
binding.tvHisEp.text =
String.format(getString(R.string.ep_), it.data.list[0].current_episode)
ImageLoadUtil.loadImage(
ImageLoadUtil.loadOvalImage(
it.data.list[0].image_url, binding.ivHistory
)
binding.ivHisPlay.tag = it.data.list[0]

View File

@ -0,0 +1,159 @@
package com.jia.er.nebuluxe.app.home
import android.content.Context
import android.view.View
import android.view.ViewGroup
import androidx.annotation.NonNull
import androidx.appcompat.widget.AppCompatTextView
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.chad.library.adapter4.BaseQuickAdapter
import com.chad.library.adapter4.viewholder.QuickViewHolder
import com.jia.er.nebuluxe.app.R
import com.jia.er.nebuluxe.app.data.RecommendDataRes
import com.jia.er.nebuluxe.app.utils.AppUtil
import com.jia.er.nebuluxe.app.utils.LOG
class ReelsBannerAdapter() : BaseQuickAdapter<RecommendDataRes.Data, QuickViewHolder>() {
interface OnPositionChangeListener {
fun onPositionChange(position: Int)
}
override fun onBindViewHolder(
holder: QuickViewHolder, position: Int, item: RecommendDataRes.Data?
) {
holder.itemView.setTag(R.id.tag_rev_id, position)
LOG.d("ReelsBannerAdapter", position.toString() + ".onBindViewHolder.24:" + (item == null))
if (item == null) {
holder.itemView.visibility = View.INVISIBLE
return
}
holder.itemView.visibility = View.VISIBLE
val tvName = holder.getView<AppCompatTextView>(R.id.tv_name)
Glide.with(holder.itemView.context).load(item?.image_url)
.placeholder(R.drawable.iv_placeholder_v).into(holder.getView(R.id.iv_icon_banner))
tvName.text = item?.name
}
override fun onCreateViewHolder(
context: Context, parent: ViewGroup, viewType: Int
): QuickViewHolder {
val view: ViewGroup =
QuickViewHolder(R.layout.custom_banner_view_reels, parent).itemView as ViewGroup
view.layoutParams = ViewGroup.LayoutParams(
(AppUtil.getScreenWidth(parent.context) - 20) / 5, ViewGroup.LayoutParams.MATCH_PARENT
)
view.addOnLayoutChangeListener { v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom ->
val name = view?.findViewById<AppCompatTextView>(R.id.tv_name)?.text as String
var focusPosition = currentSelect + 1
var position = v.getTag(R.id.tag_rev_id) as Int
LOG.d("ReelsBannerAdapter", "onCreateViewHolder.53:" + currentSelect)
LOG.d(
"ReelsBannerAdapter",
name + ".onCreateViewHolder.isSelect:" + v.getTag(R.id.tag_rev_id)
)
if (focusPosition == position) {
view.scaleX = 0.9F
view.scaleY = 0.9F
view.translationX = 0.05F * view.width
view.translationY = .1F * view.height
} else if (position - focusPosition == -1 || position - focusPosition == 1) {
view.scaleX = 0.7F
view.scaleY = 0.7F
view.translationX = 0.05F * view.width
view.translationY = .2F * view.height
} else if (position - focusPosition == -2 || position - focusPosition == 2) {
view.scaleX = 0.55F
view.scaleY = 0.55F
if (position < focusPosition) {
view.translationX = .15F * view.width
} else {
view.translationX = -.0F * view.width
}
view.translationY = .3F * view.height
} else {
view.scaleX = 0.35F
view.scaleY = 0.35F
if (position < focusPosition) {
view.translationX = .45F * view.width
} else {
view.translationX = -.25F * view.width
}
view.translationY = .4F * view.height
}
}
itemWidth = AppUtil.getScreenWidth(context) / 5
return QuickViewHolder(view)
}
var currentSelect: Int = 0
var itemWidth: Int = 0
var myRecyclerView: RecyclerView? = null
var smoothX: Int = 0
fun scrollToPosition(position: Int) {
myRecyclerView?.post {
myRecyclerView?.smoothScrollBy(itemWidth * (position + 1 - currentSelect), 0)
}
}
fun attachView(recycler: RecyclerView,other: RecyclerView) {
myRecyclerView = recycler
recycler.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(@NonNull recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
smoothX = smoothX + dx
val select: Int = (1 + (smoothX + itemWidth * 0.5f) / itemWidth).toInt()
if (currentSelect != select) {
LOG.e("SetMBTIController", "onScrolled.68:" + select)
currentSelect = select
recyclerView.setTag(R.id.tag_rev_id, currentSelect)
recycler.adapter?.notifyDataSetChanged()
}
}
override fun onScrollStateChanged(@NonNull recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
LOG.e("SetMBTIController", "onScrollStateChanged.70:" + newState)
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
listener?.onPositionChange(currentSelect - 1)
recyclerView.smoothScrollBy(
(currentSelect - 1) * itemWidth - smoothX, 0
)
other.onChildAttachedToWindow(other.getChildAt(currentSelect-1))
}
}
})
}
fun setOnPositionChangeListener(listener: OnPositionChangeListener) {
this.listener = listener
}
var listener: OnPositionChangeListener? = null
fun setData(list: List<RecommendDataRes.Data>) {
// Create a mutable list to add null items at the beginning
val newList = mutableListOf<RecommendDataRes.Data?>()
repeat(2) {
newList.add(null)
}
newList.addAll(list)
repeat(2) {
newList.add(null)
}
items = newList as List<RecommendDataRes.Data>
}
fun addData(list: List<RecommendDataRes.Data>) {
// Create a mutable list to add null items at the beginning
val newList = items?.toMutableList() ?: mutableListOf()
newList.addAll(items.size - 2, list)
items = newList as List<RecommendDataRes.Data>
}
}

View File

@ -1,6 +1,7 @@
package com.jia.er.nebuluxe.app.home
import android.annotation.SuppressLint
import android.content.Intent
import android.graphics.Color
import android.net.Uri
import android.text.SpannableStringBuilder
@ -35,15 +36,20 @@ import com.jia.er.nebuluxe.app.ui.RecyclerViewScrollerDetection
import com.blankj.utilcode.util.NetworkUtils
import com.blankj.utilcode.util.ViewUtils
import com.bumptech.glide.Glide
import com.chad.library.adapter4.util.getItemView
import com.jia.er.nebuluxe.app.R
import com.jia.er.nebuluxe.app.basics.BaseFragment
import com.jia.er.nebuluxe.app.basics.Constants
import com.jia.er.nebuluxe.app.data.CollectionRes.CollectionData
import com.jia.er.nebuluxe.app.databinding.FragmentReelsBinding
import com.jia.er.nebuluxe.app.net.MainViewModel
import com.jia.er.nebuluxe.app.utils.appendWithStyle
import com.jia.er.nebuluxe.app.utils.formatTimestamp
import com.jia.er.nebuluxe.app.utils.singleClick
import com.jia.er.nebuluxe.app.utils.toast
import com.jia.er.nebuluxe.app.utils.DialogUtils
import com.jia.er.nebuluxe.app.utils.ImageLoadUtil
import com.jia.er.nebuluxe.app.utils.LOG
import com.jia.er.nebuluxe.app.video.PlayerDetailActivity
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
@ -63,9 +69,11 @@ class ReelsFragment : BaseFragment<FragmentReelsBinding>(),
private var currentView: View? = null
private var loadingLine: LoadingLine? = null
private var tvName: AppCompatTextView? = null
private var tvEp: AppCompatTextView? = null
private var tvTime: AppCompatTextView? = null
private var play: AppCompatImageView? = null
private var collection: AppCompatImageView? = null
// private var collection: AppCompatImageView? = null
private var ivIconPlayer: AppCompatImageView? = null
private var ivCover: AppCompatImageView? = null
private var exampleSeekbarPlayerController: AppCompatSeekBar? = null
@ -76,9 +84,11 @@ class ReelsFragment : BaseFragment<FragmentReelsBinding>(),
private val currentSize = 10
private var dataRes: RecommendDataRes.Data? = null
private var currentPosition = 0
private var tvEpTotal: AppCompatTextView? = null
// private var tvEpTotal: AppCompatTextView? = null
private val mViewModel by lazy { ViewModelProvider(this)[MainViewModel::class.java] }
private var isCanPlay = false
private val bannerAdapter = ReelsBannerAdapter()
override fun top() {
activity?.window?.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
@ -92,11 +102,12 @@ class ReelsFragment : BaseFragment<FragmentReelsBinding>(),
playerView = ViewUtils.layoutId2View(R.layout.include_player_view) as PlayerView
playerView?.player = player
loadingLine = playerView?.findViewById(R.id.load_line)
tvName = playerView?.findViewById(R.id.example_tv_title_player_controller)
tvName = playerView?.findViewById(R.id.tv_name)
tvEp = playerView?.findViewById(R.id.tv_ep)
tvTime = playerView?.findViewById(R.id.tv_player_seek_time)
tvEpTotal = playerView?.findViewById(R.id.tv_ep_total)
// tvEpTotal = playerView?.findViewById(R.id.tv_ep_total)
play = playerView?.findViewById(R.id.example_iv_play_player_controller)
collection = playerView?.findViewById(R.id.example_iv_collection_controller)
// collection = playerView?.findViewById(R.id.example_iv_collection_controller)
ivIconPlayer = playerView?.findViewById(R.id.iv_icon_player)
exampleSeekbarPlayerController =
playerView?.findViewById(R.id.example_seekBar_player_controller)
@ -112,6 +123,7 @@ class ReelsFragment : BaseFragment<FragmentReelsBinding>(),
player?.addListener(object : Player.Listener {
override fun onPlaybackStateChanged(playbackState: Int) {
super.onPlaybackStateChanged(playbackState)
LOG.d("ReelsFragment", "onPlaybackStateChanged.121:" + playbackState)
when (playbackState) {
Player.STATE_BUFFERING -> {
if (!isHidden) {
@ -142,30 +154,34 @@ class ReelsFragment : BaseFragment<FragmentReelsBinding>(),
}
})
collection?.setOnClickListener {
singleClick {
if (dataRes?.is_collect == true) {
dataRes?.video_info?.short_play_id?.let { it1 ->
dataRes?.video_info?.short_play_video_id?.let { it2 ->
DialogUtils.unFavoriteDialog(
requireContext(),
it1, it2, mViewModel
)
}
}
} else {
dataRes?.video_info?.short_play_id?.let {
dataRes?.video_info?.short_play_video_id.let { it1 ->
if (it1 != null) {
mViewModel.doCollect(
it, it1
)
}
}
}
binding.banner.apply {
setAdapter(bannerAdapter)
layoutManager = LinearLayoutManager(
context, LinearLayoutManager.HORIZONTAL, false
)
}
bannerAdapter.attachView(binding.banner, binding.rvRecommend)
bannerAdapter.setOnPositionChangeListener(object :
ReelsBannerAdapter.OnPositionChangeListener {
override fun onPositionChange(position: Int) {
// binding.rvRecommend.smoothScrollToPosition(position)
binding.rvRecommend.scrollToPosition(position)
binding.rvRecommend.postDelayed({
setActive(
binding.rvRecommend.layoutManager?.findViewByPosition(
position
), position, null, -1
)
}, 300)
if (position >= (homeForYouAdapter?.itemCount ?: 0) - 2) {
loadMore()
}
}
}
})
bannerAdapter.addOnItemChildClickListener(R.id.iv_icon_banner, { adapter, view, position ->
val item = adapter.getItem(position) as RecommendDataRes.Data
openVideo(item.video_info?.short_play_id)
})
binding.srFy.apply {
setOnRefreshListener {
recyclerViewScrollerDetection.isFirstAttached = false
@ -185,18 +201,10 @@ class ReelsFragment : BaseFragment<FragmentReelsBinding>(),
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
val layoutManager = recyclerView.layoutManager as LinearLayoutManager
val lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition()
val totalItemCount = layoutManager.itemCount
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
if (isSlidingUp &&
lastVisibleItemPosition == totalItemCount - 1
) {
currentPage++
mViewModel.getRecommands(currentPage, currentSize, "")
}
bannerAdapter.scrollToPosition(lastVisibleItemPosition)
}
}
})
@ -230,6 +238,28 @@ class ReelsFragment : BaseFragment<FragmentReelsBinding>(),
}
}
fun openVideo(videoId: Int?) {
if (videoId == null) {
LOG.d("HomeFragment", "openVideo.videoId.is.empty:" + LOG.useInfo())
return
}
startActivity(
Intent(
context, PlayerDetailActivity::class.java
).apply {
putExtra(
Constants.CONSTANTS_short_play_id, videoId
)
})
}
private fun loadMore() {
singleClick {
mViewModel.getRecommands(++currentPage, currentSize, "")
LOG.d("ReelsFragment", "loadMore.259:" + currentPage)
}
}
private fun setProgress() {
exampleProgressJob?.cancel()
val duration = player!!.duration
@ -279,17 +309,18 @@ class ReelsFragment : BaseFragment<FragmentReelsBinding>(),
mViewModel.recommendData.observe(this) {
if (it != null) {
if (it.data?.list?.isNotEmpty() == true) {
LOG.bean("ReelsFragment.289", it.data.list)
if (currentPage == 1) {
homeForYouAdapter = HomeForYouAdapter()
val layoutManager =
LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
binding?.rvRecommend?.layoutManager = layoutManager
binding?.rvRecommend?.adapter = homeForYouAdapter
binding?.rvRecommend?.isNestedScrollingEnabled = false
binding.rvRecommend.layoutManager = layoutManager
binding.rvRecommend.adapter = homeForYouAdapter
binding.rvRecommend.isNestedScrollingEnabled = false
pagerSnapHelper.attachToRecyclerView(binding?.rvRecommend)
recyclerViewScrollerDetection.setCurrentListener(this)
recyclerViewScrollerDetection.attachToSnapHelper(pagerSnapHelper)
binding?.rvRecommend?.let { it1 ->
binding.rvRecommend.let { it1 ->
recyclerViewScrollerDetection.addOnScrollListener(
it1
)
@ -297,10 +328,13 @@ class ReelsFragment : BaseFragment<FragmentReelsBinding>(),
it.data?.list?.forEach { item ->
Glide.with(requireContext()).load(item.image_url).preload()
}
bannerAdapter.setData(it.data.list)
homeForYouAdapter?.submitList(it.data.list)
} else {
homeForYouAdapter?.addAll(it.data.list)
bannerAdapter.addData(it.data.list)
}
bannerAdapter.notifyDataSetChanged()
hideLoading()
} else {
toast(getString(R.string.no_more_data))
@ -313,30 +347,30 @@ class ReelsFragment : BaseFragment<FragmentReelsBinding>(),
binding.srFy.finishRefresh()
}
mViewModel.collectData.observe(this) {
if (it != null) {
collection?.setImageResource(R.drawable.iv_example_collection_h)
dataRes?.collect_total = dataRes?.collect_total?.plus(1)
homeForYouAdapter?.getItem(currentPosition)?.is_collect = true
homeForYouAdapter?.getItem(currentPosition)?.collect_total =
dataRes?.collect_total
toast(getString(R.string.success))
} else {
toast(R.string.network_error)
}
}
mViewModel.cancelCollectData.observe(this) {
if (it != null) {
collection?.setImageResource(R.drawable.iv_example_collection_n)
dataRes?.collect_total = dataRes?.collect_total?.minus(1)
homeForYouAdapter?.getItem(currentPosition)?.is_collect = false
homeForYouAdapter?.getItem(currentPosition)?.collect_total =
dataRes?.collect_total
toast(getString(R.string.success))
} else {
toast(R.string.network_error)
}
}
// mViewModel.collectData.observe(this) {
// if (it != null) {
// collection?.setImageResource(R.drawable.iv_example_collection_h)
// dataRes?.collect_total = dataRes?.collect_total?.plus(1)
// homeForYouAdapter?.getItem(currentPosition)?.is_collect = true
// homeForYouAdapter?.getItem(currentPosition)?.collect_total =
// dataRes?.collect_total
// toast(getString(R.string.success))
// } else {
// toast(R.string.network_error)
// }
// }
// mViewModel.cancelCollectData.observe(this) {
// if (it != null) {
// collection?.setImageResource(R.drawable.iv_example_collection_n)
// dataRes?.collect_total = dataRes?.collect_total?.minus(1)
// homeForYouAdapter?.getItem(currentPosition)?.is_collect = false
// homeForYouAdapter?.getItem(currentPosition)?.collect_total =
// dataRes?.collect_total
// toast(getString(R.string.success))
// } else {
// toast(R.string.network_error)
// }
// }
}
private fun buildMediaSource(videoPath: String): MediaSource {
@ -375,6 +409,7 @@ class ReelsFragment : BaseFragment<FragmentReelsBinding>(),
override fun setActive(
currentView: View?, position: Int, previousView: View?, previousPosition: Int
) {
LOG.d("ReelsFragment", "setActive.381:" + position)
isCanPlay = true
currentPosition = position
this.currentView = currentView
@ -395,7 +430,12 @@ class ReelsFragment : BaseFragment<FragmentReelsBinding>(),
Glide.with(this).load(dataRes?.image_url).into(it1)
}
tvName?.text = dataRes?.name
// TODO: tvEp?.text="剧类别,接口未返回"
val builder = SpannableStringBuilder()
ImageLoadUtil.loadOvalImage(
dataRes?.image_url,
playerView?.findViewById(R.id.iv)
)
builder.appendWithStyle(
"Ep.".plus(dataRes?.video_info?.episode),
Color.parseColor("#50FFFFFF"),
@ -406,12 +446,13 @@ class ReelsFragment : BaseFragment<FragmentReelsBinding>(),
Color.parseColor("#50FFFFFF"),
isBold = false
)
tvEpTotal?.text = builder
collection?.setImageResource(if (dataRes?.is_collect == true) R.drawable.iv_example_collection_h else R.drawable.iv_example_collection_n)
// tvEpTotal?.text = builder
// collection?.setImageResource(if (dataRes?.is_collect == true) R.drawable.iv_example_collection_h else R.drawable.iv_example_collection_n)
}
override fun disActive(detachedView: View?, detachedPosition: Int) {
if (null == detachedView) return
LOG.d("ReelsFragment", "disActive.424:" + detachedPosition)
ivCover = detachedView.findViewById(R.id.iv_icon)
ivCover?.visibility = View.VISIBLE
if (player?.isPlaying == true) {

View File

@ -0,0 +1,72 @@
package com.jia.er.nebuluxe.app.ui
import android.view.View
import androidx.viewpager2.widget.ViewPager2
import com.jia.er.nebuluxe.app.utils.LOG
class ReelsRotatePageTransformer(
private val maxRotate: Float = DEFAULT_MAX_ROTATE,
private val sideMargin: Float = 0f, // Positive value creates visible gap
private val scaleFactor: Float = 0.95f
) : ViewPager2.PageTransformer {
companion object {
private const val DEFAULT_MAX_ROTATE = 15.0f
private const val DEFAULT_CENTER = 0.5f
}
override fun transformPage(view: View, position: Float) {
val scale = if (abs(position) <= 1) {
(1 - abs(position)) * (1 - scaleFactor) + scaleFactor
} else {
scaleFactor
}
when {
position < -2 -> {
// [-Infinity,-2)
view.rotation = maxRotate * -1
view.pivotX = view.width.toFloat()
view.pivotY = view.height.toFloat()
view.scaleX = scaleFactor
view.scaleY = scaleFactor
view.translationX = -sideMargin * 2
}
position <= 2 -> { // [-2,2]
// Calculate direction (left or right)
val direction = if (position < 0) -1f else 1f
view.pivotX = if (position < 0) {
view.width * (DEFAULT_CENTER + DEFAULT_CENTER * -position)
} else {
view.width * DEFAULT_CENTER * (1 - position)
}
// Removed invalid line: view.width= view.width /5
LOG.d("ReelsRotatePageTransformer", "transformPage." + position + ":" + view.width)
view.pivotY = view.height.toFloat()
view.rotation = maxRotate * position
view.scaleX = .25F
view.scaleY = 1F
view.translationX = (sideMargin * position) + (sideMargin * direction)
}
else -> {
// (2,+Infinity]
view.rotation = maxRotate
view.pivotX = 0f
view.pivotY = view.height.toFloat()
view.scaleX = scaleFactor
view.scaleY = scaleFactor
view.translationX = sideMargin * 2
}
}
}
private fun abs(value: Float): Float {
return if (value < 0) -value else value
}
}

View File

@ -3,6 +3,8 @@ package com.jia.er.nebuluxe.app.utils
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.util.DisplayMetrics
import android.view.WindowManager
import android.view.inputmethod.InputMethodManager
import android.view.inputmethod.InputMethodManager.HIDE_IMPLICIT_ONLY
import android.widget.EditText
@ -24,22 +26,35 @@ object AppUtil {
if (context is Activity) {
val activity = context
LOG.e("AppUtils", "hideInput:activity-> " + activity)
if (activity.getWindow().getCurrentFocus() != null) {
if (activity.getWindow().getCurrentFocus() is EditText) {
hideInput((activity.getWindow().getCurrentFocus() as EditText?)!!)
if (activity.window.currentFocus != null) {
if (activity.window.currentFocus is EditText) {
hideInput((activity.window.currentFocus as EditText?)!!)
} else {
LOG.e("AppUtils", "hideInput:View-> " + activity.getWindow().getCurrentFocus())
val inputManager = activity.getWindow().getContext()
LOG.e("AppUtils", "hideInput:View-> " + activity.window.currentFocus)
val inputManager = activity.window.context
.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
inputManager.hideSoftInputFromWindow(
activity.getWindow().getCurrentFocus()!!
.getWindowToken(), HIDE_IMPLICIT_ONLY
activity.window.currentFocus!!
.windowToken, HIDE_IMPLICIT_ONLY
)
}
}
}
}
fun getScreenWidth(context: Context): Int {
val dm = DisplayMetrics()
val windowManager = context
.getSystemService(Context.WINDOW_SERVICE) as WindowManager
windowManager.getDefaultDisplay().getMetrics(dm)
// screenWidth = dm.widthPixels;
// screenHeight = dm.heightPixels;
return dm.widthPixels
}
fun showInput(editText: EditText) {
val imm = MyApplication.context
.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager?

View File

@ -2,6 +2,7 @@ package com.jia.er.nebuluxe.app.utils
import android.widget.ImageView
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.CircleCrop
import com.jia.er.nebuluxe.app.R
object ImageLoadUtil {
@ -15,4 +16,16 @@ object ImageLoadUtil {
.placeholder(if (isHor) R.drawable.ic_default_iv_hor else R.drawable.ic_default_iv_ver)
.into(iv)
}
fun loadOvalImage(url: String?, iv: ImageView?) {
if (url == null || iv == null) {
LOG.d("ImageLoadUtil.20", "图片填充错误:" + LOG.useInfo())
return
}
val isHor = iv.width > iv.height
Glide.with(iv.context).load(url)
.transform(CircleCrop())
.placeholder(if (isHor) R.drawable.ic_default_iv_hor else R.drawable.ic_default_iv_ver)
.into(iv)
}
}

View File

@ -35,11 +35,12 @@ class SeriesDataAdapter :
// context.getColor(R.color.white)
// )
// }
if (item?.is_lock == true && !Memory.isVip()) {
holder.setVisible(R.id.iv_example_lock, true)
} else {
holder.setVisible(R.id.iv_example_lock, false)
}
// todo 解锁功能暂时隐藏
// if (item?.is_lock == true && !Memory.isVip()) {
// holder.setVisible(R.id.iv_example_lock, true)
// } else {
// holder.setVisible(R.id.iv_example_lock, false)
// }
}
override fun onCreateViewHolder(

View File

@ -0,0 +1,63 @@
<?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"
tools:background="#000">
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/iv_icon_banner"
android:layout_width="match_parent"
android:layout_height="@dimen/padding_90px"
android:scaleType="centerCrop"
android:src="@drawable/ic_default_iv_ver"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:shapeAppearance="@style/CircleCornerStyle" />
<!-- <com.google.android.material.card.MaterialCardView-->
<!-- android:id="@+id/example_cardView"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="@dimen/padding_90px"-->
<!-- android:layout_marginTop="@dimen/padding_20px"-->
<!-- android:layout_marginBottom="@dimen/padding_20px"-->
<!-- app:cardCornerRadius="@dimen/padding_10px"-->
<!-- app:cardElevation="@dimen/padding_0px"-->
<!-- app:layout_constraintTop_toTopOf="parent">-->
<!-- <RelativeLayout-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="match_parent">-->
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ellipsize="end"
android:gravity="center"
android:maxLines="1"
android:textColor="#FFFFFF"
android:textSize="@dimen/text_size_12px"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="fracture and rebirth after fulfillmen" />
<!-- <androidx.appcompat.widget.AppCompatTextView-->
<!-- android:id="@+id/tv_tag"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_below="@id/tv_name"-->
<!-- android:layout_marginHorizontal="@dimen/padding_11px"-->
<!-- android:textColor="#F0C2E1"-->
<!-- android:textSize="@dimen/text_size_10px"-->
<!-- tools:text="Revenge" />-->
<!-- </RelativeLayout>-->
<!-- </com.google.android.material.card.MaterialCardView>-->
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -326,6 +326,7 @@
android:layout_height="@dimen/padding_50px"
android:layout_marginLeft="@dimen/padding_20px"
android:layout_marginRight="@dimen/padding_20px"
android:layout_marginBottom="@dimen/padding_35px"
android:background="@drawable/bg_conner_50px_black_history"
android:gravity="center"
android:orientation="horizontal"
@ -344,10 +345,12 @@
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_his_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:maxLines="1"
android:paddingLeft="@dimen/padding_10px"
android:textColor="@color/text_color_white"
android:textSize="@dimen/text_size_14px"

View File

@ -11,11 +11,20 @@
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_recommend"
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent" />
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_recommend"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/banner"
android:layout_width="match_parent"
android:layout_height="@dimen/padding_140px"
android:layout_gravity="bottom"
android:layout_marginBottom="@dimen/padding_30px" />
</FrameLayout>
</com.scwang.smart.refresh.layout.SmartRefreshLayout>

View File

@ -12,25 +12,12 @@
android:layout_height="match_parent"
android:scaleType="centerCrop" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/example_tv_title_player_controller"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/padding_16px"
android:layout_marginTop="@dimen/padding_55px"
android:lineSpacingExtra="@dimen/padding_1px"
android:lineSpacingMultiplier="1.1"
android:text="Love Adventure Under Contract"
android:textColor="#FFDAA4"
android:textSize="@dimen/text_size_18px"
android:textStyle="bold" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_player_seek_time"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@id/example_ll_bottom_controller"
android:layout_below="@id/example_ll_bottom_controller"
android:layout_marginBottom="@dimen/padding_10px"
android:gravity="center_horizontal"
android:textColor="@color/white"
@ -38,17 +25,22 @@
android:visibility="invisible"
tools:text="00:00/02:24" />
<androidx.appcompat.widget.LinearLayoutCompat
<FrameLayout
android:id="@+id/example_ll_bottom_controller"
android:layout_width="match_parent"
android:layout_height="@dimen/padding_20px"
android:layout_alignParentBottom="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="@dimen/padding_19px"
android:layout_marginTop="@dimen/padding_49px"
android:layout_marginRight="@dimen/padding_19px"
android:layout_marginBottom="@dimen/padding_19px"
android:gravity="center"
android:orientation="vertical">
<com.jia.er.nebuluxe.app.ui.LoadingLine
android:id="@+id/load_line"
android:layout_width="match_parent"
android:layout_height="@dimen/padding_2px" />
<androidx.appcompat.widget.AppCompatSeekBar
android:id="@+id/example_seekBar_player_controller"
android:layout_width="match_parent"
@ -60,16 +52,59 @@
android:splitTrack="false"
android:thumb="@drawable/progress_thumb"
android:thumbOffset="@dimen/padding_8px" />
</androidx.appcompat.widget.LinearLayoutCompat>
</FrameLayout>
<com.jia.er.nebuluxe.app.ui.LoadingLine
android:id="@+id/load_line"
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/ll_history"
android:layout_width="match_parent"
android:layout_height="@dimen/padding_2px"
android:layout_alignParentBottom="true"
android:layout_marginLeft="@dimen/padding_19px"
android:layout_marginRight="@dimen/padding_19px"
android:layout_marginBottom="@dimen/padding_28px" />
android:layout_height="@dimen/padding_50px"
android:layout_below="@id/example_ll_bottom_controller"
android:layout_marginLeft="@dimen/padding_20px"
android:layout_marginRight="@dimen/padding_20px"
android:layout_marginTop="@dimen/padding_35px"
android:gravity="center"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
tools:visibility="visible">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv"
android:layout_width="@dimen/padding_50px"
android:layout_height="@dimen/padding_50px"
android:layout_marginRight="@dimen/padding_25px"
android:src="@drawable/iv_avatar"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:maxLines="1"
android:paddingLeft="@dimen/padding_10px"
android:textColor="@color/text_color_white"
android:textSize="@dimen/text_size_14px"
app:layout_constraintBottom_toTopOf="@id/tv_ep"
app:layout_constraintLeft_toRightOf="@id/iv"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="fake marriage true love" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_ep"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:paddingLeft="@dimen/padding_10px"
android:textColor="@color/text_color_gray_DF"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@id/iv"
app:layout_constraintTop_toBottomOf="@id/tv_name"
tools:text="fake marriage true love" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/example_iv_play_player_controller"
@ -81,58 +116,31 @@
android:padding="@dimen/padding_15px"
android:src="@drawable/iv_example_stop" />
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/cl"
android:layout_alignParentEnd="true"
android:layout_marginRight="@dimen/padding_16px"
android:layout_marginBottom="@dimen/padding_26px"
android:gravity="center"
android:orientation="vertical">
<!-- <androidx.appcompat.widget.LinearLayoutCompat-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_alignParentEnd="true"-->
<!-- android:layout_marginRight="@dimen/padding_16px"-->
<!-- android:layout_marginBottom="@dimen/padding_26px"-->
<!-- android:gravity="center"-->
<!-- android:orientation="vertical">-->
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/example_iv_collection_controller"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/iv_example_collection_n" />
<!-- <androidx.appcompat.widget.AppCompatImageView-->
<!-- android:id="@+id/example_iv_collection_controller"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:src="@drawable/iv_example_collection_n" />-->
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/example_tv_collection_num_controller"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="111"
android:textColor="#FFDAA4"
android:textSize="@dimen/text_size_12px"
android:textStyle="bold" />
<!-- <androidx.appcompat.widget.AppCompatTextView-->
<!-- android:id="@+id/example_tv_collection_num_controller"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:gravity="center"-->
<!-- android:text="111"-->
<!-- android:textColor="#FFDAA4"-->
<!-- android:textSize="@dimen/text_size_12px"-->
<!-- android:textStyle="bold" />-->
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl"
android:layout_width="match_parent"
android:layout_height="@dimen/padding_36px"
android:layout_above="@id/example_ll_bottom_controller"
android:layout_marginLeft="@dimen/padding_16px"
android:layout_marginRight="@dimen/padding_16px"
android:layout_marginBottom="@dimen/padding_6px">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_ep_total"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/padding_12px"
android:layout_marginRight="@dimen/padding_12px"
android:drawablePadding="@dimen/padding_5px"
android:gravity="left"
android:text="EP.1 / EP.51"
android:textColor="#FFE17D"
android:textSize="@dimen/text_size_14px"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<!-- </androidx.appcompat.widget.LinearLayoutCompat>-->
</RelativeLayout>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="tag_rev_id" type="id"/>
</resources>

View File

@ -16,6 +16,11 @@
<item name="cornerSize">@dimen/padding_10px</item>
</style>
<style name="Circle60pxCornerStyle">
<item name="cornerFamily">rounded</item>
<item name="cornerSize">@dimen/padding_60px</item>
</style>
<style name="HorizontalLine">
<item name="android:background">@color/text_color_white</item>
<item name="android:layout_height">1px</item>