如何将两个片段并排设置并在它们之间进行通信?

huangapple go评论74阅读模式
英文:

How can I setup two Fragments Side by Side and Communicate between them?

问题

以下是翻译好的部分:

这是我第一次使用片段(Fragments),我开始创建了一个新的项目,并在Android Studio中选择了“导航抽屉活动”(Navigation Drawer Activity)。我的第一步是在“content_main.xml”中添加第二个片段(如下所示),并将MainActivity.java中对原始nav_host的引用更新为左侧片段。

<?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:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:showIn="@layout/app_bar_main">

    <fragment
        android:id="@+id/nav_host_fragment_left"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:layout_constraintEnd_toStartOf="@+id/guideline"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navGraph="@navigation/mobile_navigation" />

    <fragment
        android:id="@+id/nav_host_fragment_right"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="@+id/guideline"
        app:layout_constraintTop_toTopOf="parent"
        app:navGraph="@navigation/mobile_navigation" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.50121653" />
</androidx.constraintlayout.widget.ConstraintLayout>

以下是MainActivity.java:

package com.example.test;

import android.os.Bundle;

import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;

import android.view.View;

import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;

import com.google.android.material.navigation.NavigationView;

import androidx.drawerlayout.widget.DrawerLayout;

import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;

import android.view.Menu;

public class MainActivity extends AppCompatActivity {

    private AppBarConfiguration mAppBarConfiguration;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        FloatingActionButton fab = findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
        DrawerLayout drawer = findViewById(R.id.drawer_layout);
        NavigationView navigationView = findViewById(R.id.nav_view);
        mAppBarConfiguration = new AppBarConfiguration.Builder(
                R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow,
                R.id.nav_tools, R.id.nav_share, R.id.nav_send)
                .setDrawerLayout(drawer)
                .build();
        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_left);
        NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
        NavigationUI.setupWithNavController(navigationView, navController);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onSupportNavigateUp() {
        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_left);
        return NavigationUI.navigateUp(navController, mAppBarConfiguration)
                || super.onSupportNavigateUp();
    }
}

在运行应用程序时,我在两侧都看到“这是主页片段”。我可以使用菜单选择另一个菜单选项,左侧将更改以显示新的片段,而右侧仍然显示主页。我的问题是当我开始尝试在两个片段之间进行通信时。我看了下面的示例:

https://codinginflow.com/tutorials/android/fragment-to-fragment-communication-with-interfaces

但是在他们的MainActivity中有下面的代码:

fragmentA = new FragmentA();
fragmentB = new FragmentB();
getSupportFragmentManager().beginTransaction()
      .replace(R.id.container_a, fragmentA)
      .replace(R.id.container_b, fragmentB)
      .commit();

在我的当前MainActivity中,我没有看到这个,只有一些我认为以某种方式类似地工作的NavController项。

所以我有两个问题:

问题1 - 示例项目如何在我点击菜单项时替换左侧的片段?

问题2 - 我如何从MainActivity与右侧的片段进行通信?我认为我应该能够在MainActivity的OnCreate()中使用findFragmentById,但这不起作用。

HomeFragment homeFrag = getSupportFragmentManager().findFragmentById(R.id.nav_host_frag_right);

我猜想我需要修改创建片段的方式?非常感谢任何帮助!

英文:

This is my first time using fragments and I started off creating a new Project and choosing "Navigation Drawer Activity" in Android Studio. My first step was to add the second fragment in 'content_main.xml" (shown below) and update the references to the original nav_host in MainActivity.java to the left fragment.

