mirror of
https://github.com/lizongying/my-tv.git
synced 2026-10-26 22:26:29 +08:00
channel num setting
This commit is contained in:
@@ -22,6 +22,7 @@ class ChannelFragment : Fragment() {
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = ChannelBinding.inflate(inflater, container, false)
|
||||
_binding!!.root.visibility = View.GONE
|
||||
(activity as MainActivity).fragmentReady()
|
||||
return binding.root
|
||||
}
|
||||
@@ -41,7 +42,6 @@ class ChannelFragment : Fragment() {
|
||||
handler.postDelayed(removeRunnable, delay)
|
||||
} else {
|
||||
val ch = "${binding.channelContent.text}$channel".toInt()
|
||||
Log.i(TAG, "channel $ch")
|
||||
(activity as MainActivity).play(ch)
|
||||
binding.channelContent.text = ""
|
||||
view?.visibility = View.GONE
|
||||
|
||||
@@ -23,17 +23,11 @@ class InfoFragment : Fragment() {
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = InfoBinding.inflate(inflater, container, false)
|
||||
_binding!!.root.visibility = View.GONE
|
||||
(activity as MainActivity).fragmentReady()
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
|
||||
// Use a Handler to delay the fragment transaction
|
||||
handler.postDelayed(removeRunnable, delay)
|
||||
}
|
||||
|
||||
fun show(tvViewModel: TVViewModel) {
|
||||
binding.textView.text = tvViewModel.title.value
|
||||
if (tvViewModel.title.value == "CCTV8K 超高清") {
|
||||
@@ -56,10 +50,13 @@ class InfoFragment : Fragment() {
|
||||
handler.postDelayed(removeRunnable, delay)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
handler.postDelayed(removeRunnable, delay)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
Log.i(TAG, "onPause")
|
||||
// Cancel the delayed task when the fragment is paused
|
||||
handler.removeCallbacks(removeRunnable)
|
||||
}
|
||||
|
||||
|
||||
@@ -25,9 +25,10 @@ import java.security.MessageDigest
|
||||
class MainActivity : FragmentActivity() {
|
||||
|
||||
var playerFragment = PlayerFragment()
|
||||
private val mainFragment = MainFragment2()
|
||||
private val mainFragment = MainFragment()
|
||||
private val infoFragment = InfoFragment()
|
||||
private val channelFragment = ChannelFragment()
|
||||
private lateinit var settingFragment: SettingFragment
|
||||
|
||||
private var doubleBackToExitPressedOnce = false
|
||||
|
||||
@@ -39,9 +40,9 @@ class MainActivity : FragmentActivity() {
|
||||
|
||||
private lateinit var sharedPref: SharedPreferences
|
||||
private var channelReversal = false
|
||||
private var channelNum = true
|
||||
|
||||
private var versionName = ""
|
||||
private lateinit var dialogFragment: MyDialogFragment
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@@ -57,8 +58,6 @@ class MainActivity : FragmentActivity() {
|
||||
.add(R.id.main_browse_fragment, infoFragment)
|
||||
.add(R.id.main_browse_fragment, channelFragment)
|
||||
.add(R.id.main_browse_fragment, mainFragment)
|
||||
.hide(infoFragment)
|
||||
.hide(channelFragment)
|
||||
.hide(mainFragment)
|
||||
.commit()
|
||||
mainFragment.view?.requestFocus()
|
||||
@@ -66,15 +65,32 @@ class MainActivity : FragmentActivity() {
|
||||
gestureDetector = GestureDetector(this, GestureListener())
|
||||
|
||||
sharedPref = getPreferences(Context.MODE_PRIVATE)
|
||||
channelReversal = sharedPref.getBoolean(CHANNEL_REVERSAL, false)
|
||||
channelReversal = sharedPref.getBoolean(CHANNEL_REVERSAL, channelReversal)
|
||||
channelNum = sharedPref.getBoolean(CHANNEL_NUM, channelNum)
|
||||
|
||||
versionName = getPackageInfo().versionName
|
||||
dialogFragment = MyDialogFragment(versionName, channelReversal)
|
||||
settingFragment = SettingFragment(versionName, channelReversal, channelNum)
|
||||
}
|
||||
|
||||
fun showInfoFragment(tvViewModel: TVViewModel) {
|
||||
infoFragment.show(tvViewModel)
|
||||
channelFragment.show(tvViewModel)
|
||||
if (channelNum) {
|
||||
channelFragment.show(tvViewModel)
|
||||
}
|
||||
}
|
||||
|
||||
private fun showChannel(channel: String) {
|
||||
if (!mainFragment.isHidden) {
|
||||
return
|
||||
}
|
||||
|
||||
if (settingFragment.isVisible) {
|
||||
return
|
||||
}
|
||||
|
||||
if (channelNum) {
|
||||
channelFragment.show(channel)
|
||||
}
|
||||
}
|
||||
|
||||
fun play(tvViewModel: TVViewModel) {
|
||||
@@ -199,25 +215,33 @@ class MainActivity : FragmentActivity() {
|
||||
this.channelReversal = channelReversal
|
||||
}
|
||||
|
||||
fun saveChannelNum(channelNum: Boolean) {
|
||||
with(sharedPref.edit()) {
|
||||
putBoolean(CHANNEL_NUM, channelNum)
|
||||
apply()
|
||||
}
|
||||
this.channelNum = channelNum
|
||||
}
|
||||
|
||||
private fun showHelp() {
|
||||
if (!mainFragment.isHidden) {
|
||||
return
|
||||
}
|
||||
|
||||
Log.i(TAG, "dialogFragment ${dialogFragment.isVisible}")
|
||||
if (!dialogFragment.isVisible) {
|
||||
dialogFragment.show(supportFragmentManager, "settings_dialog")
|
||||
Log.i(TAG, "settingFragment ${settingFragment.isVisible}")
|
||||
if (!settingFragment.isVisible) {
|
||||
settingFragment.show(supportFragmentManager, "setting")
|
||||
handler.removeCallbacks(hideHelp)
|
||||
handler.postDelayed(hideHelp, delayHideHelp)
|
||||
} else {
|
||||
handler.removeCallbacks(hideHelp)
|
||||
dialogFragment.dismiss()
|
||||
settingFragment.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
private val hideHelp = Runnable {
|
||||
if (dialogFragment.isVisible) {
|
||||
dialogFragment.dismiss()
|
||||
if (settingFragment.isVisible) {
|
||||
settingFragment.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,18 +297,6 @@ class MainActivity : FragmentActivity() {
|
||||
}, 2000)
|
||||
}
|
||||
|
||||
private fun showChannel(channel: String) {
|
||||
if (!mainFragment.isHidden) {
|
||||
return
|
||||
}
|
||||
|
||||
if (dialogFragment.isVisible) {
|
||||
return
|
||||
}
|
||||
|
||||
channelFragment.show(channel)
|
||||
}
|
||||
|
||||
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
|
||||
when (keyCode) {
|
||||
KeyEvent.KEYCODE_0 -> {
|
||||
@@ -479,5 +491,6 @@ class MainActivity : FragmentActivity() {
|
||||
companion object {
|
||||
private const val TAG = "MainActivity"
|
||||
private const val CHANNEL_REVERSAL = "channel_reversal"
|
||||
private const val CHANNEL_NUM = "channel_num"
|
||||
}
|
||||
}
|
||||
@@ -6,33 +6,33 @@ import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import androidx.leanback.app.BrowseSupportFragment
|
||||
import androidx.leanback.widget.ArrayObjectAdapter
|
||||
import androidx.leanback.widget.HeaderItem
|
||||
import androidx.leanback.widget.ListRow
|
||||
import androidx.leanback.widget.ListRowPresenter
|
||||
import androidx.leanback.widget.ListRowPresenter.SelectItemViewHolderTask
|
||||
import androidx.leanback.widget.OnItemViewClickedListener
|
||||
import androidx.leanback.widget.OnItemViewSelectedListener
|
||||
import androidx.leanback.widget.Presenter
|
||||
import androidx.leanback.widget.Row
|
||||
import androidx.leanback.widget.RowPresenter
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.lizongying.mytv.Utils.getDateTimestamp
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.lizongying.mytv.Utils.dpToPx
|
||||
import com.lizongying.mytv.databinding.RowBinding
|
||||
import com.lizongying.mytv.databinding.ShowBinding
|
||||
import com.lizongying.mytv.models.TVListViewModel
|
||||
import com.lizongying.mytv.models.TVViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class MainFragment : Fragment(), CardAdapter.ItemListener {
|
||||
|
||||
class MainFragment : BrowseSupportFragment() {
|
||||
var itemPosition: Int = 0
|
||||
private var itemPosition = 0
|
||||
|
||||
private var rowList: MutableList<View> = mutableListOf()
|
||||
|
||||
private var _binding: ShowBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
private var request: Request = Request()
|
||||
|
||||
private var rowsAdapter: ArrayObjectAdapter? = null
|
||||
|
||||
var tvListViewModel = TVListViewModel()
|
||||
|
||||
private var sharedPref: SharedPreferences? = null
|
||||
@@ -44,87 +44,216 @@ class MainFragment : BrowseSupportFragment() {
|
||||
|
||||
private var ready = 0
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
headersState = HEADERS_DISABLED
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = ShowBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
|
||||
activity?.let { request.initYSP(it) }
|
||||
|
||||
sharedPref = activity?.getPreferences(Context.MODE_PRIVATE)
|
||||
|
||||
loadRows()
|
||||
view?.post {
|
||||
val content = binding.content
|
||||
|
||||
setupEventListeners()
|
||||
var idx: Long = 0
|
||||
for ((k, v) in TVList.list) {
|
||||
val itemBinding: RowBinding =
|
||||
RowBinding.inflate(layoutInflater, content, false)
|
||||
|
||||
mUpdateProgramRunnable = UpdateProgramRunnable()
|
||||
handler.post(mUpdateProgramRunnable)
|
||||
|
||||
tvListViewModel.getTVListViewModel().value?.forEach { tvViewModel ->
|
||||
tvViewModel.errInfo.observe(viewLifecycleOwner) { _ ->
|
||||
if (tvViewModel.errInfo.value != null
|
||||
&& tvViewModel.id.value == itemPosition
|
||||
) {
|
||||
Toast.makeText(context, tvViewModel.errInfo.value, Toast.LENGTH_SHORT).show()
|
||||
val tvListViewModelCurrent = TVListViewModel()
|
||||
for ((idx2, v1) in v.withIndex()) {
|
||||
val tvViewModel = TVViewModel(v1)
|
||||
tvViewModel.setRowPosition(idx.toInt())
|
||||
tvViewModel.setItemPosition(idx2)
|
||||
tvListViewModelCurrent.addTVViewModel(tvViewModel)
|
||||
tvListViewModel.addTVViewModel(tvViewModel)
|
||||
}
|
||||
}
|
||||
tvViewModel.ready.observe(viewLifecycleOwner) { _ ->
|
||||
tvListViewModel.maxNum.add(v.size)
|
||||
|
||||
// not first time && channel not change
|
||||
if (tvViewModel.ready.value != null
|
||||
&& tvViewModel.id.value == itemPosition
|
||||
&& check(tvViewModel)
|
||||
) {
|
||||
Log.i(TAG, "ready ${tvViewModel.title.value}")
|
||||
(activity as? MainActivity)?.play(tvViewModel)
|
||||
}
|
||||
val adapter = CardAdapter(viewLifecycleOwner, tvListViewModelCurrent)
|
||||
rowList.add(itemBinding.rowItems)
|
||||
|
||||
adapter.setItemListener(this)
|
||||
|
||||
itemBinding.rowHeader.text = k
|
||||
itemBinding.rowItems.adapter = adapter
|
||||
itemBinding.rowItems.layoutManager =
|
||||
LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
|
||||
|
||||
val layoutParams = itemBinding.row.layoutParams as ViewGroup.MarginLayoutParams
|
||||
layoutParams.topMargin = dpToPx(11F)
|
||||
itemBinding.row.layoutParams = layoutParams
|
||||
content.addView(itemBinding.row)
|
||||
|
||||
idx++
|
||||
}
|
||||
tvViewModel.change.observe(viewLifecycleOwner) { _ ->
|
||||
if (tvViewModel.change.value != null) {
|
||||
val title = tvViewModel.title.value
|
||||
Log.i(TAG, "switch $title")
|
||||
if (tvViewModel.pid.value != "") {
|
||||
Log.i(TAG, "request $title ${tvViewModel.pid.value}")
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
tvViewModel.let { request.fetchData(it) }
|
||||
}
|
||||
(activity as? MainActivity)?.showInfoFragment(tvViewModel)
|
||||
setSelectedPosition(
|
||||
tvViewModel.getRowPosition(), true,
|
||||
SelectItemViewHolderTask(tvViewModel.getItemPosition())
|
||||
)
|
||||
} else {
|
||||
if (check(tvViewModel)) {
|
||||
(activity as? MainActivity)?.play(tvViewModel)
|
||||
|
||||
mUpdateProgramRunnable = UpdateProgramRunnable()
|
||||
handler.post(mUpdateProgramRunnable)
|
||||
|
||||
itemPosition = sharedPref?.getInt(POSITION, 0)!!
|
||||
if (itemPosition >= tvListViewModel.size()) {
|
||||
itemPosition = 0
|
||||
}
|
||||
tvListViewModel.setItemPosition(itemPosition)
|
||||
setPosition()
|
||||
tvListViewModel.getTVListViewModel().value?.forEach { tvViewModel ->
|
||||
tvViewModel.errInfo.observe(viewLifecycleOwner) { _ ->
|
||||
if (tvViewModel.errInfo.value != null
|
||||
&& tvViewModel.id.value == itemPosition
|
||||
) {
|
||||
Toast.makeText(context, tvViewModel.errInfo.value, Toast.LENGTH_SHORT)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
tvViewModel.ready.observe(viewLifecycleOwner) { _ ->
|
||||
|
||||
// not first time && channel not change
|
||||
if (tvViewModel.ready.value != null
|
||||
&& tvViewModel.id.value == itemPosition
|
||||
&& check(tvViewModel)
|
||||
) {
|
||||
Log.i(TAG, "ready ${tvViewModel.title.value}")
|
||||
(activity as? MainActivity)?.play(tvViewModel)
|
||||
}
|
||||
}
|
||||
tvViewModel.change.observe(viewLifecycleOwner) { _ ->
|
||||
if (tvViewModel.change.value != null) {
|
||||
val title = tvViewModel.title.value
|
||||
Log.i(TAG, "switch $title")
|
||||
if (tvViewModel.pid.value != "") {
|
||||
Log.i(TAG, "request $title ${tvViewModel.pid.value}")
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
tvViewModel.let { request.fetchData(it) }
|
||||
}
|
||||
(activity as? MainActivity)?.showInfoFragment(tvViewModel)
|
||||
|
||||
setSelectedPosition(
|
||||
tvViewModel.getRowPosition(), true,
|
||||
SelectItemViewHolderTask(tvViewModel.getItemPosition())
|
||||
setPosition(
|
||||
tvViewModel.getRowPosition(), tvViewModel.getItemPosition()
|
||||
)
|
||||
} else {
|
||||
if (check(tvViewModel)) {
|
||||
(activity as? MainActivity)?.play(tvViewModel)
|
||||
(activity as? MainActivity)?.showInfoFragment(tvViewModel)
|
||||
setPosition(
|
||||
tvViewModel.getRowPosition(), tvViewModel.getItemPosition()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fragmentReady()
|
||||
fragmentReady()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
handler.removeCallbacks(mUpdateProgramRunnable)
|
||||
with(sharedPref!!.edit()) {
|
||||
putInt("position", itemPosition)
|
||||
apply()
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
}
|
||||
|
||||
override fun onItemFocusChange(tvViewModel: TVViewModel, hasFocus: Boolean) {
|
||||
if (hasFocus) {
|
||||
tvListViewModel.setItemPositionCurrent(tvViewModel.id.value!!)
|
||||
(activity as MainActivity).keepRunnable()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onItemClicked(tvViewModel: TVViewModel) {
|
||||
if (this.isHidden) {
|
||||
(activity as? MainActivity)?.switchMainFragment()
|
||||
return
|
||||
}
|
||||
|
||||
if (itemPosition != tvViewModel.id.value!!) {
|
||||
itemPosition = tvViewModel.id.value!!
|
||||
tvListViewModel.setItemPosition(itemPosition)
|
||||
tvListViewModel.getTVViewModel(itemPosition)?.changed()
|
||||
}
|
||||
(activity as? MainActivity)?.switchMainFragment()
|
||||
}
|
||||
|
||||
fun setPosition() {
|
||||
val tvViewModel = tvListViewModel.getTVViewModel(itemPosition)
|
||||
rowList[tvViewModel!!.getRowPosition()].post {
|
||||
((rowList[tvViewModel.getRowPosition()] as RecyclerView).layoutManager as LinearLayoutManager).findViewByPosition(
|
||||
tvViewModel.getItemPosition()
|
||||
)?.requestFocus()
|
||||
}
|
||||
}
|
||||
|
||||
fun setPosition(rowPosition: Int, itemPosition: Int) {
|
||||
rowList[rowPosition].post {
|
||||
((rowList[rowPosition] as RecyclerView).layoutManager as LinearLayoutManager).findViewByPosition(
|
||||
itemPosition
|
||||
)?.requestFocus()
|
||||
}
|
||||
}
|
||||
|
||||
fun check(tvViewModel: TVViewModel): Boolean {
|
||||
val title = tvViewModel.title.value
|
||||
val videoUrl = tvViewModel.videoIndex.value?.let { tvViewModel.videoUrl.value?.get(it) }
|
||||
if (videoUrl == null || videoUrl == "") {
|
||||
Log.e(TAG, "$title videoUrl is empty")
|
||||
return false
|
||||
}
|
||||
|
||||
if (videoUrl == lastVideoUrl) {
|
||||
Log.e(TAG, "$title videoUrl is duplication")
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
fun fragmentReady() {
|
||||
ready++
|
||||
Log.i(TAG, "ready $ready")
|
||||
if (ready == 4) {
|
||||
// request.fetchPage()
|
||||
tvListViewModel.getTVViewModel(itemPosition)?.changed()
|
||||
}
|
||||
}
|
||||
|
||||
fun play(itemPosition: Int) {
|
||||
view?.post {
|
||||
if (itemPosition < tvListViewModel.size()) {
|
||||
this.itemPosition = itemPosition
|
||||
tvListViewModel.setItemPosition(itemPosition)
|
||||
tvListViewModel.getTVViewModel(itemPosition)?.changed()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun prev() {
|
||||
view?.post {
|
||||
itemPosition--
|
||||
if (itemPosition == -1) {
|
||||
itemPosition = tvListViewModel.size() - 1
|
||||
}
|
||||
tvListViewModel.setItemPosition(itemPosition)
|
||||
tvListViewModel.getTVViewModel(itemPosition)?.changed()
|
||||
}
|
||||
}
|
||||
|
||||
fun next() {
|
||||
view?.post {
|
||||
itemPosition++
|
||||
if (itemPosition == tvListViewModel.size()) {
|
||||
itemPosition = 0
|
||||
}
|
||||
tvListViewModel.setItemPosition(itemPosition)
|
||||
tvListViewModel.getTVViewModel(itemPosition)?.changed()
|
||||
}
|
||||
}
|
||||
|
||||
fun updateProgram(tvViewModel: TVViewModel) {
|
||||
val timestamp = getDateTimestamp()
|
||||
val timestamp = Utils.getDateTimestamp()
|
||||
if (timestamp - tvViewModel.programUpdateTime > 60) {
|
||||
if (tvViewModel.program.value!!.isEmpty()) {
|
||||
tvViewModel.programUpdateTime = timestamp
|
||||
@@ -150,180 +279,35 @@ class MainFragment : BrowseSupportFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
fun check(tvViewModel: TVViewModel): Boolean {
|
||||
val title = tvViewModel.title.value
|
||||
val videoUrl = tvViewModel.videoIndex.value?.let { tvViewModel.videoUrl.value?.get(it) }
|
||||
if (videoUrl == null || videoUrl == "") {
|
||||
Log.e(TAG, "$title videoUrl is empty")
|
||||
return false
|
||||
override fun onStop() {
|
||||
Log.i(TAG, "onStop")
|
||||
super.onStop()
|
||||
with(sharedPref!!.edit()) {
|
||||
putInt(POSITION, itemPosition)
|
||||
apply()
|
||||
}
|
||||
|
||||
if (videoUrl == lastVideoUrl) {
|
||||
Log.e(TAG, "$title videoUrl is duplication")
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
Log.i(TAG, "POSITION saved")
|
||||
}
|
||||
|
||||
fun toLastPosition() {
|
||||
setSelectedPosition(
|
||||
selectedPosition, false,
|
||||
SelectItemViewHolderTask(tvListViewModel.maxNum[selectedPosition] - 1)
|
||||
)
|
||||
override fun onDestroy() {
|
||||
Log.i(TAG, "onDestroy")
|
||||
super.onDestroy()
|
||||
handler.removeCallbacks(mUpdateProgramRunnable)
|
||||
}
|
||||
|
||||
fun toFirstPosition() {
|
||||
setSelectedPosition(
|
||||
selectedPosition, false,
|
||||
SelectItemViewHolderTask(0)
|
||||
)
|
||||
}
|
||||
|
||||
override fun startHeadersTransition(withHeaders: Boolean) {
|
||||
}
|
||||
|
||||
private fun loadRows() {
|
||||
rowsAdapter = ArrayObjectAdapter(ListRowPresenter())
|
||||
|
||||
val cardPresenter = CardPresenter(viewLifecycleOwner)
|
||||
|
||||
var idx: Long = 0
|
||||
for ((k, v) in TVList.list) {
|
||||
val listRowAdapter = ArrayObjectAdapter(cardPresenter)
|
||||
for ((idx2, v1) in v.withIndex()) {
|
||||
val tvViewModel = TVViewModel(v1)
|
||||
tvViewModel.setRowPosition(idx.toInt())
|
||||
tvViewModel.setItemPosition(idx2)
|
||||
tvListViewModel.addTVViewModel(tvViewModel)
|
||||
listRowAdapter.add(tvViewModel)
|
||||
}
|
||||
tvListViewModel.maxNum.add(v.size)
|
||||
val header = HeaderItem(idx, k)
|
||||
rowsAdapter!!.add(ListRow(header, listRowAdapter))
|
||||
idx++
|
||||
}
|
||||
|
||||
adapter = rowsAdapter
|
||||
|
||||
itemPosition = sharedPref?.getInt("position", 0)!!
|
||||
if (itemPosition >= tvListViewModel.size()) {
|
||||
itemPosition = 0
|
||||
}
|
||||
tvListViewModel.setItemPosition(itemPosition)
|
||||
}
|
||||
|
||||
fun fragmentReady() {
|
||||
ready++
|
||||
Log.i(TAG, "ready $ready")
|
||||
if (ready == 3) {
|
||||
// request.fetchPage()
|
||||
val tvViewModel = tvListViewModel.getTVViewModel(itemPosition)
|
||||
tvViewModel?.changed()
|
||||
|
||||
(activity as? MainActivity)?.switchMainFragment()
|
||||
}
|
||||
}
|
||||
|
||||
fun prev() {
|
||||
view?.post {
|
||||
itemPosition--
|
||||
if (itemPosition == -1) {
|
||||
itemPosition = tvListViewModel.size() - 1
|
||||
}
|
||||
tvListViewModel.setItemPosition(itemPosition)
|
||||
|
||||
val tvViewModel = tvListViewModel.getTVViewModel(itemPosition)
|
||||
tvViewModel?.changed()
|
||||
}
|
||||
}
|
||||
|
||||
fun next() {
|
||||
view?.post {
|
||||
itemPosition++
|
||||
if (itemPosition == tvListViewModel.size()) {
|
||||
itemPosition = 0
|
||||
}
|
||||
tvListViewModel.setItemPosition(itemPosition)
|
||||
|
||||
val tvViewModel = tvListViewModel.getTVViewModel(itemPosition)
|
||||
tvViewModel?.changed()
|
||||
}
|
||||
}
|
||||
|
||||
fun prevSource() {
|
||||
view?.post {
|
||||
val tvViewModel = tvListViewModel.getTVViewModel(itemPosition)
|
||||
if (tvViewModel != null) {
|
||||
if (tvViewModel.videoUrl.value!!.size > 1) {
|
||||
val videoIndex = tvViewModel.videoIndex.value?.minus(1)
|
||||
if (videoIndex == -1) {
|
||||
tvViewModel.setVideoIndex(tvViewModel.videoUrl.value!!.size - 1)
|
||||
}
|
||||
tvViewModel.changed()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun nextSource() {
|
||||
view?.post {
|
||||
val tvViewModel = tvListViewModel.getTVViewModel(itemPosition)
|
||||
if (tvViewModel != null) {
|
||||
if (tvViewModel.videoUrl.value!!.size > 1) {
|
||||
val videoIndex = tvViewModel.videoIndex.value?.plus(1)
|
||||
if (videoIndex == tvViewModel.videoUrl.value!!.size) {
|
||||
tvViewModel.setVideoIndex(0)
|
||||
}
|
||||
tvViewModel.changed()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupEventListeners() {
|
||||
onItemViewClickedListener = ItemViewClickedListener()
|
||||
onItemViewSelectedListener = ItemViewSelectedListener()
|
||||
}
|
||||
|
||||
private inner class ItemViewClickedListener : OnItemViewClickedListener {
|
||||
override fun onItemClicked(
|
||||
itemViewHolder: Presenter.ViewHolder,
|
||||
item: Any,
|
||||
rowViewHolder: RowPresenter.ViewHolder,
|
||||
row: Row
|
||||
) {
|
||||
if (item is TVViewModel) {
|
||||
if (itemPosition != item.id.value!!) {
|
||||
itemPosition = item.id.value!!
|
||||
tvListViewModel.setItemPosition(itemPosition)
|
||||
|
||||
val tvViewModel = tvListViewModel.getTVViewModel(itemPosition)
|
||||
tvViewModel?.changed()
|
||||
}
|
||||
(activity as? MainActivity)?.switchMainFragment()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private inner class ItemViewSelectedListener : OnItemViewSelectedListener {
|
||||
override fun onItemSelected(
|
||||
itemViewHolder: Presenter.ViewHolder?, item: Any?,
|
||||
rowViewHolder: RowPresenter.ViewHolder, row: Row
|
||||
) {
|
||||
if (item is TVViewModel) {
|
||||
tvListViewModel.setItemPositionCurrent(item.id.value!!)
|
||||
(activity as MainActivity).keepRunnable()
|
||||
}
|
||||
}
|
||||
override fun onDestroyView() {
|
||||
Log.i(TAG, "onDestroyView")
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
view!!.requestFocus()
|
||||
view?.post { view?.requestFocus() }
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "MainFragment"
|
||||
private const val POSITION = "position"
|
||||
}
|
||||
}
|
||||
@@ -1,313 +0,0 @@
|
||||
package com.lizongying.mytv
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.lizongying.mytv.Utils.dpToPx
|
||||
import com.lizongying.mytv.databinding.RowBinding
|
||||
import com.lizongying.mytv.databinding.ShowBinding
|
||||
import com.lizongying.mytv.models.TVListViewModel
|
||||
import com.lizongying.mytv.models.TVViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class MainFragment2 : Fragment(), CardAdapter.ItemListener {
|
||||
|
||||
private var itemPosition = 0
|
||||
|
||||
private var rowList: MutableList<View> = mutableListOf()
|
||||
|
||||
private var _binding: ShowBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
private var request: Request = Request()
|
||||
|
||||
var tvListViewModel = TVListViewModel()
|
||||
|
||||
private var sharedPref: SharedPreferences? = null
|
||||
|
||||
private var lastVideoUrl: String = ""
|
||||
|
||||
private val handler = Handler(Looper.getMainLooper())
|
||||
private lateinit var mUpdateProgramRunnable: UpdateProgramRunnable
|
||||
|
||||
private var ready = 0
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = ShowBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
|
||||
activity?.let { request.initYSP(it) }
|
||||
sharedPref = activity?.getPreferences(Context.MODE_PRIVATE)
|
||||
|
||||
view?.post {
|
||||
val content = binding.content
|
||||
|
||||
var idx: Long = 0
|
||||
for ((k, v) in TVList.list) {
|
||||
val itemBinding: RowBinding =
|
||||
RowBinding.inflate(layoutInflater, content, false)
|
||||
|
||||
val tvListViewModelCurrent = TVListViewModel()
|
||||
for ((idx2, v1) in v.withIndex()) {
|
||||
val tvViewModel = TVViewModel(v1)
|
||||
tvViewModel.setRowPosition(idx.toInt())
|
||||
tvViewModel.setItemPosition(idx2)
|
||||
tvListViewModelCurrent.addTVViewModel(tvViewModel)
|
||||
tvListViewModel.addTVViewModel(tvViewModel)
|
||||
}
|
||||
tvListViewModel.maxNum.add(v.size)
|
||||
|
||||
val adapter = CardAdapter(viewLifecycleOwner, tvListViewModelCurrent)
|
||||
rowList.add(itemBinding.rowItems)
|
||||
|
||||
adapter.setItemListener(this)
|
||||
|
||||
itemBinding.rowHeader.text = k
|
||||
itemBinding.rowItems.adapter = adapter
|
||||
itemBinding.rowItems.layoutManager =
|
||||
LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
|
||||
|
||||
val layoutParams = itemBinding.row.layoutParams as ViewGroup.MarginLayoutParams
|
||||
layoutParams.topMargin = dpToPx(11F)
|
||||
itemBinding.row.layoutParams = layoutParams
|
||||
content.addView(itemBinding.row)
|
||||
|
||||
idx++
|
||||
}
|
||||
|
||||
mUpdateProgramRunnable = UpdateProgramRunnable()
|
||||
handler.post(mUpdateProgramRunnable)
|
||||
|
||||
itemPosition = sharedPref?.getInt(POSITION, 0)!!
|
||||
if (itemPosition >= tvListViewModel.size()) {
|
||||
itemPosition = 0
|
||||
}
|
||||
setPosition()
|
||||
tvListViewModel.setItemPosition(itemPosition)
|
||||
tvListViewModel.getTVListViewModel().value?.forEach { tvViewModel ->
|
||||
tvViewModel.errInfo.observe(viewLifecycleOwner) { _ ->
|
||||
if (tvViewModel.errInfo.value != null
|
||||
&& tvViewModel.id.value == itemPosition
|
||||
) {
|
||||
Toast.makeText(context, tvViewModel.errInfo.value, Toast.LENGTH_SHORT)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
tvViewModel.ready.observe(viewLifecycleOwner) { _ ->
|
||||
|
||||
// not first time && channel not change
|
||||
if (tvViewModel.ready.value != null
|
||||
&& tvViewModel.id.value == itemPosition
|
||||
&& check(tvViewModel)
|
||||
) {
|
||||
Log.i(TAG, "ready ${tvViewModel.title.value}")
|
||||
(activity as? MainActivity)?.play(tvViewModel)
|
||||
}
|
||||
}
|
||||
tvViewModel.change.observe(viewLifecycleOwner) { _ ->
|
||||
if (tvViewModel.change.value != null) {
|
||||
val title = tvViewModel.title.value
|
||||
Log.i(TAG, "switch $title")
|
||||
if (tvViewModel.pid.value != "") {
|
||||
Log.i(TAG, "request $title ${tvViewModel.pid.value}")
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
tvViewModel.let { request.fetchData(it) }
|
||||
}
|
||||
(activity as? MainActivity)?.showInfoFragment(tvViewModel)
|
||||
setPosition(
|
||||
tvViewModel.getRowPosition(), tvViewModel.getItemPosition()
|
||||
)
|
||||
} else {
|
||||
if (check(tvViewModel)) {
|
||||
(activity as? MainActivity)?.play(tvViewModel)
|
||||
(activity as? MainActivity)?.showInfoFragment(tvViewModel)
|
||||
setPosition(
|
||||
tvViewModel.getRowPosition(), tvViewModel.getItemPosition()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fragmentReady()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
}
|
||||
|
||||
override fun onItemFocusChange(tvViewModel: TVViewModel, hasFocus: Boolean) {
|
||||
if (hasFocus) {
|
||||
tvListViewModel.setItemPositionCurrent(tvViewModel.id.value!!)
|
||||
(activity as MainActivity).keepRunnable()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onItemClicked(tvViewModel: TVViewModel) {
|
||||
if (this.isHidden) {
|
||||
(activity as? MainActivity)?.switchMainFragment()
|
||||
return
|
||||
}
|
||||
|
||||
if (itemPosition != tvViewModel.id.value!!) {
|
||||
itemPosition = tvViewModel.id.value!!
|
||||
tvListViewModel.setItemPosition(itemPosition)
|
||||
tvListViewModel.getTVViewModel(itemPosition)?.changed()
|
||||
}
|
||||
(activity as? MainActivity)?.switchMainFragment()
|
||||
}
|
||||
|
||||
fun setPosition() {
|
||||
val tvViewModel = tvListViewModel.getTVViewModel(itemPosition)
|
||||
rowList[tvViewModel!!.getRowPosition()].post {
|
||||
((rowList[tvViewModel.getRowPosition()] as RecyclerView).layoutManager as LinearLayoutManager).findViewByPosition(
|
||||
tvViewModel.getItemPosition()
|
||||
)?.requestFocus()
|
||||
}
|
||||
}
|
||||
|
||||
fun setPosition(rowPosition: Int, itemPosition: Int) {
|
||||
rowList[rowPosition].post {
|
||||
((rowList[rowPosition] as RecyclerView).layoutManager as LinearLayoutManager).findViewByPosition(
|
||||
itemPosition
|
||||
)?.requestFocus()
|
||||
}
|
||||
}
|
||||
|
||||
fun check(tvViewModel: TVViewModel): Boolean {
|
||||
val title = tvViewModel.title.value
|
||||
val videoUrl = tvViewModel.videoIndex.value?.let { tvViewModel.videoUrl.value?.get(it) }
|
||||
if (videoUrl == null || videoUrl == "") {
|
||||
Log.e(TAG, "$title videoUrl is empty")
|
||||
return false
|
||||
}
|
||||
|
||||
if (videoUrl == lastVideoUrl) {
|
||||
Log.e(TAG, "$title videoUrl is duplication")
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
fun fragmentReady() {
|
||||
ready++
|
||||
Log.i(TAG, "ready $ready")
|
||||
if (ready == 4) {
|
||||
// request.fetchPage()
|
||||
tvListViewModel.getTVViewModel(itemPosition)?.changed()
|
||||
}
|
||||
}
|
||||
|
||||
fun play(itemPosition: Int) {
|
||||
view?.post {
|
||||
if (itemPosition < tvListViewModel.size()) {
|
||||
this.itemPosition = itemPosition
|
||||
tvListViewModel.setItemPosition(itemPosition)
|
||||
tvListViewModel.getTVViewModel(itemPosition)?.changed()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun prev() {
|
||||
view?.post {
|
||||
itemPosition--
|
||||
if (itemPosition == -1) {
|
||||
itemPosition = tvListViewModel.size() - 1
|
||||
}
|
||||
tvListViewModel.setItemPosition(itemPosition)
|
||||
tvListViewModel.getTVViewModel(itemPosition)?.changed()
|
||||
}
|
||||
}
|
||||
|
||||
fun next() {
|
||||
view?.post {
|
||||
itemPosition++
|
||||
if (itemPosition == tvListViewModel.size()) {
|
||||
itemPosition = 0
|
||||
}
|
||||
tvListViewModel.setItemPosition(itemPosition)
|
||||
tvListViewModel.getTVViewModel(itemPosition)?.changed()
|
||||
}
|
||||
}
|
||||
|
||||
fun updateProgram(tvViewModel: TVViewModel) {
|
||||
val timestamp = Utils.getDateTimestamp()
|
||||
if (timestamp - tvViewModel.programUpdateTime > 60) {
|
||||
if (tvViewModel.program.value!!.isEmpty()) {
|
||||
tvViewModel.programUpdateTime = timestamp
|
||||
request.fetchProgram(tvViewModel)
|
||||
} else {
|
||||
if (timestamp - tvViewModel.program.value!!.last().et < 600) {
|
||||
tvViewModel.programUpdateTime = timestamp
|
||||
request.fetchProgram(tvViewModel)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inner class UpdateProgramRunnable : Runnable {
|
||||
override fun run() {
|
||||
tvListViewModel.getTVListViewModel().value?.filter { it.programId.value != null }
|
||||
?.forEach { tvViewModel ->
|
||||
updateProgram(
|
||||
tvViewModel
|
||||
)
|
||||
}
|
||||
handler.postDelayed(this, 60000)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
Log.i(TAG, "onStop")
|
||||
super.onStop()
|
||||
with(sharedPref!!.edit()) {
|
||||
putInt(POSITION, itemPosition)
|
||||
apply()
|
||||
}
|
||||
Log.i(TAG, "POSITION saved")
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
Log.i(TAG, "onDestroy")
|
||||
super.onDestroy()
|
||||
handler.removeCallbacks(mUpdateProgramRunnable)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
Log.i(TAG, "onDestroyView")
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
view!!.requestFocus()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "MainFragment"
|
||||
private const val POSITION = "position"
|
||||
}
|
||||
}
|
||||
+14
-5
@@ -8,7 +8,10 @@ import androidx.fragment.app.DialogFragment
|
||||
import com.lizongying.mytv.databinding.DialogBinding
|
||||
|
||||
|
||||
class MyDialogFragment(private val versionName: String, private val channelReversal: Boolean) :
|
||||
class SettingFragment(private val versionName: String,
|
||||
private val channelReversal: Boolean,
|
||||
private val channelNum: Boolean,
|
||||
) :
|
||||
DialogFragment() {
|
||||
|
||||
private var _binding: DialogBinding? = null
|
||||
@@ -28,12 +31,18 @@ class MyDialogFragment(private val versionName: String, private val channelRever
|
||||
_binding?.version?.text =
|
||||
"当前版本: $versionName\n获取最新: https://github.com/lizongying/my-tv/releases/"
|
||||
|
||||
val switchView = _binding?.switchView
|
||||
switchView?.isChecked = channelReversal
|
||||
switchView?.setOnCheckedChangeListener { _, isChecked ->
|
||||
val switchChannelReversal = _binding?.switchChannelReversal
|
||||
switchChannelReversal?.isChecked = channelReversal
|
||||
switchChannelReversal?.setOnCheckedChangeListener { _, isChecked ->
|
||||
(activity as MainActivity).saveChannelReversal(isChecked)
|
||||
}
|
||||
|
||||
val switchChannelNum = _binding?.switchChannelNum
|
||||
switchChannelNum?.isChecked = channelNum
|
||||
switchChannelNum?.setOnCheckedChangeListener { _, isChecked ->
|
||||
(activity as MainActivity).saveChannelNum(isChecked)
|
||||
}
|
||||
|
||||
return binding.root
|
||||
}
|
||||
|
||||
@@ -43,7 +52,7 @@ class MyDialogFragment(private val versionName: String, private val channelRever
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TAG = "MyDialogFragment"
|
||||
const val TAG = "SettingFragment"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ object TVList {
|
||||
"CCTV10 科教" to arrayOf("600001805", "2000203503"),
|
||||
"CCTV11 戏曲" to arrayOf("600001806", "2000204103"),
|
||||
"CCTV12 社会与法" to arrayOf("600001807", "2000202603"),
|
||||
// "CCTV13 新闻" to arrayOf("600001811","2000204603"),
|
||||
"CCTV13 新闻" to arrayOf("600001811","2000204603"),
|
||||
"CCTV14 少儿" to arrayOf("600001809", "2000204403"),
|
||||
"CCTV15 音乐" to arrayOf("600001815", "2000205003"),
|
||||
"CCTV16 奥林匹克" to arrayOf("600098637", "2012375003"),
|
||||
|
||||
@@ -20,7 +20,7 @@ class TVViewModel(private var tv: TV) : ViewModel() {
|
||||
private var itemPosition: Int = 0
|
||||
|
||||
var retryTimes: Int = 0
|
||||
var retryMaxTimes: Int = 5
|
||||
var retryMaxTimes: Int = 8
|
||||
var programUpdateTime: Long = 0
|
||||
|
||||
private val _errInfo = MutableLiveData<String>()
|
||||
|
||||
@@ -26,12 +26,18 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:text="当前版本: $versionName\n获取最新: https://github.com/lizongying/my-tv/releases/"
|
||||
></TextView>
|
||||
<Switch
|
||||
android:id="@+id/switch_view"
|
||||
android:id="@+id/switch_channel_reversal"
|
||||
android:text="@string/title_channel_reversal"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
<Switch
|
||||
android:id="@+id/switch_channel_num"
|
||||
android:text="@string/title_channel_num"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
</LinearLayout>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<resources>
|
||||
<string name="app_name">我的电视</string>
|
||||
<string name="title_channel_reversal">频道反转</string>
|
||||
<string name="title_channel_reversal">换台反转</string>
|
||||
<string name="title_channel_num">数字选台</string>
|
||||
</resources>
|
||||
Reference in New Issue
Block a user