英文:
Kotlin - Open other fragment on click CardView in another fragment
问题
Sure, here's the translated version of the code:
1. MainActivity.kt
import ...
class MainActivity : AppCompatActivity() {
private lateinit var appBarConfiguration: AppBarConfiguration
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val toolbar: Toolbar = findViewById(R.id.toolbar)
setSupportActionBar(toolbar)
val fab: FloatingActionButton = findViewById(R.id.fab)
fab.setOnClickListener { view ->
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show()
}
val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
val navView: NavigationView = findViewById(R.id.nav_view)
val navController = findNavController(R.id.nav_host_fragment)
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
appBarConfiguration = AppBarConfiguration(setOf(
R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow), drawerLayout)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
// Inflate the menu; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.main, menu)
return true
}
override fun onSupportNavigateUp(): Boolean {
val navController = findNavController(R.id.nav_host_fragment)
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}
}
2. HomeFragment.kt
import ...
class HomeFragment : Fragment() {
private lateinit var homeViewModel: HomeViewModel
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
homeViewModel =
ViewModelProviders.of(this).get(HomeViewModel::class.java)
val root = inflater.inflate(R.layout.fragment_home, container, false)
val myCard1 = root.findViewById(R.id.cardOpenGallery) as CardView
myCard1.setOnClickListener(object : View.OnClickListener {
override fun onClick(v: View?) {
val fragment = GalleryFragment()
val transaction = requireActivity().supportFragmentManager.beginTransaction()
transaction.replace(R.id.nav_host_fragment, fragment)
transaction.addToBackStack(null)
transaction.commit()
}
})
return root
}
}
3. GalleryFragment.kt
import ...
class GalleryFragment : Fragment() {
private lateinit var galleryViewModel: GalleryViewModel
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
galleryViewModel =
ViewModelProviders.of(this).get(GalleryViewModel::class.java)
val root = inflater.inflate(R.layout.fragment_gallery, container, false)
val textView: TextView = root.findViewById(R.id.text_gallery)
galleryViewModel.text.observe(viewLifecycleOwner, Observer {
textView.text = it
})
return root
}
}
4. SlideshowFragment.kt
import ...
class SlideshowFragment : Fragment() {
private lateinit var slideshowViewModel: SlideshowViewModel
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
slideshowViewModel =
ViewModelProviders.of(this).get(SlideshowViewModel::class.java)
val root = inflater.inflate(R.layout.fragment_slideshow, container, false)
val textView: TextView = root.findViewById(R.id.text_slideshow)
slideshowViewModel.text.observe(viewLifecycleOwner, Observer {
textView.text = it
})
return root
}
}
This code will allow you to open the GalleryFragment
when the CardView in HomeFragment
is clicked.
英文:
I'm new in Android Studio and having trouble opening fragment on click CardView in other fragment. I have Navigation View in layout and navigate to other fragment (fragment_home, fragment_gallery, fragment_slideshow, and other fragment layout.). But I have to create CardView in fragment_home to click for open some fragment layout (Gallery and Slideshow).
I have layout:
1. fragment_home.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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.home.HomeFragment">
<androidx.cardview.widget.CardView
android:id="@+id/cardOpenGallery"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_margin="20dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="80dp"
android:background="#ccc">
<TextView
android:id="@+id/textOpenGallery"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:textAlignment="center"
android:textSize="30sp"
android:textColor="#000"
android:text="Open Gallery"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
2. fragment_gallery.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.gallery.GalleryFragment">
<!-- other layout element here -->
</FrameLayout>
3. fragment_slideshow.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.gallery.SlideshowFragment">
<!-- other layout element here -->
</FrameLayout>
And Kotlin code,
1. MainActivity.kt
import ...
class MainActivity : AppCompatActivity() {
private lateinit var appBarConfiguration: AppBarConfiguration
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val toolbar: Toolbar = findViewById(R.id.toolbar)
setSupportActionBar(toolbar)
val fab: FloatingActionButton = findViewById(R.id.fab)
fab.setOnClickListener { view ->
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show()
}
val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
val navView: NavigationView = findViewById(R.id.nav_view)
val navController = findNavController(R.id.nav_host_fragment)
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
appBarConfiguration = AppBarConfiguration(setOf(
R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow), drawerLayout)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
// Inflate the menu; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.main, menu)
return true
}
override fun onSupportNavigateUp(): Boolean {
val navController = findNavController(R.id.nav_host_fragment)
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}
}
2. HomeFragment.kt
import ...
class HomeFragment : Fragment() {
private lateinit var homeViewModel: HomeViewModel
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
homeViewModel =
ViewModelProviders.of(this).get(HomeViewModel::class.java)
val root = inflater.inflate(R.layout.fragment_home, container, false)
//I have problem here-----
val myCard1 = root.findViewById(R.id.cardOpenGallery) as CardView
myCard1.setOnClickListener(object : View.OnClickListener {
override fun onClick(v: View?) {
inflater.inflate(R.layout.fragment_gallery, container, false)
}
})
return root
}
}
3. GalleryFragment.kt
import ...
class GalleryFragment : Fragment() {
private lateinit var galleryViewModel: GalleryViewModel
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
galleryViewModel =
ViewModelProviders.of(this).get(GalleryViewModel::class.java)
val root = inflater.inflate(R.layout.fragment_gallery, container, false)
val textView: TextView = root.findViewById(R.id.text_gallery)
galleryViewModel.text.observe(viewLifecycleOwner, Observer {
textView.text = it
})
return root
}
}
4. SlideshowFragment.kt
import ...
class SlideshowFragment : Fragment() {
private lateinit var slideshowViewModel: SlideshowViewModel
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
slideshowViewModel =
ViewModelProviders.of(this).get(SlideshowViewModel::class.java)
val root = inflater.inflate(R.layout.fragment_slideshow, container, false)
val textView: TextView = root.findViewById(R.id.text_slideshow)
slideshowViewModel.text.observe(viewLifecycleOwner, Observer {
textView.text = it
})
return root
}
}
How to implement action for CardView click to open other fragment?, Please help and Thank for your any solution. Thanks.
答案1
得分: 0
你需要在这里打开另一个片段。为此,您需要用所需的片段替换MainActivity中的片段容器。
将这个
myCard1.setOnClickListener(object : View.OnClickListener {
override fun onClick(v: View?) {
inflater.inflate(R.layout.fragment_gallery, container, false)
}
})
替换为这个
myCard1.setOnClickListener(object : View.OnClickListener {
override fun onClick(v: View?) {
((Activity) getContext).supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, GalleryFragment())
.commit()
}
})
我希望这对您有所帮助。
祝您编码愉快
英文:
You need to open another fragment here. For this you need to replace the fragment container in MainActivity with the desired fragment.
Replace this
myCard1.setOnClickListener(object : View.OnClickListener {
override fun onClick(v: View?) {
inflater.inflate(R.layout.fragment_gallery, container, false)
}
})
with this
myCard1.setOnClickListener(object : View.OnClickListener {
override fun onClick(v: View?) {
((Activity) getContext).supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, GalleryFragment())
.commit()
}
})
I hope this will work for you.
Happy Coding
答案2
得分: 0
你只是试图在你的HomeFragment中添加fragment_gallery。我不认为这是正确的做法。尽管如此,我会提供我使用的方法。
在你的 activity_main.xml 文件中添加一个 FrameLayout,它将用于添加/替换所需的fragment。
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
现在在你的 Activity 中创建以下函数。它将帮助你替换所需的 fragment。
private fun replaceFragment(fragmentInstance: Fragment) {
supportFragmentManager
.beginTransaction()
.addToBackStack(fragmentInstance.javaClass.canonicalName) // 可选
.replace(R.id.container, fragmentInstance)
.commit()
}
现在,在 onCreate 中加载 homeFragment(因为它是你要显示的第一个 fragment)。
override fun onCreate(savedInstanceState: Bundle?) {
val fragment = HomeFragment()
replaceFragment(fragment)
}
此阶段,你将能够成功加载 homeFragment。现在下一步是创建一个回调接口。每次你点击 homeFragment 中的任何卡片,你只需要将所需的信息传递回 MainActivity。将加载 fragment 的责任留给 Activity 是一个很好的做法。
interface OnCardClickListener {
fun onCardClick(fragment: Fragment)
}
在 MainActivity 中实现此监听器。
class MainActivity : OnCardClickListener {
这将覆盖 onCardClick。在 onCardClick 内部调用 replace 方法。
override fun onCardClick(fragment: Fragment) {
replaceFragment(fragment)
}
在 HomeFragment 中,创建 OnCardClickListener 的实例。
var listener: OnCardClickListener? = null
然后在 onAttach 中。
override fun onAttach(context: Context) {
super.onAttach(context)
listener = context as OnCardClickListener
}
到目前为止,我们已经实现了加载 fragment 所需的机制。现在只剩下一个最后的步骤,即在点击 cardView 时打开所需的 fragment。为此,请按照以下步骤操作:
myCard1.setOnClickListener {
listener?.onCardClick(GalleryFragment())
}
// 如果还有另一个可用的卡片。
myCard2.setOnClickListener {
listener?.onCardClick(SlideshowFragment())
}
英文:
You're just trying to inflate the fragment_gallery inside your homeFragment. I don't think it's the right way to do it. Although, I'll suggest the approach I use.
Inside your activity_main.xml add the FrameLayout. which will be useful to add/replace the desired fragment into it.
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
Now in your Activity, create the following function. It will help you to replace the desired fragment.
private fun replaceFragment(fragmentInstance: Fragment) {
supportFragmentManager
.beginTransaction()
.addToBackStack(fragmentInstance.javaClass.canonicalName)//optional
.replace(R.id.container, fragmentInstance)
.commit()
}
Now, inside onCreate load the homeFragment (as it is your first fragment to show)
override fun onCreate(savedInstanceState: Bundle?) {
val fragment = HomeFragment()
replaceFragment(fragment)
}
At this stage, you'll be able to load homeFragment successfully. Now next step is to create a callback interface. Every time you click on any card from the homeFragment you just have to provide the required information back to the mainActivity. It is good practice to leaving the responsibility of loading fragments on the activity.
interface OnCardClickListener {
fun onCardClick(fragment: Fragment)
}
implement this listener in MainActivity.
class MainActivity: OnCardClickListener{
It will override the onCardClick. now inside onCardClick call the replace method.
override onCardClick(fragment: Fragment){
replaceFragment(fragment)
}
Inside HomeFragment, Create an instance of OnCardClickListener
var listener: OnCardClickListener? = null
then in onAttach.
override fun onAttach(context: Context) {
super.onAttach(context)
listener = context as OnCardClickListener
}
Till this point, we have implemented the mechanism required to load fragment. Now only one final step is pending which is opening the desired fragment onClick of cardView. for that do as follow:
myCard1.setOnClickListener{
listener.onCardClick(GalleryFragment())
}
//If there's one more card available.
myCard2.setOnClickListener{
listener.onCardClick(SlideshowFragment())
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论