kotlin - 2个Fragment实现左右显示,左边列表,右边详情,平板横、竖屏切换(一)
2026/8/13 8:29:02 网站建设 项目流程

kotlin -2个Fragment实现左右显示,左边列表,右边详情,平板横、竖屏切换

(要使用平板测试)平板横屏:左右fragment实现分屏效果,平板竖屏:只显示左边的fragment,点击才显示右边fragment
屏幕旋转,会销毁重新创建,执行onCreate方法。
在AndroidManifest.xml配置android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboardHidden|navigation"属性,只调用onConfigurationChanged方法
fragment的
add方法
如果新打开一个activity,该fragment只回调onStop()方法,没有调用onDestroy()方法。
如果popBackStack或者finish,会回调onStop()和onDestroy()方法
replace方法:旧的fragment执行onDestroy()方法,然后新建一个fragment,执行onViewCreated()方法。

package com.example.androidkotlindemo2.pad.leftright import android.content.Intent import android.content.res.Configuration import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.example.androidkotlindemo2.R import com.example.androidkotlindemo2.utils.LogUtils /** * Author : wn * Email : maoning20080809@163.com * Date : 2025/8/30 21:41 * Description : (要使用平板测试)平板横屏:左右fragment实现分屏效果,平板竖屏:只显示左边的fragment,点击才显示右边fragment * 屏幕旋转,会销毁重新创建,执行onCreate方法。 * 在AndroidManifest.xml配置android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboardHidden|navigation"属性,只调用onConfigurationChanged方法 * fragment的 * add方法, * 如果新打开一个activity,该fragment只回调onStop()方法,没有调用onDestroy()方法。 * 如果popBackStack或者finish,会回调onStop()和onDestroy()方法 * replace:旧的fragment执行onDestroy()方法,然后新建一个fragment,执行onViewCreated()方法。 */ classLRFragmentActivity: AppCompatActivity() { //平板横屏 private var isLandscape: Boolean = false override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.lr_fragment_main) LogUtils.d("LeftRightMainActivity onCreate"); // 初始化显示列表Fragment if (savedInstanceState == null) { supportFragmentManager.beginTransaction() .replace(R.id.fragment_list_container, LRListFragment()) .commit() } checkOrientation() } //检查横、竖屏 private fun checkOrientation() { val orientation = resources.configuration.orientation isLandscape = orientation == Configuration.ORIENTATION_LANDSCAPE } fun setOnItemClick(position: Int, lrItem: LRItem) { if(position < 3){if(isLandscape){ //平板横屏,左右显示fragment showItemDetailReplace(lrItem) } else { //平板竖屏,使用新的Activity显示 startRightActivity(lrItem) }} else if(position < 6){ //只适配平板横屏效果 showItemDetailAdd(lrItem) } else { showItemNewActivity(lrItem) } } //竖屏打开新的Activity fun startRightActivity(lrItem: LRItem){ val intent = Intent(this, LRRightActivity::class.java) intent.putExtra("lr_item", lrItem) startActivity(intent) } //使用replace方法 fun showItemDetailReplace(lrItem: LRItem) { val detailFragment = LRDetailReplaceFragment.newInstance(lrItem) supportFragmentManager.beginTransaction() .replace(R.id.fragment_detail_container, detailFragment) .commit() } //使用add方法, 只回调onStop方法,不回调onDestroy方法 fun showItemDetailAdd(LRItem: LRItem) { val detailNewFragment = LRDetailAddFragment.newInstance(LRItem) supportFragmentManager.beginTransaction().add(R.id.fragment_detail_container, detailNewFragment) .addToBackStack("detail_new_fragment") // 添加这行才能popBackStack回退.commit() } //屏幕旋转,移除fragment fun removeDetailFragment(){ val detailFragment = supportFragmentManager.findFragmentById(R.id.fragment_detail_container) if(detailFragment != null){ supportFragmentManager.beginTransaction() .remove(detailFragment) .commit() } } //使用add方法, 只回调onStop方法,不回调onDestroy方法 fun showItemNewActivity(LRItem: LRItem) { startActivity(Intent(this, LRNewActivity::class.java)) } override funonConfigurationChanged(newConfig: Configuration) { super.onConfigurationChanged(newConfig) LogUtils.i("LeftRightMainActivity onConfigurationChanged"); checkOrientation() removeDetailFragment() } override fun onStop() { super.onStop() LogUtils.d("LeftRightMainActivity onDestroy") } override fun onDestroy() { super.onDestroy() LogUtils.d("LeftRightMainActivity onDestroy") } override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) LogUtils.i("LeftRightMainActivity onNewIntent") } }
package com.example.androidkotlindemo2.pad.leftright import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.example.androidkotlindemo2.R import com.example.androidkotlindemo2.utils.LogUtils /** * Author : wn * Email : maoning20080809@163.com * Date : 2025/8/30 21:41 * Description : */ classLRListFragment: Fragment(){ private lateinit var recyclerView: RecyclerView private lateinit var adapter: LRAdapter private var LRItemList = mutableListOf<LRItem>() override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { return inflater.inflate(R.layout.lr_fragment_item_list, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) setupRecyclerView(view) loadItems() } private fun setupRecyclerView(view: View) { recyclerView = view.findViewById(R.id.recycler_view) adapter = LRAdapter(LRItemList, object : LROnItemClickInter{ override fun setOnItemClick(position: Int, lrItem: LRItem) { // 通知Activity显示详情 (activity as? LRFragmentActivity)?.setOnItemClick(position,lrItem) } override fun setOnLongClickListener(position: Int, lrItem: LRItem) { LogUtils.i("长按:${position}") } }) recyclerView.layoutManager = LinearLayoutManager(requireContext()) recyclerView.adapter = adapter recyclerView.addItemDecoration( DividerItemDecoration(requireContext(), LinearLayoutManager.VERTICAL) ) } private fun loadItems() { for(i in 1 .. 20){ LRItemList.add(LRItem(i, "项目${i}", "这是第${i}个项目的详细描述")) } adapter.notifyDataSetChanged() } }
package com.example.androidkotlindemo2.pad.leftright import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.Button import android.widget.TextView import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment import com.example.androidkotlindemo2.MyApp import com.example.androidkotlindemo2.R import com.example.androidkotlindemo2.utils.LogUtils /** * Author : wn * Email : maoning20080809@163.com * Date : 2025/8/30 21:45 * Description : 新的详情,使用fragment的add方法调用,只会调用onStop() */ classLRDetailAddFragment: Fragment() { companion object { private const val ARG_ITEM = "item" fun newInstance(LRItem: LRItem): LRDetailAddFragment { val fragment = LRDetailAddFragment() val args = Bundle().apply { putParcelable(ARG_ITEM, LRItem) } fragment.arguments = args return fragment } } override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { return inflater.inflate(R.layout.lr_fragment_item_detail, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) LogUtils.w("LRDetailAddFragment onViewCreated ----------------------------") LogUtils.w("LRDetailAddFragment onViewCreated() ${this}") arguments?.getParcelable<LRItem>(ARG_ITEM)?.let { item -> displayItemDetails(view, item) } view.findViewById<Button>(R.id.lr_item_details_back).visibility = View.VISIBLE //返回 view.findViewById<Button>(R.id.lr_item_details_back).setOnClickListener { LogUtils.i("LRDetailNewFragment返回") requireActivity().supportFragmentManager.popBackStack() } view.findViewById<Button>(R.id.lr_item_details_finish).visibility = View.VISIBLE //关闭 - view.findViewById<Button>(R.id.lr_item_details_finish).setOnClickListener { LogUtils.i("LRDetailNewFragment关闭") requireActivity().finish() } } override fun onStart() { super.onStart() LogUtils.w("LRDetailAddFragment onStart() ${this}") } override fun onResume() { super.onResume() LogUtils.w("LRDetailAddFragment onResume() ${this}") } override fun onPause() { super.onPause() LogUtils.w("LRDetailAddFragment onPause() ${this}") } override fun onStop() { super.onStop() LogUtils.w("LRDetailAddFragment onStop() ${this}") } override fun onDestroy() { super.onDestroy() LogUtils.w("LRDetailAddFragment onDestroy() ${this}") } private fun displayItemDetails(view: View, LRItem: LRItem) { view.findViewById<TextView>(R.id.title_text_view).text = LRItem.title view.findViewById<TextView>(R.id.description_text_view).text = "新页面:" + LRItem.description view.findViewById<TextView>(R.id.description_text_view).setTextColor(ContextCompat.getColor(MyApp.myApp,R.color.blue)) view.findViewById<TextView>(R.id.description_text_view).setTextSize(30f) } }
package com.example.androidkotlindemo2.pad.leftright import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.Button import android.widget.TextView import androidx.fragment.app.Fragment import com.example.androidkotlindemo2.R import com.example.androidkotlindemo2.utils.LogUtils /** * Author : wn * Email : maoning20080809@163.com * Date : 2025/8/30 21:45 * Description : 使用replace方法,会调用onStop()和onDestroy()方法, */ classLRDetailReplaceFragment: Fragment() { companion object { private const val ARG_ITEM = "item" fun newInstance(LRItem: LRItem): LRDetailReplaceFragment { val fragment = LRDetailReplaceFragment() val args = Bundle().apply { putParcelable(ARG_ITEM, LRItem) } fragment.arguments = args return fragment } } override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { return inflater.inflate(R.layout.lr_fragment_item_detail, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) LogUtils.i("LRDetailReplaceFragment onViewCreated ----------------------------") LogUtils.d("LRDetailReplaceFragment onViewCreated() ${this}") arguments?.getParcelable<LRItem>(ARG_ITEM)?.let { item -> displayItemDetails(view, item) } //返回 view.findViewById<Button>(R.id.lr_item_details_back).visibility = View.GONE view.findViewById<Button>(R.id.lr_item_details_finish).visibility = View.GONE } override fun onStart() { super.onStart() LogUtils.d("LRDetailReplaceFragment onStart() ${this}") } override fun onResume() { super.onResume() LogUtils.d("LRDetailReplaceFragment onResume() ${this}") } override fun onPause() { super.onPause() LogUtils.d("LRDetailReplaceFragment onPause() ${this}") } override fun onStop() { super.onStop() LogUtils.d("LRDetailReplaceFragment onStop() ${this}") } override fun onDestroy() { super.onDestroy() LogUtils.d("LRDetailReplaceFragment onDestroy() ${this}") } private fun displayItemDetails(view: View, LRItem: LRItem) { view.findViewById<TextView>(R.id.title_text_view).text = LRItem.title view.findViewById<TextView>(R.id.description_text_view).text = LRItem.description } }
package com.example.androidkotlindemo2.pad.leftright import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.LinearLayout import android.widget.TextView import androidx.cardview.widget.CardView import androidx.core.content.ContextCompat import androidx.recyclerview.widget.RecyclerView import com.example.androidkotlindemo2.MyApp import com.example.androidkotlindemo2.R /** * Author : wn * Email : maoning20080809@163.com * Date : 2025/8/30 21:42 * Description : */ classLRAdapter( private val itemList: List<LRItem>, private val listener: LROnItemClickInter ) : RecyclerView.Adapter<LRAdapter.ItemViewHolder>() { var selectedPosition = -1 inner class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val titleTextView: TextView = itemView.findViewById(R.id.title_text_view) val container: LinearLayout = itemView.findViewById(R.id.item_container) } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { val view = LayoutInflater.from(parent.context) .inflate(R.layout.lr_fragment_item, parent, false) return ItemViewHolder(view) } override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { val lrItem = itemList[position] holder.titleTextView.text = lrItem.title holder.container.setOnClickListener { listener.setOnItemClick(position, lrItem) selectedPosition = position notifyDataSetChanged() } holder.container.setOnLongClickListener { listener.setOnLongClickListener(position, lrItem) true } if(selectedPosition == position){ holder.container.setBackgroundColor(ContextCompat.getColor(MyApp.myApp, R.color.lr_item_selected_bg)) } else { holder.container.setBackgroundColor(ContextCompat.getColor(MyApp.myApp, R.color.lr_item_default_bg)) } } override fun getItemCount(): Int = itemList.size }
package com.example.androidkotlindemo2.pad.leftright import android.os.Bundle import android.widget.Button import androidx.appcompat.app.AppCompatActivity import com.example.androidkotlindemo2.R import com.example.androidkotlindemo2.utils.LogUtils /** * Author : wn * Email : maoning20080809@163.com * Date : 2025/9/6 13:04 * Description : 打开新的页面 */ classLRNewActivity: AppCompatActivity(){ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.lr_activity_new) LogUtils.e("LRNewActivity onViewCreated ----------------------------") findViewById<Button>(R.id.lr_activity_new_close).setOnClickListener { finish() } } override fun onCreateDescription(): CharSequence? { return super.onCreateDescription() } override fun onDestroy() { super.onDestroy() LogUtils.e("LRNewActivity onDestroy ----------------------------") } }
package com.example.androidkotlindemo2.pad.leftright /** * Author : wn * Email : maoning20080809@163.com * Date : 2025/9/6 9:46 * Description : */ interfaceLROnItemClickInter{ //点击 fun setOnItemClick(position: Int, lrItem: LRItem) //长按 fun setOnLongClickListener(position: Int, lrItem: LRItem) }
package com.example.androidkotlindemo2.pad.leftright import android.os.Bundle import android.widget.Button import androidx.appcompat.app.AppCompatActivity import com.example.androidkotlindemo2.R import com.example.androidkotlindemo2.utils.LogUtils /** * Author : wn * Email : maoning20080809@163.com * Date : 2025/9/6 13:04 * Description : 在Activity中显示右边的fragment */ classLRRightActivity: AppCompatActivity(){ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.lr_activity_right) val lrItem = intent.getParcelableExtra<LRItem>("lr_item") as LRItem if (savedInstanceState == null) { supportFragmentManager.beginTransaction() .replace(R.id.fragment_right_container, LRDetailReplaceFragment.newInstance(lrItem)) .commit() } } }
package com.example.androidkotlindemo2.pad.leftright import android.os.Parcel import android.os.Parcelable /** * Author : wn * Email : maoning20080809@163.com * Date : 2025/8/30 21:41 * Description : */ data classLRItem( val id: Int, val title: String, val description: String, val imageUrl: String? = null ) : Parcelable { constructor(parcel: Parcel) : this( parcel.readInt(), parcel.readString() ?: "", parcel.readString() ?: "", parcel.readString() ) override fun writeToParcel(parcel: Parcel, flags: Int) { parcel.writeInt(id) parcel.writeString(title) parcel.writeString(description) parcel.writeString(imageUrl) } override fun describeContents(): Int { return 0 } companion object CREATOR : Parcelable.Creator<LRItem> { override fun createFromParcel(parcel: Parcel): LRItem { return LRItem(parcel) } override fun newArray(size: Int): Array<LRItem?> { return arrayOfNulls(size) } } }
lr_fragment_main.xml布局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" android:weightSum="2"> <FrameLayout android:id="@+id/fragment_list_container" android:layout_width="300dp" android:layout_height="match_parent" /> <TextView android:layout_width="1dp" android:layout_height="match_parent" android:background="@color/blue"/> <FrameLayout android:id="@+id/fragment_detail_container" android:layout_width="match_parent" android:layout_height="match_parent"/> </LinearLayout>
lr_fragment_item_list.xml布局
<?xml version="1.0" encoding="utf-8"?> <androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="8dp" />
lr_fragment_item_detail.xml布局
<?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/gray_e5e5e5" android:padding="16dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <androidx.appcompat.widget.AppCompatButton android:id="@+id/lr_item_details_finish" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAllCaps="false" android:textSize="30sp" android:textColor="@color/green" android:text="关闭finish"/> <androidx.appcompat.widget.AppCompatButton android:id="@+id/lr_item_details_back" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAllCaps="false" android:textSize="30sp" android:textColor="@color/green" android:text="返回"/> <TextView android:id="@+id/title_text_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="24sp" android:textStyle="bold" android:layout_marginBottom="16dp" /> <TextView android:id="@+id/description_text_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="16sp" /> <TextView android:id="@+id/description_tip" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="@color/red" android:text="1-3 使用 fragment 的 replace \n 4-6使用 fragment 的add() \n 其他使用打开activity" android:textSize="26sp" /> </LinearLayout> </ScrollView>
lr_fragment_item.xml布局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/item_container" android:background="@drawable/lr_click_item_bg" android:clickable="true" android:focusable="true" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="4dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="16dp" android:orientation="vertical"> <TextView android:id="@+id/title_text_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="18sp" android:textStyle="bold" /> </LinearLayout> </LinearLayout>
lr_activity_new.xml布局
<?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/gray_e5e5e5" android:padding="16dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <androidx.appcompat.widget.AppCompatButton android:id="@+id/lr_activity_new_close" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAllCaps="false" android:text="关闭"/> <TextView android:id="@+id/title_text_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="24sp" android:textStyle="bold" android:text="新的Activity" android:layout_marginBottom="16dp" /> <TextView android:id="@+id/description_text_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="16sp" /> </LinearLayout> </ScrollView>
lr_activity_right.xml布局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/gray_e5e5e5" android:orientation="vertical"> <FrameLayout android:id="@+id/fragment_right_container" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
drawable:
lr_click_item_bg.xml
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@color/lr_item_selected_bg" android:state_selected="true"/> <item android:drawable="@color/lr_item_selected_bg" android:state_pressed="true"/> <item android:drawable="@color/lr_item_default_bg"/> </selector>
<color name="lr_item_default_bg">#FFFFFF</color> <color name="lr_item_selected_bg">#FF00FF</color>
<activity android:name=".pad.leftright.LRFragmentActivity"android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboardHidden|navigation"/> <activity android:name=".pad.leftright.LRNewActivity"/> <activity android:name=".pad.leftright.LRRightActivity"/>

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询