9

Я взломал свое первое приложение из кучи учебников. С помощью одного из них я реализовал RecyclerView внутри фрагмента, который используется основным действием. Теперь я нашел another tutorial, который я хочу использовать для реализации множественного выбора в режиме контекстного действия. Большая проблема заключается в том, что в учебнике не используется фрагмент. Я попытался переписать код, чтобы он поместился в фрагмент. Я нахожусь теперь в точке, где я не получаю никаких ошибок в Android Studio и прогонов приложения, но когда я на самом деле сделать LongClick, чтобы выбрать элемент, он падает с NullPointerException:Проблемы с реализацией режима контекстного действия в фрагменте recyclerview

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

Я полностью потерял мнение о том, почему это происходит и с целым мульти-отборным материалом в целом.

Я думаю, что соответствующие части каждого участвующих классов:

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

Большое спасибо вы сохранили мой день. –

+0

nice sample am уже api получение данных и установка в пользовательский интерфейс адаптера, как реализовать режим действия с удалением этого образца отсутствует какой-либо код, я думаю, пожалуйста, укажите завершенные или примерные ссылки – Harsha

+0

actionmode заполняется и только один элемент выбирается за контекст режим действия, когда я нажимаю второй элемент, его не выбрали, пожалуйста, помогите мне – Harsha

ответ

7

Проблема, как представляется, из вашего onItemLongClicked метода в FragmentToday.java класса. Это должно было быть:

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

    toggleSelection(position); 

    return true; 
} 

вместо:

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

    toggleSelection(position); 

    return true; 
}