9

Tôi đã tấn công ứng dụng đầu tiên của mình từ một loạt các hướng dẫn. Với sự giúp đỡ của một trong số họ, tôi đã thực hiện RecyclerView bên trong một đoạn được sử dụng bởi hoạt động chính. Bây giờ tôi đã tìm thấy another tutorial mà tôi muốn sử dụng để triển khai đa lựa chọn với chế độ hành động theo ngữ cảnh. Vấn đề lớn là, hướng dẫn không sử dụng một đoạn. Tôi đã cố gắng viết lại mã để phù hợp với một đoạn. Tôi bây giờ tại một điểm mà tôi không nhận được bất kỳ lỗi trong Android Studio và chạy ứng dụng, nhưng khi tôi thực sự làm LongClick để chọn một mục, nó bị treo với một NullPointerException:Các vấn đề với việc thực hiện chế độ hành động theo ngữ cảnh trong recyclerview fragment

java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v7.view.ActionMode.setTitle(java.lang.CharSequence)' on a null object reference

Tôi hoàn toàn bị mất là tại sao điều này xảy ra và với toàn bộ công cụ đa lựa chọn nói chung.

Tôi nghĩ rằng phần liên quan của mỗi lớp tham gia là:

Adapter.java:

public class Adapter extends SelectableAdapter<Adapter.ViewHolder> { 

private ArrayList<Meal> items = new ArrayList<>(); 

private Context context; 
private ViewHolder.ClickListener clickListener; 

public Adapter(ViewHolder.ClickListener clickListener) { 
    super(); 
    this.clickListener = clickListener; 

} 

@Override 
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
    View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.fragment_today_items, parent, false); 
    return new ViewHolder(v, clickListener); 
} 

@Override 
public void onBindViewHolder(final ViewHolder holder, int position) { 
    Meal currentMeal = items.get(position); 


    holder.meal_typeicon.setImageResource(currentMeal.getBadgeIcon()); 
    holder.meal_price.setText(currentMeal.getPriceOutput()); 

    holder.meal_name.setText(isSelected(position) ? "SELECTED" : "NOT SELECTED"); 


} 

public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener { 
    @SuppressWarnings("unused") 
    private static final String TAG = ViewHolder.class.getSimpleName(); 

    private RelativeLayout meal_item; 

    private ClickListener listener; 

    private TextView meal_name; 
    private TextView meal_price; 
    private TextView meal_contents; 
    private TextView meal_contents_spelledout; 
    private ImageView meal_typeicon; 

    public ViewHolder(View itemView, ClickListener listener) { 
     super(itemView); 
     meal_item = (RelativeLayout) itemView.findViewById(R.id.meal_item); 

     this.listener = listener; 

     itemView.setOnClickListener(this); 
     itemView.setOnLongClickListener(this); 


     meal_name = (TextView) itemView.findViewById(R.id.meal_name); 
     meal_price = (TextView) itemView.findViewById(R.id.meal_price); 
     meal_contents = (TextView) itemView.findViewById(R.id.meal_contents); 
     meal_contents_spelledout = (TextView) itemView.findViewById(R.id.meal_contents_spelledout); 
     meal_typeicon = (ImageView) itemView.findViewById(R.id.meal_typeicon); 
    } 

    @Override 
    public void onClick(View v) { 
     if (listener != null) { 
      listener.onItemClicked(getAdapterPosition()); 
     } 
    } 

    @Override 
    public boolean onLongClick(View v) { 
     if (listener != null) { 
      return listener.onItemLongClicked(getAdapterPosition()); 
     } 
     return false; 
    } 

    public interface ClickListener { 
     void onItemClicked(int position); 

     boolean onItemLongClicked(int position); 
    } 
} 

@Override 
public int getItemCount() { 
    return items.size(); 
} 

public void setMealList(ArrayList<Meal> listMeals) { 
    this.items = listMeals; 
    notifyDataSetChanged(); 
    notifyItemRangeChanged(0, listMeals.size()); 
} 
} 

SelectableAdapter.java:

public abstract class SelectableAdapter<VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> { 
@SuppressWarnings("unused") 
private static final String TAG = SelectableAdapter.class.getSimpleName(); 

private SparseBooleanArray selectedItems; 


public SelectableAdapter() { 
    selectedItems = new SparseBooleanArray(); 
} 


/** 
* Indicates if the item at position position is selected 
* @param position Position of the item to check 
* @return true if the item is selected, false otherwise 
*/ 
public boolean isSelected(int position) { 
    return getSelectedItems().contains(position); 
} 


/** 
* Toggle the selection status of the item at a given position 
* @param position Position of the item to toggle the selection status for 
*/ 
public void toggleSelection(int position) { 

    if (selectedItems.get(position, false)) { 
     selectedItems.delete(position); 
    } else { 
     selectedItems.put(position, true); 
    } 
    notifyItemChanged(position); 
} 

/** 
* Clear the selection status for all items 
*/ 
public void clearSelection() { 
    List<Integer> selection = getSelectedItems(); 
    selectedItems.clear(); 
    for (Integer i : selection) { 
     notifyItemChanged(i); 
    } 
} 

/** 
* Count the selected items 
* @return Selected items count 
*/ 
public int getSelectedItemCount() { 
    return selectedItems.size(); 
} 

/** 
* Indicates the list of selected items 
* @return List of selected items ids 
*/ 
public List<Integer> getSelectedItems() { 
    List<Integer> items = new ArrayList<>(selectedItems.size()); 
    for (int i = 0; i < selectedItems.size(); ++i) { 
     items.add(selectedItems.keyAt(i)); 
    } 
    return items; 
} 
} 

