【问题标题】:How do I make Activity to work inside fragment?如何使 Activity 在片段内工作?
【发布时间】:2019-07-29 21:02:35
【问题描述】:

当我从 Navigation Drawer 中选择 chillzone 片段时,我可以切换片段,但是当我尝试从 BottomNavigationView 中选择某些内容时,没有任何反应。

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout 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/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context=".ui.MainActivity"
    tools:openDrawer="end">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/main_toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="@color/colorPrimary"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

        <FrameLayout
            android:id="@+id/fragment_container"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </LinearLayout>

    <com.google.android.material.navigation.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:headerLayout="@layout/nav_header_main"
        app:menu="@menu/activity_main_drawer" />

</androidx.drawerlayout.widget.DrawerLayout>

chillzone_fragment.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/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context=".ui.chillzone.ChillZoneActivity"
    tools:openDrawer="start">

    <TextView
        android:id="@+id/message"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="172dp"
        android:layout_marginLeft="172dp"
        android:layout_marginTop="356dp"
        android:text="@string/chillzone"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_nav_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="0dp"
        android:layout_marginEnd="0dp"
        android:background="?android:attr/windowBackground"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:menu="@menu/bottom_nav_menu" />

</androidx.constraintlayout.widget.ConstraintLayout>

ChillZoneActivity

package com.rishabhdeepsingh.metaapp.ui.chillzone

import android.os.Bundle
import android.util.Log
import com.google.android.material.bottomnavigation.BottomNavigationView
import androidx.appcompat.app.AppCompatActivity
import android.widget.TextView
import android.widget.Toast
import com.rishabhdeepsingh.metaapp.R

class ChillZoneActivity : AppCompatActivity() {

    private lateinit var bottomNavigationView: BottomNavigationView
    private lateinit var textMessage: TextView
    private val onNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item ->
        println("~~~~~~~~~~~~~~~~~~~~~~~~")
        when (item.itemId) {
            R.id.navigation_home -> {
                textMessage.setText(R.string.title_home)
                Toast.makeText(this, "Home", Toast.LENGTH_LONG).show()
                return@OnNavigationItemSelectedListener true
            }
            R.id.navigation_dashboard -> {
                textMessage.setText(R.string.title_dashboard)
                Toast.makeText(this, "Dashboard", Toast.LENGTH_LONG).show()
                return@OnNavigationItemSelectedListener true
            }
            R.id.navigation_notifications -> {
                textMessage.setText(R.string.title_notifications)
                Toast.makeText(this, "Notifications", Toast.LENGTH_LONG).show()
                return@OnNavigationItemSelectedListener true
            }
        }
        false
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        bottomNavigationView = findViewById(R.id.bottom_nav_view)
        println("~~~~~~~~~~~~~~!!!!!!!!!!!!!!!!!!!!!~~~~~~~~~~")
        Toast.makeText(this, "Hello", Toast.LENGTH_LONG).show()
        textMessage = findViewById(R.id.message)
        bottomNavigationView.setOnNavigationItemSelectedListener(onNavigationItemSelectedListener)
    }
}

ChillZoneFragment.kt

package com.rishabhdeepsingh.metaapp.ui.chillzone

import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.rishabhdeepsingh.metaapp.R

class ChillZoneFragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.chillzone_fragment, container, false)
    }
}

MainActivity.kt

package com.rishabhdeepsingh.metaapp.ui

import android.os.Bundle
import androidx.core.view.GravityCompat
import androidx.appcompat.app.ActionBarDrawerToggle
import android.view.MenuItem
import android.widget.Toast
import androidx.drawerlayout.widget.DrawerLayout
import com.google.android.material.navigation.NavigationView
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import com.rishabhdeepsingh.metaapp.R
import com.rishabhdeepsingh.metaapp.ui.chillzone.ChillZoneFragment


class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {

    private lateinit var drawerLayout: DrawerLayout

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val toolbar: Toolbar = findViewById(R.id.main_toolbar)
        setSupportActionBar(toolbar)

        val navView: NavigationView = findViewById(R.id.nav_view)
        navView.setNavigationItemSelectedListener(this)

        drawerLayout = findViewById(R.id.drawer_layout)
        val toggle = ActionBarDrawerToggle(
            this, drawerLayout, toolbar,
            R.string.navigation_drawer_open,
            R.string.navigation_drawer_close
        )
        drawerLayout.addDrawerListener(toggle)
        toggle.syncState()

