Я только начинаю Android разработку в Kotlin, и я не совсем уверен, каков правильный подход к этой ситуации.
По сути, я пытаюсь сделать, это иметь ViewPager
, который прокручивает список элементов того же типа. Вид, связанный с каждым элементом, имеет кнопку. Когда я нажимаю кнопку, я хочу запустить новый фрагмент, назовем его iteminfo
. Фрагмент iteminfo
должен использовать задний стек, чтобы вы могли нажать кнопку «Назад» и вернуться к просмотру элемента, на который вы смотрели, прежде чем нажать кнопку.
То, как я сейчас его настроил, таково: this:
-My MainActivity добавляет () мой фрагмент, содержащий ViewPager, в FragmentManager. (Я использую архитектуру с одним действием.)
-Мой фрагмент ViewPager содержит закрытый внутренний класс с PagerAdapter
, который поддерживает список фрагментов элемента. Фрагменты элемента генерируются и добавляются в PagerAdapter при создании фрагмента ViewPager
.
- Каждый из фрагментов элемента имеет свою собственную кнопку. Когда фрагмент создан, кнопка получает onClickListener
.
Вот где я зашел в тупик ...
Пока мне удалось получить Отображаемый фрагмент iteminfo и исчезновение фрагмента элемента, но мой метод был довольно дерзким: я выполнил транзакцию фрагмента, чтобы добавить () фрагмент iteminfo к элементу root моего item_fragment. xml, а затем просто установил видимость другие элементы там ушли. Косметически это приводит меня туда, однако, если я нажму кнопку «Назад», приложение просто закроется. Так что это не поможет.
Я читал, что при переключении между представлениями фрагментов целесообразно использовать один пустой FrameLayout в файле. xml в качестве контейнера фрагментов, а затем добавить / удалите фрагменты из этого, используя FragmentManager. Это имеет смысл для меня ...
Однако я не уверен, как удалить () фрагмент, который находится внутри ViewPager
. AFAIK, вы не можете установить тег фрагмента, если вы не делаете транзакцию фрагмента. Поэтому, если я хочу выполнить replace (), я не знаю, как ссылаться на фрагмент, который я заменяю.
Так же, как «Радуйся, Мария», я попытался просто заменить весь 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()
}
}
}
frag_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)
}
}
}
frag_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 и фрагмент_инфо. xml может быть чем угодно, неважно, что они для целей моего вопроса.