【发布时间】:2020-03-03 05:33:48
【问题描述】:
我刚刚开始使用 Kotlin 进行 Android 开发,我不太确定解决这种情况的正确方法是什么。
基本上我想要做的是有一个ViewPager 滚动浏览相同类型的项目列表。与每个项目关联的视图都有一个按钮。当我按下按钮时,我想启动一个新片段,我们称之为iteminfo。 iteminfo 片段应该使用后退堆栈,以便您可以点击后退按钮并返回到您在点击按钮之前查看的项目视图。
我现在的设置方式是这样的:
-My MainActivity 将包含 ViewPager 的片段添加()到 FragmentManager。 (我打算采用单一活动架构。)
-我的 ViewPager 片段包含一个带有PagerAdapter 的私有内部类,该类维护一个项目片段列表。在创建 ViewPager 片段时会生成项目片段并将其添加到 PagerAdapter。
-每个项目片段都有自己的按钮。创建片段时,按钮会获得一个onClickListener。
这是我遇到了一些死胡同的地方......
到目前为止,我已经设法让 iteminfo 片段显示并让 item 片段消失,但我的方法非常笨拙:我执行了一个片段事务,将 iteminfo 片段添加()到我的 item_fragment 的根元素。 xml,然后将其中其他元素的可见性设置为 GONE。从外观上看,这让我到了那里,但是如果我点击后退按钮,应用程序就会退出。所以这不会削减它。
我已经读过,在片段视图之间切换时,使用 .xml 文件中的单个空 FrameLayout 作为片段容器,然后使用 FragmentManager 添加/删除片段是一个很好的设计。这对我来说很有意义......
但是,我不确定如何删除()ViewPager 内的片段。 AFAIK 除非您正在进行片段交易,否则您无法设置片段的标签。所以如果我想执行replace(),我不知道如何引用我要替换的片段。
就像 Hail-Mary 一样,我尝试只替换整个 ViewPager 片段(因为这是通过片段事务添加到 MainActivity 中的,所以我能够对其进行标记),但由于某种原因,这只会产生 NPE。子片段不能替换其父片段是有道理的,尽管我不能 100% 确定它为什么是 NPE。
无论如何,非常感谢您能给我带来的任何启发。
编辑:在下面添加了相关代码。
MainActivity.kt:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val currentFragment = supportFragmentManager
.findFragmentById(R.id.fragment_container)
if (currentFragment == null) {
val fragment = ItemPagerFragment.newInstance()
supportFragmentManager
.beginTransaction()
.add(R.id.fragment_container, fragment, "viewPager")
.commit()
}
}
}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
ItemPagerFragment.kt:
class ItemPagerFragment: Fragment() {
private lateinit var viewPager: ViewPager
private lateinit var pagerAdapter: ItemPagerAdapter
private val itemListViewModel: ItemListViewModel by lazy {
ViewModelProviders.of(this).get(ItemListViewModel::class.java)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_item_pager, container, false)
viewPager = view.findViewById(R.id.item_viewpager) as ViewPager
pagerAdapter = ItemPagerAdapter(getChildFragmentManager())
val items = itemListViewModel.items
for (item in items){
pagerAdapter.addFrag(ItemFragment.newInstance(item))
}
viewPager.adapter = pagerAdapter
return view
}
private inner class ItemPagerAdapter(fm: FragmentManager)
: FragmentStatePagerAdapter(fm)
{
private val itemFragmentList: MutableList<ItemFragment> = ArrayList()
override fun getItem(i: Int): Fragment {
return itemFragmentList[i]
}
override fun getCount() = itemFragmentList.size
fun addFrag(f: ItemFragment){
itemFragmentList.add(f)
}
}
companion object {
fun newInstance(): ItemPagerFragment {
return ItemPagerFragment()
}
}
}
fragment_item_pager.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.viewpager.widget.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/item_viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
ItemFragment.kt:
class ItemFragment(i: Item): Fragment() {
private var item: Item = i;
private lateinit var infoButton: Button
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_item, container, false)
infoButton = view.findViewById(R.id.info_button) as Button
infoButton.setOnClickListener{
val fragment: InfoFragment = InfoFragment.newInstance(item)
val fragmentManager: FragmentManager = childFragmentManager
val fragmentTransaction = fragmentManager.beginTransaction()
// this is where I have been having no success
// and know my approach is certainly wrong/confused
fragmentTransaction.replace(R.id.item_frame, fragment)
fragmentTransaction.addToBackStack(null)
fragmentTransaction.commit()
}
return view
}
companion object {
fun newInstance(i: Item): ItemFragment {
return ItemFragment(i)
}
}
}
fragment_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/item_frame"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="8dp">
<Button
android:id="@+id/info_button"
android:layout_gravity="center|bottom"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/some_string"
/>
</FrameLayout>
InfoFragment.kt 和 fragment_info.xml 可以是任何东西,就我的问题而言,它们是什么并不重要。
【问题讨论】:
-
包含您所做的代码,然后任何人都可以提供解决方案。
标签: android android-fragments kotlin android-viewpager