        if (savedInstanceState == null) {
            supportFragmentManager
                .beginTransaction()
                .replace(R.id.fragment_container, HomeFragment())
                .commit()
            navView.setCheckedItem(R.id.home)
        }
    }

    override fun onBackPressed() {
        if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
            drawerLayout.closeDrawer(GravityCompat.START)
        } else {
            super.onBackPressed()
        }
    }

    override fun onNavigationItemSelected(item: MenuItem): Boolean {
        // Handle navigation view item clicks here.
        when (item.itemId) {
            R.id.nav_home -> {
                // Handle the camera action
                supportFragmentManager
                    .beginTransaction()
                    .replace(R.id.fragment_container, HomeFragment())
                    .commit()
            }
            R.id.nav_chillzone -> {
                supportFragmentManager
                    .beginTransaction()
                    .replace(R.id.fragment_container, ChillZoneFragment())
                    .commit()
            }
            R.id.nav_slideshow -> {

            }
            R.id.nav_tools -> {

            }
            R.id.nav_share -> {
                Toast.makeText(this, "Share", Toast.LENGTH_SHORT).show()
            }
            R.id.nav_send -> {

            }
        }
        drawerLayout.closeDrawer(GravityCompat.START)
        return true
    }
}

我希望 Toast 消息应该与我选择的 BottomNavigationView 按钮相对应。

【问题讨论】:

    标签: android xml android-fragments kotlin


    【解决方案1】:

    您的BottomNavigationView 相关代码在ChillZoneActivity 中。它需要在ChillZoneFragment 中。

    class ChillZoneFragment : Fragment() {
    
        private lateinit var bottomNavigationView: BottomNavigationView
        private lateinit var textMessage: TextView
        private val onNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item ->
            println("~~~~~~~~~~~~~~~~~~~~~~~~")
            when (item.itemId) {
                R.id.navigation_home -> {
                    textMessage.setText(R.string.title_home)
                    Toast.makeText(this, "Home", Toast.LENGTH_LONG).show()
                    return@OnNavigationItemSelectedListener true
                }
                R.id.navigation_dashboard -> {
                    textMessage.setText(R.string.title_dashboard)
                    Toast.makeText(this, "Dashboard", Toast.LENGTH_LONG).show()
                    return@OnNavigationItemSelectedListener true
                }
                R.id.navigation_notifications -> {
                    textMessage.setText(R.string.title_notifications)
                    Toast.makeText(this, "Notifications", Toast.LENGTH_LONG).show()
                    return@OnNavigationItemSelectedListener true
                }
            }
            false
        }
    
        override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            val view = inflater.inflate(R.layout.chillzone_fragment, container, false)
            bottomNavigationView = view.findViewById(R.id.bottom_nav_view)
            textMessage = view.findViewById(R.id.message)
            bottomNavigationView.setOnNavigationItemSelectedListener(onNavigationItemSelectedListener)
            return view
        }
    }
    

    P.S - 您不能让活动在片段内“工作”。这不是它的工作原理。片段包含在活动中,绝不会反过来。

    Fragment 表示FragmentActivity 中的一种行为或用户界面的一部分。您可以在单个活动中组合多个片段以构建多窗格 UI 并在多个活动中重用一个片段。您可以将片段视为活动的模块化部分,它有自己的生命周期,接收自己的输入事件,并且可以在活动运行时添加或删除(有点像“子活动”,您可以在不同的活动中重复使用)。

    片段必须始终托管在 Activity 中,并且片段的生命周期直接受宿主 Activity 生命周期的影响。

    有关详细信息,请参阅official documentation

    【讨论】:

    • 那么我应该为 ChillZone 创建一个新活动吗?
    • 翻阅Codelabs for Android Fundamentals,它应该可以帮助你很好地掌握Android开发的基础知识。
    • 这里是codelab,它解释了如何创建和过渡到活动。
    【解决方案2】:

    似乎底部导航侦听器未正确设置 尝试切换:

    bottomNavigationView.setOnNavigationItemSelectedListener(onNavigationItemSelectedListener)
    

    到:

    bottomNavigationView.setOnNavigationItemSelectedListener(this)
    

    【讨论】:

      【解决方案3】:

      Android Fragment 是activity的一部分,也称为子activity。一个活动中可以有多个片段。片段代表一个活动中的多个屏幕。

      Android Fragment 生命周期受 Activity 生命周期的影响,因为 Fragment 包含在 Activity 中。

      每个fragment都有自己的生命周期方法,这些方法受activity生命周期的影响,因为fragment是嵌入在activity中的。

      FragmentManager 类负责在片段对象之间进行交互。

      您不能在片段中添加活动。

      希望对你有帮助!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多