From 9feb0dc4bc3e2eceb132c303bd4d5ec3a79bbe33 Mon Sep 17 00:00:00 2001 From: Li ZongYing Date: Fri, 19 Jan 2024 12:18:17 +0800 Subject: [PATCH] channel num setting --- .../com/lizongying/mytv/ChannelFragment.kt | 2 +- .../java/com/lizongying/mytv/InfoFragment.kt | 15 +- .../java/com/lizongying/mytv/MainActivity.kt | 63 ++- .../java/com/lizongying/mytv/MainFragment.kt | 450 +++++++++--------- .../java/com/lizongying/mytv/MainFragment2.kt | 313 ------------ ...MyDialogFragment.kt => SettingFragment.kt} | 19 +- .../main/java/com/lizongying/mytv/TVList.kt | 2 +- .../com/lizongying/mytv/models/TVViewModel.kt | 2 +- app/src/main/res/layout/dialog.xml | 10 +- app/src/main/res/values/strings.xml | 3 +- 10 files changed, 288 insertions(+), 591 deletions(-) delete mode 100644 app/src/main/java/com/lizongying/mytv/MainFragment2.kt rename app/src/main/java/com/lizongying/mytv/{MyDialogFragment.kt => SettingFragment.kt} (61%) diff --git a/app/src/main/java/com/lizongying/mytv/ChannelFragment.kt b/app/src/main/java/com/lizongying/mytv/ChannelFragment.kt index 4e51b57..493cc78 100644 --- a/app/src/main/java/com/lizongying/mytv/ChannelFragment.kt +++ b/app/src/main/java/com/lizongying/mytv/ChannelFragment.kt @@ -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 diff --git a/app/src/main/java/com/lizongying/mytv/InfoFragment.kt b/app/src/main/java/com/lizongying/mytv/InfoFragment.kt index 87f4b60..06c6693 100644 --- a/app/src/main/java/com/lizongying/mytv/InfoFragment.kt +++ b/app/src/main/java/com/lizongying/mytv/InfoFragment.kt @@ -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) } diff --git a/app/src/main/java/com/lizongying/mytv/MainActivity.kt b/app/src/main/java/com/lizongying/mytv/MainActivity.kt index 563c235..cd0a298 100644 --- a/app/src/main/java/com/lizongying/mytv/MainActivity.kt +++ b/app/src/main/java/com/lizongying/mytv/MainActivity.kt @@ -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" } } \ No newline at end of file diff --git a/app/src/main/java/com/lizongying/mytv/MainFragment.kt b/app/src/main/java/com/lizongying/mytv/MainFragment.kt index 566d70c..83a30d7 100644 --- a/app/src/main/java/com/lizongying/mytv/MainFragment.kt +++ b/app/src/main/java/com/lizongying/mytv/MainFragment.kt @@ -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 = 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" } } \ No newline at end of file diff --git a/app/src/main/java/com/lizongying/mytv/MainFragment2.kt b/app/src/main/java/com/lizongying/mytv/MainFragment2.kt deleted file mode 100644 index 42896d1..0000000 --- a/app/src/main/java/com/lizongying/mytv/MainFragment2.kt +++ /dev/null @@ -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 = 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" - } -} \ No newline at end of file diff --git a/app/src/main/java/com/lizongying/mytv/MyDialogFragment.kt b/app/src/main/java/com/lizongying/mytv/SettingFragment.kt similarity index 61% rename from app/src/main/java/com/lizongying/mytv/MyDialogFragment.kt rename to app/src/main/java/com/lizongying/mytv/SettingFragment.kt index 24a9cb5..94c0e94 100644 --- a/app/src/main/java/com/lizongying/mytv/MyDialogFragment.kt +++ b/app/src/main/java/com/lizongying/mytv/SettingFragment.kt @@ -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" } } diff --git a/app/src/main/java/com/lizongying/mytv/TVList.kt b/app/src/main/java/com/lizongying/mytv/TVList.kt index 011921b..33a1dfa 100644 --- a/app/src/main/java/com/lizongying/mytv/TVList.kt +++ b/app/src/main/java/com/lizongying/mytv/TVList.kt @@ -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"), diff --git a/app/src/main/java/com/lizongying/mytv/models/TVViewModel.kt b/app/src/main/java/com/lizongying/mytv/models/TVViewModel.kt index b896bf6..e33ebb1 100644 --- a/app/src/main/java/com/lizongying/mytv/models/TVViewModel.kt +++ b/app/src/main/java/com/lizongying/mytv/models/TVViewModel.kt @@ -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() diff --git a/app/src/main/res/layout/dialog.xml b/app/src/main/res/layout/dialog.xml index 45bf1fc..75c8c46 100644 --- a/app/src/main/res/layout/dialog.xml +++ b/app/src/main/res/layout/dialog.xml @@ -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/" > + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d9b2b04..e74e266 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,4 +1,5 @@ 我的电视 - 频道反转 + 换台反转 + 数字选台 \ No newline at end of file