Как заменить fragment внутри ViewPager и сменить toolbar?
Нашел в одном из приложений интересную фичу, хочу повторить ее, суть в том что есть приложение с ViewPager и TabLayout и кучей фрагментов внутри.
На первом фрагменте есть кнопка 
, по ее нажатию фрагмент заменяется на другой 
, при этом убирается ads_banner и заменяется toolbar, а при свайпе вправо и обратно устанавливается фрагмент1, подскажите пожалуйста, как такое можно сделать. Вот что я уже написал activity_main.xml
<?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:id="@+id/mainlayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:fitsSystemWindows="true"
android:orientation="vertical"
tools:context=".MainActivity">
<com.google.android.gms.ads.AdView
android:id="@+id/adView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:background="@color/transparent"
app:adSize="SMART_BANNER"
app:adUnitId="@string/banner_key"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
style="@style/MyToolbar"
android:layout_width="match_parent"
android:layout_height="35dp"
android:layout_marginTop="2dp"
android:gravity="center"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/adView"
app:popupTheme="@style/AppTheme.PopupOverlay">
<TextView
android:id="@+id/toolbar_txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:fontFamily="@font/sf_pro_display_regular"
android:textColor="@color/black"
android:textSize="24sp"
tools:layout_editor_absoluteX="206dp"
tools:layout_editor_absoluteY="7dp" />
</androidx.appcompat.widget.Toolbar>
<androidx.viewpager.widget.ViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/tab_layout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/toolbar" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="#fff"
android:elevation="6dp"
android:minHeight="?attr/actionBarSize"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:tabBackground="@drawable/tab_color_selector"
app:tabIndicatorColor="#2196F3"
app:tabIndicatorGravity="top"
app:tabIndicatorHeight="4dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity
class MainActivity : AppCompatActivity() {
private var mAdView: AdView? = null
@SuppressLint("ResourceType")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val adRequest = AdRequest.Builder().build()
mAdView = findViewById(R.id.adView)
mAdView!!.loadAd(adRequest)
initTab()
}
fun initTab() {
tab_layout.addTab(tab_layout.newTab().setIcon(R.drawable.image1)
tab_layout.addTab(tab_layout.newTab().setIcon(R.drawable.image2)
tab_layout.addTab(tab_layout.newTab().setIcon(R.drawable.image3)
tab_layout.tabGravity = TabLayout.GRAVITY_FILL
val adapter = MyPagerAdapter(supportFragmentManager, tab_layout.tabCount)
pager.adapter = adapter
pager.offscreenPageLimit = 2
pager.addOnPageChangeListener(TabLayout.TabLayoutOnPageChangeListener(tab_layout))
tab_layout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab) {
pager.currentItem = tab.position
if (tab.position == 0) {
tab_layout.getTabAt(0)!!.setIcon(R.drawable.image1_focus)
}
if (tab.position == 1) {
tab_layout.getTabAt(1)!!.setIcon(R.drawable.image2_focus)
}
if (tab.position == 2) {
tab_layout.getTabAt(2)!!.setIcon(R.drawable.image3_focus)
}
}
override fun onTabUnselected(tab: TabLayout.Tab) {
if (tab.position == 0) tab_layout.getTabAt(0)!!.setIcon(R.drawable.image1)
if (tab.position == 1) tab_layout.getTabAt(1)!!.setIcon(R.drawable.image2)
if (tab.position == 2) tab_layout.getTabAt(2)!!.setIcon(R.drawable.image3)
}
override fun onTabReselected(tab: TabLayout.Tab) {
}
})
}
MyPagerAdapter
class MyPagerAdapter(fm: FragmentManager, internal var mNumOfTabs: Int) : FragmentStatePagerAdapter(fm) {
override fun getItem(position: Int): Fragment {
when (position) {
0 -> {
return RootFragment()
// return Fragment1()
}
1 -> {
return Fragment2()
}
2 -> {
return Fragment3()
}
}
}
override fun getCount(): Int {
return mNumOfTabs
}
}
Fragment1
class Fragment1: Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.fr1, container, false)
return view
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
btnfr1.setOnClickListener {
val trans = fragmentManager!!.beginTransaction()
trans.replace(R.id.root_frame, Fragment4())
trans.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
trans.addToBackStack(null)
trans.commit()
}
}
В Fragment1 только кнопка для вызова Fragment4, сам Fragment4 просто с текстом
RootFragment
class RootFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.root_fragment, container, false)
val transaction = fragmentManager!!.beginTransaction()
transaction.replace(R.id.root_frame, Fragment1())
transaction.commit()
return view
}
}
root_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/root_frame" >
</FrameLayout>
Пробовал сделать как здесь https://www.codexpedia.com/android/android-viewpager-fragment-swap/ получилось заменить Fragment1 на Fragment4, но я не знаю как сбросить Fragment4 при свайпе и не понимаю как заменить Toolbar и убрать ads
Ответы (1 шт):
Вся задача здесь заключается в управлении разметкой Activity из фрагмента. В целом это не так сложно.
Вам нужно создать в вашей Activity с ViewPager-ом контейнеры для ViewPager, банеров и Toolbar-а. Это банальная XML разметка.
Вы создаете интерфейс что-то вроде такого:
interface ActivityController { fun showBanner(isShow: Boolean) fun showToolbar(isShow: Boolean, toolbarTitle: String) }И реализовать этот интерфейс в Activity.
Получить экземпляр этого интерфейса в фрагменте. Тут точно не подскажу, но скорее всего вы сможете его получить у фрагмента в методе:
override fun onAttach(context: Context) { super.onAttach(context); if (context is ActivityController) { this.activityController = (ActivityController) context; } else { throw new IllegalStateException("Activity must implement ActivityController"); } }Скорее всего контекстом вашего фрагмента будет именно этот context если он будет реализован в вашей Activity. Почему скорее всего? Я не до конца уверен, что через ViewPager это будет так, но т.к. ViewPager хранит в себе контекст Activity в которой он есть, то очевидно, что это утверждение должно работать.
С другой стороны вам возможно и не нужен этот колбек во Fragment если вы можете в самом ViewPager понять, какое действие вам нужно выполнить. Условно если вы во ViewPager в
onPageSelected()видите, что открылся FragmentA и вам надо скрыть Toolbar то просто вызываете этот метод из ViewPager-a.Собственно уже в Activity в методах
showBanner(isShow: Boolean)иshowToolbar(isShow: Boolean, toolbarTitle: String)вы и показываете нужные вам элементы UI.
Что касается второго вопроса, я не совсем понял его.