FragmentToday.java:

public class FragmentToday extends Fragment implements  Adapter.ViewHolder.ClickListener{ 
private RequestQueue requestQueue; 
public ArrayList<Meal> listMeals = new ArrayList<>(); 
private TextView textVolleyError; 
private MealSorter mSorter = new MealSorter(); 
private Adapter adapter; 
private ActionModeCallback actionModeCallback = new ActionModeCallback(); 
private ActionMode actionMode; 

public static FragmentToday newInstance() { 
    return new FragmentToday(); 
} 

public FragmentToday() { 
} 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    VolleySingleton volleySingleton = VolleySingleton.getInstance(); 
    requestQueue = volleySingleton.getRequestQueue(); 
    sendJsonRequest(); 

} 

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, 
         Bundle savedInstanceState) { 
    View view = inflater.inflate(R.layout.fragment_today, container, false); 
    textVolleyError = (TextView) view.findViewById(R.id.textVolleyError); 

    adapter = new Adapter(this); 

    RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.recycler_view); 
    recyclerView.setAdapter(adapter); 
    recyclerView.setItemAnimator(new DefaultItemAnimator()); 
    recyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); 

    sendJsonRequest(); 
    return view; 
} 

@Override 
public void onItemClicked(int position) { 
    if (actionMode != null) { 
     toggleSelection(position); 
    } 
} 

@Override 
public boolean onItemLongClicked(int position) { 
    if (actionMode != null) { 
     ((AppCompatActivity) getActivity()).startSupportActionMode(actionModeCallback); 
    } 

    toggleSelection(position); 

    return true; 
} 

private void toggleSelection(int position) { 
    adapter.toggleSelection(position); 
    int count = adapter.getSelectedItemCount(); 

    if (count == 0) { 
     actionMode.finish(); 
    } else { 
     actionMode.setTitle(String.valueOf(count)); 
     actionMode.invalidate(); 
    } 
} 

private class ActionModeCallback implements ActionMode.Callback { 
    @SuppressWarnings("unused") 
    private final String TAG = ActionModeCallback.class.getSimpleName(); 

    @Override 
    public boolean onCreateActionMode(ActionMode mode, Menu menu) { 
     mode.getMenuInflater().inflate (R.menu.menu_cam, menu); 
     return true; 
    } 

    @Override 
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) { 
     return false; 
    } 

    @Override 
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) { 
     switch (item.getItemId()) { 
      case R.id.favorite: 
       // TODO: actually remove items 
       Log.d(TAG, "menu_remove"); 
       mode.finish(); 
       return true; 

      default: 
       return false; 
     } 
    } 

    @Override 
    public void onDestroyActionMode(ActionMode mode) { 
     adapter.clearSelection(); 
     actionMode = null; 
    } 
} 

} 
+0

Big Cảm ơn bạn đã lưu trong ngày của tôi. –

+0

mẫu đẹp đã nhận được và đặt thành giao diện người dùng bộ chuyển đổi, cách triển khai chế độ hành động với xóa mẫu này thiếu một số mã mà tôi nghĩ là vui lòng cung cấp liên kết hoàn chỉnh hoặc mẫu – Harsha

+0

actionmode được điền và chỉ một mục được chọn tại một thời điểm cho ngữ cảnh chế độ hành động khi tôi nhấn mục thứ hai của nó không được chọn xin vui lòng giúp tôi – Harsha

Trả lời

7

Sự cố dường như là từ phương thức onItemLongClicked của lớp học FragmentToday.java. Nó cần phải có được:

@Override 
public boolean onItemLongClicked(int position) { 
    if (actionMode == null) { 
     actionMode = ((AppCompatActivity) getActivity()).startSupportActionMode(actionModeCallback); 
    } 

    toggleSelection(position); 

    return true; 
} 

thay vì:

@Override 
public boolean onItemLongClicked(int position) { 
    if (actionMode != null) { 
     ((AppCompatActivity) getActivity()).startSupportActionMode(actionModeCallback); 
    } 

    toggleSelection(position); 

    return true; 
} 
Các vấn đề liên quan