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 # If you keep the line number information, uncomment this to
# hide the original source file name. # 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) { 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.llHistory.visibility = View.VISIBLE
binding.tvHisTitle.text = it.data.list[0].name binding.tvHisTitle.text = it.data.list[0].name
binding.tvHisEp.text = binding.tvHisEp.text =
String.format(getString(R.string.ep_), it.data.list[0].current_episode) String.format(getString(R.string.ep_), it.data.list[0].current_episode)
ImageLoadUtil.loadImage( ImageLoadUtil.loadOvalImage(
it.data.list[0].image_url, binding.ivHistory it.data.list[0].image_url, binding.ivHistory
) )
binding.ivHisPlay.tag = it.data.list[0] 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 package com.jia.er.nebuluxe.app.home
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Intent
import android.graphics.Color import android.graphics.Color
import android.net.Uri import android.net.Uri
import android.text.SpannableStringBuilder 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.NetworkUtils
import com.blankj.utilcode.util.ViewUtils import com.blankj.utilcode.util.ViewUtils
import com.bumptech.glide.Glide 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.R
import com.jia.er.nebuluxe.app.basics.BaseFragment 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.databinding.FragmentReelsBinding
import com.jia.er.nebuluxe.app.net.MainViewModel import com.jia.er.nebuluxe.app.net.MainViewModel
import com.jia.er.nebuluxe.app.utils.appendWithStyle import com.jia.er.nebuluxe.app.utils.appendWithStyle
import com.jia.er.nebuluxe.app.utils.formatTimestamp import com.jia.er.nebuluxe.app.utils.formatTimestamp
import com.jia.er.nebuluxe.app.utils.singleClick import com.jia.er.nebuluxe.app.utils.singleClick
import com.jia.er.nebuluxe.app.utils.toast 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.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
@ -63,9 +69,11 @@ class ReelsFragment : BaseFragment<FragmentReelsBinding>(),
private var currentView: View? = null private var currentView: View? = null
private var loadingLine: LoadingLine? = null private var loadingLine: LoadingLine? = null
private var tvName: AppCompatTextView? = null private var tvName: AppCompatTextView? = null
private var tvEp: AppCompatTextView? = null
private var tvTime: AppCompatTextView? = null private var tvTime: AppCompatTextView? = null
private var play: AppCompatImageView? = null private var play: AppCompatImageView? = null
private var collection: AppCompatImageView? = null
// private var collection: AppCompatImageView? = null
private var ivIconPlayer: AppCompatImageView? = null private var ivIconPlayer: AppCompatImageView? = null
private var ivCover: AppCompatImageView? = null private var ivCover: AppCompatImageView? = null
private var exampleSeekbarPlayerController: AppCompatSeekBar? = null private var exampleSeekbarPlayerController: AppCompatSeekBar? = null
@ -76,9 +84,11 @@ class ReelsFragment : BaseFragment<FragmentReelsBinding>(),
private val currentSize = 10 private val currentSize = 10
private var dataRes: RecommendDataRes.Data? = null private var dataRes: RecommendDataRes.Data? = null
private var currentPosition = 0 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 val mViewModel by lazy { ViewModelProvider(this)[MainViewModel::class.java] }
private var isCanPlay = false private var isCanPlay = false
private val bannerAdapter = ReelsBannerAdapter()
override fun top() { override fun top() {
activity?.window?.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) 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 = ViewUtils.layoutId2View(R.layout.include_player_view) as PlayerView
playerView?.player = player playerView?.player = player
loadingLine = playerView?.findViewById(R.id.load_line) 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) 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) 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) ivIconPlayer = playerView?.findViewById(R.id.iv_icon_player)
exampleSeekbarPlayerController = exampleSeekbarPlayerController =
playerView?.findViewById(R.id.example_seekBar_player_controller) playerView?.findViewById(R.id.example_seekBar_player_controller)
@ -112,6 +123,7 @@ class ReelsFragment : BaseFragment<FragmentReelsBinding>(),
player?.addListener(object : Player.Listener { player?.addListener(object : Player.Listener {
override fun onPlaybackStateChanged(playbackState: Int) { override fun onPlaybackStateChanged(playbackState: Int) {
super.onPlaybackStateChanged(playbackState) super.onPlaybackStateChanged(playbackState)
LOG.d("ReelsFragment", "onPlaybackStateChanged.121:" + playbackState)
when (playbackState) { when (playbackState) {
Player.STATE_BUFFERING -> { Player.STATE_BUFFERING -> {
if (!isHidden) { if (!isHidden) {
@ -142,30 +154,34 @@ class ReelsFragment : BaseFragment<FragmentReelsBinding>(),
} }
}) })
collection?.setOnClickListener { binding.banner.apply {
singleClick { setAdapter(bannerAdapter)
if (dataRes?.is_collect == true) { layoutManager = LinearLayoutManager(
dataRes?.video_info?.short_play_id?.let { it1 -> context, LinearLayoutManager.HORIZONTAL, false
dataRes?.video_info?.short_play_video_id?.let { it2 -> )
DialogUtils.unFavoriteDialog( }
requireContext(), bannerAdapter.attachView(binding.banner, binding.rvRecommend)
it1, it2, mViewModel bannerAdapter.setOnPositionChangeListener(object :
) ReelsBannerAdapter.OnPositionChangeListener {
} override fun onPositionChange(position: Int) {
} // binding.rvRecommend.smoothScrollToPosition(position)
} else { binding.rvRecommend.scrollToPosition(position)
dataRes?.video_info?.short_play_id?.let { binding.rvRecommend.postDelayed({
dataRes?.video_info?.short_play_video_id.let { it1 -> setActive(
if (it1 != null) { binding.rvRecommend.layoutManager?.findViewByPosition(
mViewModel.doCollect( position
it, it1 ), 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 { binding.srFy.apply {
setOnRefreshListener { setOnRefreshListener {
recyclerViewScrollerDetection.isFirstAttached = false recyclerViewScrollerDetection.isFirstAttached = false
@ -185,18 +201,10 @@ class ReelsFragment : BaseFragment<FragmentReelsBinding>(),
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState) super.onScrollStateChanged(recyclerView, newState)
val layoutManager = recyclerView.layoutManager as LinearLayoutManager val layoutManager = recyclerView.layoutManager as LinearLayoutManager
val lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition() val lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition()
val totalItemCount = layoutManager.itemCount
if (newState == RecyclerView.SCROLL_STATE_IDLE) { if (newState == RecyclerView.SCROLL_STATE_IDLE) {
if (isSlidingUp && bannerAdapter.scrollToPosition(lastVisibleItemPosition)
lastVisibleItemPosition == totalItemCount - 1
) {
currentPage++
mViewModel.getRecommands(currentPage, currentSize, "")
}
} }
} }
}) })
@ -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() { private fun setProgress() {
exampleProgressJob?.cancel() exampleProgressJob?.cancel()
val duration = player!!.duration val duration = player!!.duration
@ -279,17 +309,18 @@ class ReelsFragment : BaseFragment<FragmentReelsBinding>(),
mViewModel.recommendData.observe(this) { mViewModel.recommendData.observe(this) {
if (it != null) { if (it != null) {
if (it.data?.list?.isNotEmpty() == true) { if (it.data?.list?.isNotEmpty() == true) {
LOG.bean("ReelsFragment.289", it.data.list)
if (currentPage == 1) { if (currentPage == 1) {
homeForYouAdapter = HomeForYouAdapter() homeForYouAdapter = HomeForYouAdapter()
val layoutManager = val layoutManager =
LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
binding?.rvRecommend?.layoutManager = layoutManager binding.rvRecommend.layoutManager = layoutManager
binding?.rvRecommend?.adapter = homeForYouAdapter binding.rvRecommend.adapter = homeForYouAdapter
binding?.rvRecommend?.isNestedScrollingEnabled = false binding.rvRecommend.isNestedScrollingEnabled = false
pagerSnapHelper.attachToRecyclerView(binding?.rvRecommend) pagerSnapHelper.attachToRecyclerView(binding?.rvRecommend)
recyclerViewScrollerDetection.setCurrentListener(this) recyclerViewScrollerDetection.setCurrentListener(this)
recyclerViewScrollerDetection.attachToSnapHelper(pagerSnapHelper) recyclerViewScrollerDetection.attachToSnapHelper(pagerSnapHelper)
binding?.rvRecommend?.let { it1 -> binding.rvRecommend.let { it1 ->
recyclerViewScrollerDetection.addOnScrollListener( recyclerViewScrollerDetection.addOnScrollListener(
it1 it1
) )
@ -297,10 +328,13 @@ class ReelsFragment : BaseFragment<FragmentReelsBinding>(),
it.data?.list?.forEach { item -> it.data?.list?.forEach { item ->
Glide.with(requireContext()).load(item.image_url).preload() Glide.with(requireContext()).load(item.image_url).preload()
} }
bannerAdapter.setData(it.data.list)
homeForYouAdapter?.submitList(it.data.list) homeForYouAdapter?.submitList(it.data.list)
} else { } else {
homeForYouAdapter?.addAll(it.data.list) homeForYouAdapter?.addAll(it.data.list)
bannerAdapter.addData(it.data.list)
} }
bannerAdapter.notifyDataSetChanged()
hideLoading() hideLoading()
} else { } else {
toast(getString(R.string.no_more_data)) toast(getString(R.string.no_more_data))
@ -313,30 +347,30 @@ class ReelsFragment : BaseFragment<FragmentReelsBinding>(),
binding.srFy.finishRefresh() binding.srFy.finishRefresh()
} }
mViewModel.collectData.observe(this) { // mViewModel.collectData.observe(this) {
if (it != null) { // if (it != null) {
collection?.setImageResource(R.drawable.iv_example_collection_h) // collection?.setImageResource(R.drawable.iv_example_collection_h)
dataRes?.collect_total = dataRes?.collect_total?.plus(1) // dataRes?.collect_total = dataRes?.collect_total?.plus(1)
homeForYouAdapter?.getItem(currentPosition)?.is_collect = true // homeForYouAdapter?.getItem(currentPosition)?.is_collect = true
homeForYouAdapter?.getItem(currentPosition)?.collect_total = // homeForYouAdapter?.getItem(currentPosition)?.collect_total =
dataRes?.collect_total // dataRes?.collect_total
toast(getString(R.string.success)) // toast(getString(R.string.success))
} else { // } else {
toast(R.string.network_error) // toast(R.string.network_error)
} // }
} // }
mViewModel.cancelCollectData.observe(this) { // mViewModel.cancelCollectData.observe(this) {
if (it != null) { // if (it != null) {
collection?.setImageResource(R.drawable.iv_example_collection_n) // collection?.setImageResource(R.drawable.iv_example_collection_n)
dataRes?.collect_total = dataRes?.collect_total?.minus(1) // dataRes?.collect_total = dataRes?.collect_total?.minus(1)
homeForYouAdapter?.getItem(currentPosition)?.is_collect = false // homeForYouAdapter?.getItem(currentPosition)?.is_collect = false
homeForYouAdapter?.getItem(currentPosition)?.collect_total = // homeForYouAdapter?.getItem(currentPosition)?.collect_total =
dataRes?.collect_total // dataRes?.collect_total
toast(getString(R.string.success)) // toast(getString(R.string.success))
} else { // } else {
toast(R.string.network_error) // toast(R.string.network_error)
} // }
} // }
} }
private fun buildMediaSource(videoPath: String): MediaSource { private fun buildMediaSource(videoPath: String): MediaSource {
@ -375,6 +409,7 @@ class ReelsFragment : BaseFragment<FragmentReelsBinding>(),
override fun setActive( override fun setActive(
currentView: View?, position: Int, previousView: View?, previousPosition: Int currentView: View?, position: Int, previousView: View?, previousPosition: Int
) { ) {
LOG.d("ReelsFragment", "setActive.381:" + position)
isCanPlay = true isCanPlay = true
currentPosition = position currentPosition = position
this.currentView = currentView this.currentView = currentView
@ -395,7 +430,12 @@ class ReelsFragment : BaseFragment<FragmentReelsBinding>(),
Glide.with(this).load(dataRes?.image_url).into(it1) Glide.with(this).load(dataRes?.image_url).into(it1)
} }
tvName?.text = dataRes?.name tvName?.text = dataRes?.name
// TODO: tvEp?.text="剧类别,接口未返回"
val builder = SpannableStringBuilder() val builder = SpannableStringBuilder()
ImageLoadUtil.loadOvalImage(
dataRes?.image_url,
playerView?.findViewById(R.id.iv)
)
builder.appendWithStyle( builder.appendWithStyle(
"Ep.".plus(dataRes?.video_info?.episode), "Ep.".plus(dataRes?.video_info?.episode),
Color.parseColor("#50FFFFFF"), Color.parseColor("#50FFFFFF"),
@ -406,12 +446,13 @@ class ReelsFragment : BaseFragment<FragmentReelsBinding>(),
Color.parseColor("#50FFFFFF"), Color.parseColor("#50FFFFFF"),
isBold = false isBold = false
) )
tvEpTotal?.text = builder // tvEpTotal?.text = builder
collection?.setImageResource(if (dataRes?.is_collect == true) R.drawable.iv_example_collection_h else R.drawable.iv_example_collection_n) // 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) { override fun disActive(detachedView: View?, detachedPosition: Int) {
if (null == detachedView) return if (null == detachedView) return
LOG.d("ReelsFragment", "disActive.424:" + detachedPosition)
ivCover = detachedView.findViewById(R.id.iv_icon) ivCover = detachedView.findViewById(R.id.iv_icon)
ivCover?.visibility = View.VISIBLE ivCover?.visibility = View.VISIBLE
if (player?.isPlaying == true) { 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.app.Activity
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.util.DisplayMetrics
import android.view.WindowManager
import android.view.inputmethod.InputMethodManager import android.view.inputmethod.InputMethodManager
import android.view.inputmethod.InputMethodManager.HIDE_IMPLICIT_ONLY import android.view.inputmethod.InputMethodManager.HIDE_IMPLICIT_ONLY
import android.widget.EditText import android.widget.EditText
@ -24,22 +26,35 @@ object AppUtil {
if (context is Activity) { if (context is Activity) {
val activity = context val activity = context
LOG.e("AppUtils", "hideInput:activity-> " + activity) LOG.e("AppUtils", "hideInput:activity-> " + activity)
if (activity.getWindow().getCurrentFocus() != null) { if (activity.window.currentFocus != null) {
if (activity.getWindow().getCurrentFocus() is EditText) { if (activity.window.currentFocus is EditText) {
hideInput((activity.getWindow().getCurrentFocus() as EditText?)!!) hideInput((activity.window.currentFocus as EditText?)!!)
} else { } else {
LOG.e("AppUtils", "hideInput:View-> " + activity.getWindow().getCurrentFocus()) LOG.e("AppUtils", "hideInput:View-> " + activity.window.currentFocus)
val inputManager = activity.getWindow().getContext() val inputManager = activity.window.context
.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager .getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
inputManager.hideSoftInputFromWindow( inputManager.hideSoftInputFromWindow(
activity.getWindow().getCurrentFocus()!! activity.window.currentFocus!!
.getWindowToken(), HIDE_IMPLICIT_ONLY .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) { fun showInput(editText: EditText) {
val imm = MyApplication.context val imm = MyApplication.context
.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager? .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 android.widget.ImageView
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.CircleCrop
import com.jia.er.nebuluxe.app.R import com.jia.er.nebuluxe.app.R
object ImageLoadUtil { object ImageLoadUtil {
@ -15,4 +16,16 @@ object ImageLoadUtil {
.placeholder(if (isHor) R.drawable.ic_default_iv_hor else R.drawable.ic_default_iv_ver) .placeholder(if (isHor) R.drawable.ic_default_iv_hor else R.drawable.ic_default_iv_ver)
.into(iv) .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) // context.getColor(R.color.white)
// ) // )
// } // }
if (item?.is_lock == true && !Memory.isVip()) { // todo 解锁功能暂时隐藏
holder.setVisible(R.id.iv_example_lock, true) // if (item?.is_lock == true && !Memory.isVip()) {
} else { // holder.setVisible(R.id.iv_example_lock, true)
holder.setVisible(R.id.iv_example_lock, false) // } else {
} // holder.setVisible(R.id.iv_example_lock, false)
// }
} }
override fun onCreateViewHolder( 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_height="@dimen/padding_50px"
android:layout_marginLeft="@dimen/padding_20px" android:layout_marginLeft="@dimen/padding_20px"
android:layout_marginRight="@dimen/padding_20px" android:layout_marginRight="@dimen/padding_20px"
android:layout_marginBottom="@dimen/padding_35px"
android:background="@drawable/bg_conner_50px_black_history" android:background="@drawable/bg_conner_50px_black_history"
android:gravity="center" android:gravity="center"
android:orientation="horizontal" android:orientation="horizontal"
@ -344,10 +345,12 @@
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatTextView <androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_his_title" android:id="@+id/tv_his_title"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:maxLines="1"
android:paddingLeft="@dimen/padding_10px" android:paddingLeft="@dimen/padding_10px"
android:textColor="@color/text_color_white" android:textColor="@color/text_color_white"
android:textSize="@dimen/text_size_14px" android:textSize="@dimen/text_size_14px"

View File

@ -11,11 +11,20 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" /> android:layout_height="wrap_content" />
<FrameLayout
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_recommend"
android:layout_width="match_parent" 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> </com.scwang.smart.refresh.layout.SmartRefreshLayout>

View File

@ -12,25 +12,12 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:scaleType="centerCrop" /> 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 <androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_player_seek_time" android:id="@+id/tv_player_seek_time"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" 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:layout_marginBottom="@dimen/padding_10px"
android:gravity="center_horizontal" android:gravity="center_horizontal"
android:textColor="@color/white" android:textColor="@color/white"
@ -38,17 +25,22 @@
android:visibility="invisible" android:visibility="invisible"
tools:text="00:00/02:24" /> tools:text="00:00/02:24" />
<androidx.appcompat.widget.LinearLayoutCompat <FrameLayout
android:id="@+id/example_ll_bottom_controller" android:id="@+id/example_ll_bottom_controller"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="@dimen/padding_20px" android:layout_height="@dimen/padding_20px"
android:layout_alignParentBottom="true" android:layout_alignParentTop="true"
android:layout_marginLeft="@dimen/padding_19px" android:layout_marginLeft="@dimen/padding_19px"
android:layout_marginTop="@dimen/padding_49px"
android:layout_marginRight="@dimen/padding_19px" android:layout_marginRight="@dimen/padding_19px"
android:layout_marginBottom="@dimen/padding_19px"
android:gravity="center" android:gravity="center"
android:orientation="vertical"> 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 <androidx.appcompat.widget.AppCompatSeekBar
android:id="@+id/example_seekBar_player_controller" android:id="@+id/example_seekBar_player_controller"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -60,16 +52,59 @@
android:splitTrack="false" android:splitTrack="false"
android:thumb="@drawable/progress_thumb" android:thumb="@drawable/progress_thumb"
android:thumbOffset="@dimen/padding_8px" /> android:thumbOffset="@dimen/padding_8px" />
</androidx.appcompat.widget.LinearLayoutCompat> </FrameLayout>
<com.jia.er.nebuluxe.app.ui.LoadingLine <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/load_line" android:id="@+id/ll_history"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="@dimen/padding_2px" android:layout_height="@dimen/padding_50px"
android:layout_alignParentBottom="true" android:layout_below="@id/example_ll_bottom_controller"
android:layout_marginLeft="@dimen/padding_19px" android:layout_marginLeft="@dimen/padding_20px"
android:layout_marginRight="@dimen/padding_19px" android:layout_marginRight="@dimen/padding_20px"
android:layout_marginBottom="@dimen/padding_28px" /> 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 <androidx.appcompat.widget.AppCompatImageView
android:id="@+id/example_iv_play_player_controller" android:id="@+id/example_iv_play_player_controller"
@ -81,58 +116,31 @@
android:padding="@dimen/padding_15px" android:padding="@dimen/padding_15px"
android:src="@drawable/iv_example_stop" /> android:src="@drawable/iv_example_stop" />
<androidx.appcompat.widget.LinearLayoutCompat <!-- <androidx.appcompat.widget.LinearLayoutCompat-->
android:layout_width="wrap_content" <!-- android:layout_width="wrap_content"-->
android:layout_height="wrap_content" <!-- android:layout_height="wrap_content"-->
android:layout_above="@id/cl" <!-- android:layout_alignParentEnd="true"-->
android:layout_alignParentEnd="true" <!-- android:layout_marginRight="@dimen/padding_16px"-->
android:layout_marginRight="@dimen/padding_16px" <!-- android:layout_marginBottom="@dimen/padding_26px"-->
android:layout_marginBottom="@dimen/padding_26px" <!-- android:gravity="center"-->
android:gravity="center" <!-- android:orientation="vertical">-->
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatImageView <!-- <androidx.appcompat.widget.AppCompatImageView-->
android:id="@+id/example_iv_collection_controller" <!-- android:id="@+id/example_iv_collection_controller"-->
android:layout_width="wrap_content" <!-- android:layout_width="wrap_content"-->
android:layout_height="wrap_content" <!-- android:layout_height="wrap_content"-->
android:src="@drawable/iv_example_collection_n" /> <!-- android:src="@drawable/iv_example_collection_n" />-->
<androidx.appcompat.widget.AppCompatTextView <!-- <androidx.appcompat.widget.AppCompatTextView-->
android:id="@+id/example_tv_collection_num_controller" <!-- android:id="@+id/example_tv_collection_num_controller"-->
android:layout_width="wrap_content" <!-- android:layout_width="wrap_content"-->
android:layout_height="wrap_content" <!-- android:layout_height="wrap_content"-->
android:gravity="center" <!-- android:gravity="center"-->
android:text="111" <!-- android:text="111"-->
android:textColor="#FFDAA4" <!-- android:textColor="#FFDAA4"-->
android:textSize="@dimen/text_size_12px" <!-- android:textSize="@dimen/text_size_12px"-->
android:textStyle="bold" /> <!-- android:textStyle="bold" />-->
</androidx.appcompat.widget.LinearLayoutCompat> <!-- </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>
</RelativeLayout> </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> <item name="cornerSize">@dimen/padding_10px</item>
</style> </style>
<style name="Circle60pxCornerStyle">
<item name="cornerFamily">rounded</item>
<item name="cornerSize">@dimen/padding_60px</item>
</style>
<style name="HorizontalLine"> <style name="HorizontalLine">
<item name="android:background">@color/text_color_white</item> <item name="android:background">@color/text_color_white</item>
<item name="android:layout_height">1px</item> <item name="android:layout_height">1px</item>