我正在运行一个适配器,该适配器显示食品列表,用户应该在其中在EditText中输入相应的数量。
如果用户按下软键盘的确认按钮,则一切正常,适配器将通过OnEditorActionListener或什至附加的OnFocusChangeListener正确读取金额。
但是,如果用户直接点击视图的FAB,则不会记录该金额,因为不会调用OnEditorActionListener或OnFocusChangeListener。
在这种非常可能的情况下,如何确保正确记录了金额?
这是我的适配器类代码:
public class FoodCalcAdapter extends RecyclerView.Adapter<FoodCalcAdapter.FoodViewHolder> {
class FoodViewHolder extends RecyclerView.ViewHolder implements AdapterView.OnItemSelectedListener {
// The views of the food calc item
private final TextView foodnameView;
private final EditText amountView;
private final Spinner typicalAmountSpinner;
private FoodViewHolder(View itemView) {
super(itemView);
foodnameView = itemView.findViewById(R.id.newmeal_foodname);
typicalAmountSpinner = itemView.findViewById(R.id.newmeal_typicalamountspinner);
amountView = itemView.findViewById(R.id.newmeal_amount);
amountView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
int amount = Integer.parseInt(v.getText().toString());
storeAmount(amount);
return true;
}
return false;
}
});
amountView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
String text = ((EditText) v).getText().toString();
int amount = Integer.parseInt(text);
storeAmount(amount);
}
}
});
}
private void storeAmount(int amount) {
// Store the amount in the first spinner item
TypicalAmount typicalAmount = (TypicalAmount) typicalAmountSpinner.getItemAtPosition(0);
typicalAmount.setAmount(amount);
// ... and store it in the food
selectedFood.get(getAdapterPosition()).setAmount(amount);
}
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
// On selecting a spinner item, write amount to amount view ...
TypicalAmount typicalAmount = (TypicalAmount) parent.getItemAtPosition(position);
amountView.setText(String.valueOf(typicalAmount.getAmount()));
// ... and store it as amount in the food
selectedFood.get(getAdapterPosition()).setAmount(typicalAmount.getAmount());
// If a typical amount (position > 0) is selected, we disable entering text,
// if custom amount (position == 0) is selected, we enable entering text
if (position == 0) {
amountView.setEnabled(true);
amountView.selectAll();
} else {
amountView.setEnabled(false);
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
// Nothing to do here
}
}
private final LayoutInflater mInflater;
private List<Food> selectedFood; // Cached copy of all selected food items
FoodCalcAdapter(Context context) {
mInflater = LayoutInflater.from(context);
}
@Override
public FoodViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// Create the food calc item
View itemView = mInflater.inflate(R.layout.food_calc_item, parent, false);
return new FoodViewHolder(itemView);
}
@Override
public void onBindViewHolder(FoodViewHolder holder, int position) {
if (selectedFood != null) {
// Get the current food item
Food food = selectedFood.get(position);
// Set the food name
holder.foodnameView.setText(food.getName());
// Create typical amount spinner
List<TypicalAmount> typicalAmounts = new ArrayList<>();
// First entry should always contain the custom amount, which is by default 0 when first used here
typicalAmounts.add(new TypicalAmount(food.getAmount(), null, mInflater.getContext().getString(R.string.newmeal_customamount)));
// Append typical amounts
appendTypicalAmount(typicalAmounts, food.getAmountSmall(), food.getCommentSmall(), mInflater.getContext().getString(R.string.amountsmall_label));
appendTypicalAmount(typicalAmounts, food.getAmountMedium(), food.getCommentMedium(), mInflater.getContext().getString(R.string.amountmedium_label));
appendTypicalAmount(typicalAmounts, food.getAmountLarge(), food.getCommentLarge(), mInflater.getContext().getString(R.string.amountlarge_label));
// Create adapter and add to spinner
ArrayAdapter<TypicalAmount> typicalAmountAdapter = new ArrayAdapter<>(mInflater.getContext(), R.layout.support_simple_spinner_dropdown_item, typicalAmounts);
typicalAmountAdapter.setDropDownViewResource(R.layout.support_simple_spinner_dropdown_item);
holder.typicalAmountSpinner.setOnItemSelectedListener(holder);
holder.typicalAmountSpinner.setAdapter(typicalAmountAdapter);
// Highlight custom amount text to make it easier to edit it
holder.amountView.selectAll();
} else {
// Covers the case no food has been selected (should never happen, we check before)
holder.foodnameView.setText(mInflater.getContext().getString(R.string.newmeal_nofoodselected));
}
}
void setSelectedFood(List<Food> selectedFood) {
this.selectedFood = selectedFood;
}
List<Food> getSelectedFood() {
return selectedFood;
}
private void appendTypicalAmount(List<TypicalAmount> typicalAmounts, int amount, String comment, String defaultComment) {
if (amount > 0) {
typicalAmounts.add(new TypicalAmount(amount, comment, defaultComment));
}
}
// getItemCount() is called many times, and when it is first called,
// allFood has not been updated (means initially, it's null, and we can't return null)
@Override
public int getItemCount() {
if (selectedFood != null)
return selectedFood.size();
else return 0;
}
}
建议通过单击FAB来检索值,但是我不知道如何处理,因为FAB是在Adapter类之外,周围的Activity类中创建的,因此我无法从中访问单个ViwHolders在适配器内。这是周围活动的代码:
public class NewMealActivity extends AppCompatActivity {
public static final String INTENT_FOODCALC = "FoodCalc";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_meal);
// Create recycler view
RecyclerView recyclerView = findViewById(R.id.recyclerview_newmeal);
final FoodCalcAdapter adapter = new FoodCalcAdapter(this);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
// Pass selected food to adapter
List<Food> selectedFood = getIntent().getParcelableArrayListExtra(MainActivity.INTENT_FOODLIST);
adapter.setSelectedFood(selectedFood);
// Floating action button to calculate meal
FloatingActionButton fabCalc = findViewById(R.id.fab_calcmeal);
fabCalc.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(NewMealActivity.this, CalcMealActivity.class);
// Get all selected food, each weighted with its amount
ArrayList<Food> weightedFood = new ArrayList<Food>(adapter.getSelectedFood());
// Set to intent
Intent weightedFoodList = intent.putParcelableArrayListExtra(INTENT_FOODCALC, weightedFood);
// Start activity
startActivity(intent);
}
});
}
}