将值从适配器传递到导航组件中的 BottomNavigationView 片段
Passing value from Adapter to a BottomNavigationView Fragment in Navigation components
该应用程序在 MainActivity
上有一个 BottomNavigationView
,用于处理 Fragment 之间的导航。其中一个片段有一个 RecyclerView
并且 RecyclerView
的项目有一个按钮。
我试图让 RecyclerView
项的按钮导航到另一个片段并传递一个值,但我在传递数据时一直收到空对象引用。
- 我为 Fragment 开关创建了一个界面来获得对
MainActivity
的点击,并创建了一个 Bundle 来将接收到的值传递给所需的 Fragment
// The interface
public interface OnItemClickListener {
void onItemClick();
适配器class
//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);
}
});
}
- 然后在MainActivity中我实现了切换BottomNavigation的View的接口
public class MainActivity extends AppCompatActivity implements OnItemClickListener {
BottomNavigationView navView;
@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);
}
@Override
public void onItemClick() {
navView.setSelectedItemId(R.id.navigation_map);
}
}
- 作为最后一步,我调用了我在第一步中创建的 Bundle,但这是空对象引用出现的地方。
//MapFragment
private void setCam(){
Bundle bundle = getArguments();
if (getArguments() != null ){
String SLatitude = bundle.getString("latitude");
String SLongitude = bundle.getString("longitude");
Double latitude = Double.parseDouble(SLatitude);
Double longitude = Double.parseDouble(SLongitude);
LatLng latLng = new LatLng(latitude,longitude);
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 20));
Toast.makeText(getActivity(), latLng.toString(), Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(getActivity(), "error present", Toast.LENGTH_SHORT).show();
}
}
提前致谢。
在使用导航控制器时,你传入带参数的数据。转到您的导航组件 XML 文件并进行以下更改;
1.Inside导航动作,需要加参数
<action
android:id="@+id/action_id"
app:destination="@id/destinationFragment">
<argument
android:name="paramterName"
app:argType="string" />
</action>
2.Add 目标片段的相同参数
<fragment
android:id="@+id/coursesNavFragment"
android:name="com.example.example.DestinationFragment"
android:label="destination_fragment"
tools:layout="@layout/destination_fragment" >
<argument
android:name="parameterName"
app:argType="string" />
</fragment>
您也可以使用设计视图轻松完成此操作。
现在,您为导航到目标片段而调用的函数需要您向它传递一个参数。
navigationController.navigate(actionSourceFragmentToDestinationFragment("text123"))
然后您可以提取目标片段中的包。
val parameter = DestinationFragmentArgs.fromBundle(requireArguments()).parameterName
// parameter has the value of "text123"
由于导航组件使用 safeargs,您可以传递继承自 Parcellable 的任何类型的参数。
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);
这里的mapFragment
只是一个创建的对象,并没有在导航图中使用。即它是一个独立于导航的独立对象,因此它不参与导航,因为它与 navGraph 中的当前 mapFragment
片段不同。
解法:
为了解决这个问题,每当在 BottomNavigationView 的片段之间切换时都需要传递参数,注册 OnNavigationItemSelectedListener
是一个很好的地方:
首先允许适配器通过侦听器回调
将参数发送回activity
所以,修改监听回调接受一个参数
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
并修改回调以接受 activity 中的 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;
}
}
该应用程序在 MainActivity
上有一个 BottomNavigationView
,用于处理 Fragment 之间的导航。其中一个片段有一个 RecyclerView
并且 RecyclerView
的项目有一个按钮。
我试图让 RecyclerView
项的按钮导航到另一个片段并传递一个值,但我在传递数据时一直收到空对象引用。
- 我为 Fragment 开关创建了一个界面来获得对
MainActivity
的点击,并创建了一个 Bundle 来将接收到的值传递给所需的 Fragment
// The interface
public interface OnItemClickListener {
void onItemClick();
适配器class
//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);
}
});
}
- 然后在MainActivity中我实现了切换BottomNavigation的View的接口
public class MainActivity extends AppCompatActivity implements OnItemClickListener {
BottomNavigationView navView;
@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);
}
@Override
public void onItemClick() {
navView.setSelectedItemId(R.id.navigation_map);
}
}
- 作为最后一步,我调用了我在第一步中创建的 Bundle,但这是空对象引用出现的地方。
//MapFragment
private void setCam(){
Bundle bundle = getArguments();
if (getArguments() != null ){
String SLatitude = bundle.getString("latitude");
String SLongitude = bundle.getString("longitude");
Double latitude = Double.parseDouble(SLatitude);
Double longitude = Double.parseDouble(SLongitude);
LatLng latLng = new LatLng(latitude,longitude);
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 20));
Toast.makeText(getActivity(), latLng.toString(), Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(getActivity(), "error present", Toast.LENGTH_SHORT).show();
}
}
提前致谢。
在使用导航控制器时,你传入带参数的数据。转到您的导航组件 XML 文件并进行以下更改;
1.Inside导航动作,需要加参数
<action
android:id="@+id/action_id"
app:destination="@id/destinationFragment">
<argument
android:name="paramterName"
app:argType="string" />
</action>
2.Add 目标片段的相同参数
<fragment
android:id="@+id/coursesNavFragment"
android:name="com.example.example.DestinationFragment"
android:label="destination_fragment"
tools:layout="@layout/destination_fragment" >
<argument
android:name="parameterName"
app:argType="string" />
</fragment>
您也可以使用设计视图轻松完成此操作。
现在,您为导航到目标片段而调用的函数需要您向它传递一个参数。
navigationController.navigate(actionSourceFragmentToDestinationFragment("text123"))
然后您可以提取目标片段中的包。
val parameter = DestinationFragmentArgs.fromBundle(requireArguments()).parameterName
// parameter has the value of "text123"
由于导航组件使用 safeargs,您可以传递继承自 Parcellable 的任何类型的参数。
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);
这里的mapFragment
只是一个创建的对象,并没有在导航图中使用。即它是一个独立于导航的独立对象,因此它不参与导航,因为它与 navGraph 中的当前 mapFragment
片段不同。
解法:
为了解决这个问题,每当在 BottomNavigationView 的片段之间切换时都需要传递参数,注册 OnNavigationItemSelectedListener
是一个很好的地方:
首先允许适配器通过侦听器回调
将参数发送回activity所以,修改监听回调接受一个参数
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
并修改回调以接受 activity 中的 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;
}
}