&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;androidx.constraintlayout.widget.ConstraintLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
xmlns:app=&quot;http://schemas.android.com/apk/res-auto&quot;
xmlns:tools=&quot;http://schemas.android.com/tools&quot;
android:layout_width=&quot;match_parent&quot;
android:layout_height=&quot;match_parent&quot;
app:layout_behavior=&quot;@string/appbar_scrolling_view_behavior&quot;
tools:showIn=&quot;@layout/app_bar_main&quot;&gt;
&lt;fragment
android:id=&quot;@+id/nav_host_fragment_left&quot;
android:name=&quot;androidx.navigation.fragment.NavHostFragment&quot;
android:layout_width=&quot;0dp&quot;
android:layout_height=&quot;match_parent&quot;
app:defaultNavHost=&quot;true&quot;
app:layout_constraintEnd_toStartOf=&quot;@+id/guideline&quot;
app:layout_constraintLeft_toLeftOf=&quot;parent&quot;
app:layout_constraintStart_toStartOf=&quot;parent&quot;
app:layout_constraintTop_toTopOf=&quot;parent&quot;
app:navGraph=&quot;@navigation/mobile_navigation&quot; /&gt;
&lt;fragment
android:id=&quot;@+id/nav_host_fragment_right&quot;
android:name=&quot;androidx.navigation.fragment.NavHostFragment&quot;
android:layout_width=&quot;0dp&quot;
android:layout_height=&quot;match_parent&quot;
app:defaultNavHost=&quot;true&quot;
app:layout_constraintEnd_toEndOf=&quot;parent&quot;
app:layout_constraintStart_toStartOf=&quot;@+id/guideline&quot;
app:layout_constraintTop_toTopOf=&quot;parent&quot;
app:navGraph=&quot;@navigation/mobile_navigation&quot; /&gt;
&lt;androidx.constraintlayout.widget.Guideline
android:id=&quot;@+id/guideline&quot;
android:layout_width=&quot;wrap_content&quot;
android:layout_height=&quot;wrap_content&quot;
android:orientation=&quot;vertical&quot;
app:layout_constraintGuide_percent=&quot;0.50121653&quot; /&gt;
&lt;/androidx.constraintlayout.widget.ConstraintLayout&gt;

Below is MainActivity.Java

package com.example.test;
import android.os.Bundle;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
import android.view.View;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
import com.google.android.material.navigation.NavigationView;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import android.view.Menu;
public class MainActivity extends AppCompatActivity {
private AppBarConfiguration mAppBarConfiguration;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, &quot;Replace with your own action&quot;, Snackbar.LENGTH_LONG)
.setAction(&quot;Action&quot;, null).show();
}
});
DrawerLayout drawer = findViewById(R.id.drawer_layout);
NavigationView navigationView = findViewById(R.id.nav_view);
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
mAppBarConfiguration = new AppBarConfiguration.Builder(
R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow,
R.id.nav_tools, R.id.nav_share, R.id.nav_send)
.setDrawerLayout(drawer)
.build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_left);
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onSupportNavigateUp() {
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_left);
return NavigationUI.navigateUp(navController, mAppBarConfiguration)
|| super.onSupportNavigateUp();
}
}

When I run the app I see "This is home fragment" on both sides. I can use the menu to select another menu option, and the left side changes to display the new fragment, and the right is still showing home. My issue is when I start trying to communicate between the two fragments. I was looking at the example below:

https://codinginflow.com/tutorials/android/fragment-to-fragment-communication-with-interfaces

However in their MainActivity there is the below code

fragmentA = new FragmentA();
fragmentB = new FragmentB();
getSupportFragmentManager().beginTransaction()
.replace(R.id.container_a, fragmentA)
.replace(R.id.container_b, fragmentB)
.commit();

I dont see this in my current MainActivity, just some NavController items that I assume is somehow functioning in a similar fashion.

So I have 2 questions:

Q1 - How is the sample project replacing the left side fragment when I click on a menu item?

Q2 - How can I communicate with the right side fragment from the MainActivity? I am thinking I should be able to use findFragmentById in MainActivity OnCreate() but this doesn't work.

HomeFragment homeFrag = getSupportFragmentManager().findFragmentById(R.id.nav_host_frag_right);

I am guessing that I need to modify the way the fragments are created? Any help is much appreciated!

答案1

得分: 0

以下是翻译好的内容:

你可以使用 ViewModel 类作为中介,使片段之间可以轻松通信,或者可以创建一个接口并在您的活动中实现它。片段不能直接交互。
https://developer.android.com/reference/androidx/lifecycle/ViewModel
https://developer.android.com/training/basics/fragments/communicating

在第二种情况下,您可以通过以下方式调用那些接口方法:

getActivityac.methodA()
ac 是接口的引用变量methods() 是接口的其中一个方法之一
英文:

You can either use a ViewModel class to which fragments can easily communicate and it will act as an intermediator or you can create an interface an implement that in your activity.Fragments cannot interact directly.
https://developer.android.com/reference/androidx/lifecycle/ViewModel
https://developer.android.com/training/basics/fragments/communicating

you can call those interface methods by something like this in the second case :

   (getActivity)ac.methodA() ac is a reference variable of interface and methods() is 
one of the methods of interface.

huangapple
  • 本文由 发表于 2020年10月6日 06:34:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/64217091.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定