Java 将值从适配器传递到导航组件中的BottomNavigationView片段
应用程序在Java 将值从适配器传递到导航组件中的BottomNavigationView片段,java,android,android-fragments,android-recyclerview,bundle,Java,Android,Android Fragments,Android Recyclerview,Bundle,应用程序在main活动上有一个BottomNavigationView,它处理片段之间的导航。其中一个片段中有一个RecyclerView,而RecyclerView的项有一个按钮 我试图让RecyclerViewItems'按钮导航到另一个片段并传递一个值,但在传递数据时,我一直收到一个空对象引用 我为片段开关创建了一个界面来点击MainActivity,并创建了一个Bundle来将收到的值传递给所需的片段 适配器类 //Define interface OnItemClickListene
main活动
上有一个BottomNavigationView
,它处理片段之间的导航。其中一个片段中有一个RecyclerView
,而RecyclerView
的项有一个按钮
我试图让RecyclerView
Items'按钮导航到另一个片段并传递一个值,但在传递数据时,我一直收到一个空对象引用
MainActivity
,并创建了一个Bundle来将收到的值传递给所需的片段//Define interface
OnItemClickListener listener;
//Create constructor for interface
public LocationsAdapter(Activity activity) {
listener = (MainActivity)activity;
...
@Override
public void onBindViewHolder(@NonNull LocationsViewHolder holder, int position) {
//A click listener for the button
holder.showMarkerButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//Create instance of MapFragment to pass data as Bundle
MapFragment mapFragment = new MapFragment();
LatLng latLng = new LatLng(markerObject.getLatitude(),markerObject.getLongitude());
//Create Bundle and add data
Bundle bundle = new Bundle();
bundle.putString("latitude",markerObject.getLatitude().toString());
bundle.putString("longitude",markerObject.getLongitude().toString());
listener.onItemClick(bundle);
}
});
}
提前感谢。使用导航控制器时,您可以通过参数传入数据。转到导航组件XML文件并进行以下更改 1.在导航操作中,需要添加一个参数
<action
android:id="@+id/action_id"
app:destination="@id/destinationFragment">
<argument
android:name="paramterName"
app:argType="string" />
</action>
然后可以在目标片段中提取包
val parameter = DestinationFragmentArgs.fromBundle(requireArguments()).parameterName
// parameter has the value of "text123"
由于导航组件使用safeargs,因此可以传递从继承的任何类型的参数
这里的mapFragment
只是一个创建的对象,不在导航图中使用。i、 e.它是独立于导航的独立对象,因此不涉及导航,因为它与navGraph中当前的mapFragment
片段不同
解决方案:
为了解决这个问题,每当在BottomNavigationView的片段之间切换时,都需要传递参数,注册OnNavigationItemSelectedListener
是一个很好的地方:
首先,允许适配器通过侦听器回调将参数发送回活动
因此,修改侦听器回调以接受参数
interface OnItemClickListener listener {
void onItemClick(Bundle args);
}
将其应用到适配器上
@Override
public void onBindViewHolder(@NonNull LocationsViewHolder holder, int position) {
//A click listener for the button
holder.showMarkerButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LatLng latLng = new LatLng(markerObject.getLatitude(),markerObject.getLongitude());
//Create Bundle and add data
Bundle bundle = new Bundle();
bundle.putString("position",latLng.toString());
//Interface to transport the click event to the MainActivity to switch Fragment in the BottomNavigationView
listener.onItemClick(bundle);
}
});
}
最后,将OnNavigationItemSelectedListener
注册到navView
并修改回调以接受活动中的捆绑包:
public class MainActivity extends AppCompatActivity implements OnItemClickListener {
BottomNavigationView navView;
private Bundle mapArgs;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
navView = findViewById(R.id.nav_view);
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
R.id.navigation_home,R.id.navigation_map, R.id.navigation_locations, R.id.navigation_profile)
.build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
NavigationUI.setupWithNavController(navView, navController);
navView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
navController.navigate(item.getItemId(), mapArgs);
return true;
}
});
}
@Override
public void onItemClick(Bundle args) {
navView.setSelectedItemId(R.id.navigation_map);
mapArgs = args;
}
}
您可以在主活动中包含设置片段的代码吗?您正在创建捆绑包并将数据放入其中,但不将其传递到任何地方。追踪您创建的
mapFragment
对象发生了什么。@ShayKin I添加了完整的MainActivity@M.Azyoksul是的,现在我明白了问题所在,包必须提交给我将切换到的片段,片段才能访问包。如何引用BottomNavigation正在使用的MapFragment的相同实例?我知道通常一个Bundle是由一个FragmentManager提交的,比如getFragmentManager().beginTransaction().add(R.id.container,fragment.commit()代码>但是由于导航由NavController负责,所以我不能使用碎片管理器。为什么不在这种情况下使用碎片管理器呢谢谢,我让它工作了,但我还有一个问题。为了更好地理解,我更新了问题中的MapFragment方法。如果我按下RecyclerView项中的按钮,它将导航到MapFragment,但getArguments()方法返回null,但如果我返回到RecyclerView并再次按下按钮,它将打开MapFragment并显示带有LatLng的Toast,但它不会移动相机。setCam方法是在onMapReady()中调用的代码>仍然在listener.onItemClick(bundle)之后被调用代码>你能检查一下它是否还在那里吗;如果是,则删除它这是我的错,没有注意到在问题中留下了它,我现在就修复了它,但除此之外,我只有包含捆绑包的onItemClick。@EdwardAarma您还有问题吗?是的,基本上,当我第一次用按钮从RecyclerView导航到MapFragment时,捆绑包返回null,如果我重新创建MapFragment,那么我得到的是Bundle,但是moveCamera();方法不起作用。
navigationController.navigate(actionSourceFragmentToDestinationFragment("text123"))
val parameter = DestinationFragmentArgs.fromBundle(requireArguments()).parameterName
// parameter has the value of "text123"
MapFragment mapFragment = new MapFragment();
LatLng latLng = new LatLng(markerObject.getLatitude(),markerObject.getLongitude());
//Create Bundle and add data
Bundle bundle = new Bundle();
bundle.putString("position",latLng.toString());
mapFragment.setArguments(bundle);
interface OnItemClickListener listener {
void onItemClick(Bundle args);
}
@Override
public void onBindViewHolder(@NonNull LocationsViewHolder holder, int position) {
//A click listener for the button
holder.showMarkerButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LatLng latLng = new LatLng(markerObject.getLatitude(),markerObject.getLongitude());
//Create Bundle and add data
Bundle bundle = new Bundle();
bundle.putString("position",latLng.toString());
//Interface to transport the click event to the MainActivity to switch Fragment in the BottomNavigationView
listener.onItemClick(bundle);
}
});
}
public class MainActivity extends AppCompatActivity implements OnItemClickListener {
BottomNavigationView navView;
private Bundle mapArgs;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
navView = findViewById(R.id.nav_view);
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
R.id.navigation_home,R.id.navigation_map, R.id.navigation_locations, R.id.navigation_profile)
.build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
NavigationUI.setupWithNavController(navView, navController);
navView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
navController.navigate(item.getItemId(), mapArgs);
return true;
}
});
}
@Override
public void onItemClick(Bundle args) {
navView.setSelectedItemId(R.id.navigation_map);
mapArgs = args;
}
}