选择导航菜单项时不会替换上一个片段
Posted
技术标签:
【中文标题】选择导航菜单项时不会替换上一个片段【英文标题】:Previous fragment is not being replaced when selecting a navigation menu item 【发布时间】:2021-11-16 19:27:23 【问题描述】:我有一个导航抽屉活动,它根据从前一个活动作为主页片段传递的一些数据显示餐厅列表。单击其中一张餐厅卡片时,会创建另一个显示餐厅详细信息的片段。所有这些片段都将导航抽屉活动作为其父活动。当我在导航项上选择主片段菜单时,片段不会替换前一个片段,而是将自身叠加在前一个片段上。我会添加一些图片来解释这个场景。
这是我的导航抽屉 -
这是包含餐厅列表的主页片段 -
这是点击一家餐厅时显示餐厅详情的片段 -
当我从餐厅详情屏幕按下导航抽屉上的主页时,会发生这种情况 -
这里是相关代码- MainActivity2.class
package com.example.wfdmockapp;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
import android.view.Menu;
import com.example.wfdmockapp.ui.home.HomeFragment;
import com.google.android.material.snackbar.Snackbar;
import com.google.android.material.navigation.NavigationView;
import androidx.annotation.NonNull;
import androidx.core.view.GravityCompat;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.appcompat.app.AppCompatActivity;
import com.example.wfdmockapp.databinding.ActivityMain2Binding;
public class MainActivity2 extends AppCompatActivity
private static final String TAG = "MainActivity2";
private String cityId = null;
private String townId = null;
private DrawerLayout drawer;
private AppBarConfiguration mAppBarConfiguration;
private ActivityMain2Binding binding;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
binding = ActivityMain2Binding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
setSupportActionBar(binding.appBarMain.toolbar);
binding.appBarMain.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();
);
drawer = binding.drawerLayout;
NavigationView navigationView = binding.navView;
// 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)
.setOpenableLayout(drawer)
.build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController);
Intent getRestaurantIntent = getIntent();
cityId = getRestaurantIntent.getStringExtra("cityId");
townId = getRestaurantIntent.getStringExtra("townId");
Bundle bundle = new Bundle();
bundle.putString("cityId",cityId);
bundle.putString("townId",townId);
System.out.println(cityId+" "+townId);
if (savedInstanceState == null)
getSupportFragmentManager().beginTransaction()
.setReorderingAllowed(true)
.replace(R.id.nav_host_fragment_content_main, HomeFragment.class, bundle)
.commit();
@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_activity2, menu);
return true;
@Override
public boolean onSupportNavigateUp()
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
return NavigationUI.navigateUp(navController, mAppBarConfiguration)
|| super.onSupportNavigateUp();
```
HomeFragment.Java
public class HomeFragment extends Fragment
private static final String TAG = "HomeFragment";
private RequestQueue mRequestQueue;
private String cityId = null;
private String townId = null;
private String ShopListUrl= Global.base_url+"v1/get-shop-list";
private ArrayList<Shop> shops = new ArrayList<>();
private RecyclerView recyclerView;
private ShopRecyclerViewAdapter adapter;
private GifImageView loadingAnimation;
@Override
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState)
Bundle bundle = this.getArguments();
if(bundle!=null)
cityId = bundle.getString("cityId");
townId = bundle.getString("townId");
System.out.println(cityId+" "+townId);
return inflater.inflate(R.layout.fragment_home, container, false);
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState)
super.onViewCreated(view, savedInstanceState);
mRequestQueue = Volley.newRequestQueue(getContext());
loadingAnimation = view.findViewById(R.id.loading_animation);
initRecyclerView(view);
getShopList();
public void getShopList()
Log.d(TAG,"Creating Shop Object");
JSONObject shopInfoObject = new JSONObject();
try
shopInfoObject.put("city",cityId);
shopInfoObject.put("town",townId);
shopInfoObject.put("shop_type",null);
shopInfoObject.put("api_token","a4e426652ed46154d67c8af897e77022");
catch (JSONException e)
e.printStackTrace();
Log.d(TAG,"JSON Shop Object created,collecting response for Request");
JsonObjectRequest ShopListRequest = new JsonObjectRequest(Request.Method.POST, ShopListUrl, shopInfoObject, new Response.Listener<JSONObject>()
@Override
public void onResponse(JSONObject response)
try
Log.d(TAG,"Getting response");
JSONArray shopList = response.getJSONArray("shopList");
for(int i=0;i<shopList.length();i++)
JSONObject jsonObject = shopList.getJSONObject(i);
Shop shop = new Shop();
shop.setShopId(jsonObject.getString("shopId"));
shop.setName(jsonObject.getString("title"));
shop.setTypeName(jsonObject.getString("typeName"));
shop.setLogo(Global.base_imageUrl+jsonObject.getString("logo"));
shop.setSpecialOffer(jsonObject.getString("special_offer_text"));
shop.setDeliveredBy(jsonObject.getInt("deliveredBy"));
shop.setMixMatch(jsonObject.getInt("mixAndMatch"));
shop.setDeliveryFee(jsonObject.getString("delivery_fee"));
shop.setMinimumOrder(jsonObject.getString("minOrder"));
shop.setPaymentModeText(jsonObject.getString("paymentModeText"));
shop.setShopStatus(jsonObject.getString("currentStatus"));
shops.add(shop);
adapter.notifyDataSetChanged();
Log.d(TAG,"Shop data fetched");
loadingAnimation.setVisibility(View.GONE);
catch (JSONException e)
e.printStackTrace();
, new Response.ErrorListener()
@Override
public void onErrorResponse(VolleyError error)
if (error instanceof TimeoutError)
Global.displayToast("Timeout! Please Try Again",getContext());
);
ShopListRequest.setRetryPolicy(new DefaultRetryPolicy(
6000,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
mRequestQueue.add(ShopListRequest);
public void initRecyclerView(View view)
recyclerView = view.findViewById(R.id.recycler_view);
adapter = new ShopRecyclerViewAdapter(shops,getContext(),this);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
```
RestaurantDetailsFragment.Java
package com.example.wfdmockapp;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.volley.DefaultRetryPolicy;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.TimeoutError;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;
import com.bumptech.glide.Glide;
import com.example.wfdmockapp.models.Restaurant;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import de.hdodenhof.circleimageview.CircleImageView;
import pl.droidsonroids.gif.GifImageView;
public class RestaurantDetailsFragment extends Fragment
private static final String TAG = "RestaurantDetails";
private RequestQueue mRequestQueue;
private Restaurant restaurant = new Restaurant();
private String getShopDetailsUrl = Global.base_url+"v1/get-shop-details";
private String shopId;
private ArrayList<String> FoodTypeList;
//UI Components
private TextView name;
private TextView typeName;
private TextView shopMessage;
private TextView minOrder;
private TextView paymentModeText;
private RecyclerView foodTypeListRecyclerView;
private FoodTypeRecyclerViewAdapter adapter;
private TextView deliveryText;
private TextView deliveryFee;
private TextView deliveryTime;
private TextView shopStatus;
private CircleImageView shopLogo;
private LinearLayout shopDetailsView;
private GifImageView loadingAnimation;
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
shopId = getArguments().getString("shopId");
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_restaurant_details, container, false);
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState)
super.onViewCreated(view, savedInstanceState);
loadingAnimation = view.findViewById(R.id.shop_details_loading_animation);
shopDetailsView = view.findViewById(R.id.shop_view);
shopDetailsView.setVisibility(View.GONE);
FoodTypeList = restaurant.getFoodTypeList();
mRequestQueue = Volley.newRequestQueue(getContext());
initRecyclerView(view);
initUIComponents(view);
showRestaurantDetails(view);
public void showRestaurantDetails(View view)
JSONObject ShopInfoObject = new JSONObject();
try
ShopInfoObject.put("api_token","cadbc10d3aa13257cd7c69bb3d434d00");
ShopInfoObject.put("shopId",shopId);
catch (JSONException e)
e.printStackTrace();
JsonObjectRequest getShopDetailsRequest = new JsonObjectRequest(Request.Method.POST, getShopDetailsUrl, ShopInfoObject, new Response.Listener<JSONObject>()
@Override
public void onResponse(JSONObject response)
try
JSONArray shopDetails = response.getJSONArray("shop");
String deliveryTextResponse = response.getString("deliveryText");
restaurant.setDeliveryText(deliveryTextResponse);
for(int i=0;i<shopDetails.length();i++)
JSONObject shopJsonObject = shopDetails.getJSONObject(i);
restaurant.setName(shopJsonObject.getString("title"));
restaurant.setTypeName(shopJsonObject.getString("typeName"));
restaurant.setShop_message(shopJsonObject.getString("shop_message"));
String ImageUrl = Global.base_imageUrl+shopJsonObject.getString("logo");
restaurant.setLogo(ImageUrl);
restaurant.setMinOrder(shopJsonObject.getString("minOrder"));
restaurant.setStatus(shopJsonObject.getString("currentStatus"));
JSONArray foodTypeListJSONArray = shopJsonObject.getJSONArray("foodTypeList");
for(int j=0;j<foodTypeListJSONArray.length();j++)
JSONObject foodTypeListJSONObject = foodTypeListJSONArray.getJSONObject(j);
Log.d(TAG,foodTypeListJSONObject.getString("foodTypeName"));
restaurant.addFoodListItems(foodTypeListJSONObject.getString("foodTypeName"));
adapter.notifyDataSetChanged();
restaurant.setDelivery_fee(shopJsonObject.getString("delivery_fee"));
JSONObject deliveryHours = shopJsonObject.getJSONObject("deliveryHours");
String openingHours = deliveryHours.getString("openingHour");
String closingHours = deliveryHours.getString("closingHour");
restaurant.setDeliveryTime("Delivery: "+openingHours+" - "+closingHours);
restaurant.setPaymentModeText(shopJsonObject.getString("paymentModeText"));
setUIComponentValues(restaurant,view);
loadingAnimation.setVisibility(View.GONE);
shopDetailsView.setVisibility(View.VISIBLE);
catch (JSONException e)
e.printStackTrace();
, new Response.ErrorListener()
@Override
public void onErrorResponse(VolleyError error)
if (error instanceof TimeoutError)
Global.displayToast("Timeout error!Please try again",getContext());
);
getShopDetailsRequest.setRetryPolicy(new DefaultRetryPolicy(
5000,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
mRequestQueue.add(getShopDetailsRequest);
public void initUIComponents(View view)
name = view.findViewById(R.id.shopName);
typeName = view.findViewById(R.id.shopTypename);
shopMessage = view.findViewById(R.id.shop_message);
minOrder = view.findViewById(R.id.min_order);
paymentModeText = view.findViewById(R.id.payment_Method);
deliveryFee = view.findViewById(R.id.min_delivery_fee);
deliveryText = view.findViewById(R.id.delivery_time_today);
deliveryTime = view.findViewById(R.id.shop_delivery_time);
shopLogo = view.findViewById(R.id.shopLogo);
shopStatus = view.findViewById(R.id.status);
public void setUIComponentValues(Restaurant restaurant,View view)
Glide.with(getContext()).load(restaurant.getLogo()).into(shopLogo);
name.setText(restaurant.getName());
typeName.setText(restaurant.getTypeName());
String message = restaurant.getShop_message();
System.out.println(message);
if(message.equals("")||message.equals("null"))
Log.d(TAG,"No shop message,hiding field");
LinearLayout shopMsgField = view.findViewById(R.id.shop_message_field);
shopMsgField.setVisibility(View.GONE);
else
shopMessage.setText(message);
minOrder.setText("\u20ac "+restaurant.getMinOrder()+" MIN ");
paymentModeText.setText(restaurant.getPaymentModeText());
deliveryFee.setText("Delivery \u20ac "+restaurant.getDelivery_fee());
String text = restaurant.getDeliveryText();
if(text.equals("null")||text.equals(""))
deliveryText.setVisibility(View.GONE);
else
deliveryText.setText(text);
deliveryTime.setText(restaurant.getDeliveryTime());
Global.setCurrentStatusText(restaurant.getStatus(),shopStatus);
public void initRecyclerView(View view)
foodTypeListRecyclerView = view.findViewById(R.id.FoodTypeRecyclerView);
adapter = new FoodTypeRecyclerViewAdapter(FoodTypeList,getContext());
foodTypeListRecyclerView.setAdapter(adapter);
foodTypeListRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
```
ShopRecyclerViewAdapter.java
package com.example.wfdmockapp;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import com.example.wfdmockapp.models.Shop;
import java.io.FileNotFoundException;
import java.util.ArrayList;
public class ShopRecyclerViewAdapter extends RecyclerView.Adapter<ShopRecyclerViewAdapter.ViewHolder>
private static final String TAG="ShopRecyclerViewAdapter";
private ArrayList<Shop> shops;
private Context mContext;
private Fragment fragment;
public ShopRecyclerViewAdapter(ArrayList<Shop> shops,Context mContext,Fragment fragment)
this.shops = shops;
this.mContext = mContext;
this.fragment = fragment;
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType)
Log.d(TAG,"Reached onCreate");
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.shoplistitem,parent,false);
ViewHolder holder = new ViewHolder(view);
return holder;
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position)
Log.d(TAG,"Reached onBind");
try
Glide.with(mContext).load(shops.get(position).getLogo()).into(holder.shopLogo);
catch (Exception e)
Glide.with(mContext).load(R.drawable.shop_logo_base).into(holder.shopLogo);
holder.deliveryFee.setText("Delivery \u20ac "+shops.get(position).getDeliveryFee());
holder.minOrder.setText("\u20ac "+shops.get(position).getMinimumOrder()+" MIN ");
holder.paymentMethod.setText(shops.get(position).getPaymentModeText());
String status = shops.get(position).getShopStatus();
Global.setCurrentStatusText(status,holder.shopStatus);
holder.shopName.setText(shops.get(position).getName());
holder.shopTypeName.setText(shops.get(position).getTypeName());
String offerText = shops.get(position).getSpecialOffer();
if(!(offerText==null))
holder.shopOffer.setText(offerText);
else
holder.offerSection.setVisibility(View.GONE);
int deliveredBy = shops.get(position).getDeliveredBy();
makeViewInvisible(holder.delivery_layout,deliveredBy);
int mixAndMatch = shops.get(position).getMixMatch();
makeViewInvisible(holder.mixMatchLayout,mixAndMatch);
holder.parent_layout.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
Bundle bundle = new Bundle();
bundle.putString("shopId",shops.get(position).getShopId());
FragmentManager fm = fragment.getActivity().getSupportFragmentManager();
FragmentTransaction fragmentTrans = fm.beginTransaction();
fragmentTrans.replace(R.id.nav_host_fragment_content_main,RestaurantDetailsFragment.class,bundle);
fragmentTrans.setReorderingAllowed(true);
fragmentTrans.addToBackStack(null);
fragmentTrans.commit();
);
@Override
public int getItemCount()
return shops.size();
public class ViewHolder extends RecyclerView.ViewHolder
ImageView shopLogo;
TextView shopName;
TextView shopTypeName;
TextView shopOffer;
TextView minOrder;
TextView deliveryFee;
TextView paymentMethod;
TextView shopStatus;
RelativeLayout offerSection;
RelativeLayout parent_layout;
RelativeLayout delivery_layout;
RelativeLayout mixMatchLayout;
public ViewHolder(@NonNull View itemView)
super(itemView);
shopLogo = itemView.findViewById(R.id.shop_logo);
shopName = itemView.findViewById(R.id.shop_title);
shopTypeName = itemView.findViewById(R.id.shop_typename);
shopOffer = itemView.findViewById(R.id.offer_text);
offerSection = itemView.findViewById(R.id.offer_section);
minOrder = itemView.findViewById(R.id.shop_min_order);
deliveryFee = itemView.findViewById(R.id.deliver_fee);
shopStatus = itemView.findViewById(R.id.status);
paymentMethod = itemView.findViewById(R.id.shop_payment);
parent_layout = itemView.findViewById(R.id.parent_layout);
delivery_layout = itemView.findViewById(R.id.delivered_by);
mixMatchLayout = itemView.findViewById(R.id.mix_and_match);
public void makeViewInvisible(View view,int flag)
if(flag==1)
view.setVisibility(View.GONE);
```
【问题讨论】:
【参考方案1】:您需要在 onBackPressed 上弹出片段,因此需要从 MainActivity 执行函数。
MainActivity
public void popFragment()
if (getSupportFragmentManager() == null)
return;
getSupportFragmentManager().popBackStack();
@Override
public void onBackPressed()
if (getSupportFragmentManager().getBackStackEntryCount() > 1)
popFragment();
【讨论】:
当我从导航菜单中选择一个菜单项时,会调用 onBackPressed 吗?我做了更多的探索并意识到每当我在导航中选择主页项时,片段的布局都会叠加在任何其他片段上 你必须在按下 home 的同时弹出其他所有片段,而对于 back press 你只需弹出一次。【参考方案2】:原来,问题出在 ShopRecyclerViewAdapter.java 文件中。
排队
FragmentManager fm = fragment.getActivity().getSupportFragmentManager
fragment.getActivity
使上下文为空。从视图中获取上下文反而解决了这个问题。
我将上面的行替换为以下内容:
FragmentManager fm = ((FragmentActivity) view.getContext()).getSupportFragmentManager()
这里是解决方案的参考:
Replace fragment from recycler adapter
【讨论】:
以上是关于选择导航菜单项时不会替换上一个片段的主要内容,如果未能解决你的问题,请参考以下文章