簡體   English   中英

將值從適配器傳遞到導航組件中的底部導航視圖片段

[英]Passing value from Adapter to a BottomNavigationView Fragment in Navigation components

該應用程序在MainActivity上有一個BottomNavigationView ,用於處理 Fragment 之間的導航。 其中一個片段中有一個RecyclerViewRecyclerView的項目有一個按鈕。

我試圖讓RecyclerView Items 的按鈕導航到另一個 Fragment 並傳遞一個值,但我一直收到 null object 引用並傳遞數據。

  1. 我創建了一個界面來獲得對 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);
                    }
        });
}
  1. 然后在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);
    }
}
  1. 作為最后一步,我調用了我在第一步中創建的 Bundle,但這就是 null object 參考出現的地方。
//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();
        }
    }

提前致謝。

使用導航 controller 時,您通過參數傳入數據。 Go 到您的導航組件 XML 文件並進行以下更改;

1.在導航動作中,您需要添加一個參數。

<action
    android:id="@+id/action_id"
    app:destination="@id/destinationFragment">
    <argument
        android:name="paramterName"
        app:argType="string" />
</action>

2.將相同的參數添加到目標片段

<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>

您也可以使用設計視圖輕松完成此操作。

現在,您調用以導航到目標片段的 function 期望您向其傳遞參數。

navigationController.navigate(actionSourceFragmentToDestinationFragment("text123"))

然后您可以在目標片段中提取捆綁包。

val parameter = DestinationFragmentArgs.fromBundle(requireArguments()).parameterName
// parameter has the value of "text123"

由於導航組件使用安全參數,因此您可以傳遞任何類型的繼承自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只是一個創建的 object,沒有在導航圖中使用。 即它是獨立於導航的獨立object,因此它不參與導航,因為它與navGraph 中的當前mapFragment片段不同。

解決方案:

為了解決這個問題,您需要在BottomNavigationView的片段之間切換時傳遞參數,並且注冊OnNavigationItemSelectedListener是一個好地方:

首先允許適配器通過偵聽器回調將 arguments 發送回活動

因此,修改偵聽器回調以接受參數

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並修改回調以接受活動中的 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;
    }


}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM