1 回答
TA贡献1811条经验 获得超4个赞
您可以使用Google Android架构中的LiveData以及一些接口来实现您想要的。
-> 声明Interfaces
您需要调用的各种方法ViewHolders
来实现您想要的逻辑
interface AnimalVolumeChangeListener{
public void onAnimalVolumeChanged(int groupId, double previousVolume, double currentVolume);
}
interface TotalVolumeInterface{
public Pair<LifecycleOwner,LiveData<Double>> getTotalVolume(int groupId);
public void removeObservers(int groupId);
}
-> 将这些接口作为对象传递到 Recycler Adapter 的构造函数中。
class Animal_Volume_Adapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private ArrayList<AnimalsArray> mList;
private TotalVolumeInterface mTotalVolumeInterface;
private AnimalVolumeChangeListener mAnimalVolumeChangeListener;
private double volume = 0;
public Animal_Volume_Adapter(ArrayList<AnimalsArray> list,
TotalVolumeInterface totalVolumeInterface,
AnimalVolumeChangeListener animalVolumeChangeListener) {
this.mList = list;
this.mTotalVolumeInterface = totalVolumeInterface;
this.mAnimalVolumeChangeListener = animalVolumeChangeListener;
}
-> 在创建视图持有者时将您作为参数传递给相应视图持有者的接口设置
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case AnimalsArray.TOP:
View top = LayoutInflater.from(parent.getContext()).inflate(R.layout.animal_top_layout, parent, false);
return new Top(top);
case AnimalsArray.MIDDLE:
View data = LayoutInflater.from(parent.getContext()).inflate(R.layout.animal_middle_layout, parent, false);
Middle middleHolder = new Middle(data);
middleHolder.setAnimalVolumeChangeListener(mAnimalVolumeChangeListener);
return middleHolder;
case AnimalsArray.BOTTOM:
View footer = LayoutInflater.from(parent.getContext()).inflate(R.layout.animal_bottom_layout, parent, false);
Bottom bottomHolder = new Bottom(footer);
bottomHolder.setTotalVolumeInterface(mTotalVolumeInterface);
return bottomHolder;
}
return null;
}
修改ViewHolder类
static class Middle extends RecyclerView.ViewHolder {
Context context;
EditText weight;
EditText quantity;
TextView volume;
AnimalVolumeChangeListener animalVolumeChangeListener;
Middle(final View itemView) {
super(itemView);
context = itemView.getContext();
volume = (EditText) itemView.findViewById(R.id.volume);
weight = (EditText) itemView.findViewById(R.id.weight);
quantity= (EditText) itemView.findViewById(R.id.quantity);
}
public void setAnimalVolumeChangeListener(AnimalVolumeChangeListener animalVolumeChangeListener) {
this.animalVolumeChangeListener = animalVolumeChangeListener;
}
}
static class Bottom extends RecyclerView.ViewHolder {
TextView volume;
TotalVolumeInterface totalVolumeInterface;
Bottom(View itemView) {
super(itemView);
volume = (TextView) itemView.findViewById(R.id.volumeText);
}
public void setTotalVolumeInterface(TotalVolumeInterface totalVolumeInterface) {
this.totalVolumeInterface = totalVolumeInterface;
}
}
-> 在需要时从 onBindViewHolder 中的界面调用方法。
在您的情况下,您需要有一种方法来识别 ViewHolderMiddle的总体积对 ViewHolder 的值有贡献Bottom(因此下面我用来groupId表示此参数)。
@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
final AnimalsArray object = mList.get(position);
/* middle holders contributing to the total volume of the same have the
*same groupId together with their corressponding bottom holder.
*TODO: Assigned this value in accordance to however you are assigning Middle ViewHolders to Bottom ViewHolders*/
int groupId = 0;
if (object != null) {
switch (object.getCategory()) {
case AnimalsArray.TOP:
break;
case AnimalsArray.MIDDLE:
Middle middleHolder = (Middle) holder;
middleHolder.weight.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
}
@Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
}
@Override
public void afterTextChanged(Editable arg0) {
//While this edittext is being changed, I would like the 3rd viewtype which contains the volume to be calculated on the fly as the user enters numbers in this field.
String volumeBeforeChange = middleHolder.volume.getText().toString();
double previousVolume = Double.parseDouble(volumeBeforeChange);
if (arg0.toString().isEmpty() || arg0.toString().length() <= 0 || arg0.toString().equals("") || arg0.toString() == null || arg0.toString().equals("0") || arg0.toString().startsWith(".")) {
middleHolder.weight.setText("0");
middleHolder.animalVolumeChangeListener.onAnimalVolumeChanged(middleHolder.groupId,previousVolume,0);
} else {
volume = calculateWarmUpVolume(context, arg0.toString(), ((Middle) holder).quantity.getText().toString());
middleHolder.animalVolumeChangeListener.onAnimalVolumeChanged(middleHolder.groupId,previousVolume,volume);
}
}
});
middleHolder.quantity.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
}
@Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
}
@Override
public void afterTextChanged(Editable arg0) {
//While this edittext is being changed, I would like the 3rd viewtype which contains the volume to be calculated on the fly as the user enters numbers in this field.
String volumeBeforeChange = middleHolder.volume.getText().toString();
double previousVolume = Double.parseDouble(volumeBeforeChange);
if (arg0.toString().isEmpty() || arg0.toString().length() <= 0 || arg0.toString().equals("") || arg0.toString() == null || arg0.toString().equals("0") || arg0.toString().startsWith(".")) {
((Middle) holder).quantity.setText("0");
middleHolder.animalVolumeChangeListener.onAnimalVolumeChanged(middleHolder.groupId,previousVolume,0);
} else {
volume = calculateWarmUpVolume(context, ((Middle) holder).weight.getText().toString(), arg0.toString());
middleHolder.animalVolumeChangeListener.onAnimalVolumeChanged(middleHolder.groupId,previousVolume,volume);
}
}
});
break;
case AnimalsArray.BOTTOM:
Bottom bottomHolder = ((Bottom) holder);
Pair<LifecycleOwner, LiveData<Double>> totalVolumePair = bottomHolder.totalVolumeInterface.getTotalVolume(groupId);
totalVolumePair.second.observe(totalVolumePair.first,
new Observer<Double>(){
@Override
public void onChanged(Double aDouble) {
//Check if double is a whole number. If it is, remove decimal by converting to integer
String volumedWeight;
if ((aDouble % 1) == 0) {
int roundedVolume = aDouble.intValue();
volumedWeight = Integer.toString(roundedVolume);
} else {
volumedWeight = Double.toString(volume);
}
bottomHolder.volume.setText(String.valueOf(volumedWeight));
}
}
);
break;
}
}
}
@Override
public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) {
super.onViewRecycled(holder);
/* middle holders contributing to the total volume of the same have the
*same groupId together with their corressponding bottom holder.
*/
int groupId = 0;
if(holder instanceof Bottom){
((Bottom) holder).totalVolumeInterface.removeObservers(groupId);
}
}
-> 最后为接口的重写方法编写逻辑。
public class SetupRecyclerClass extends AppCompatActivity implements TotalVolumeInterface, AnimalVolumeChangeListener{
HashMap<Integer, MutableLiveData<Double>> mTotalVolumesMap = new HashMap<>();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ArrayList<AnimalsArray> animalsArrayArrayList = new ArrayList<>();
Animal_Volume_Adapter adapter = new Animal_Volume_Adapter(animalsArrayArrayList,this, this);
}
@Override
public Pair<LifecycleOwner, LiveData<Double>> getTotalVolume(int groupId) {
if(mTotalVolumesMap.get(groupId) == null){
mTotalVolumesMap.put(groupId,new MutableLiveData<>(0.0));
}
return new Pair<>(this,mTotalVolumesMap.get(groupId));
}
@Override
public void removeObservers(int groupId) {
mTotalVolumesMap.get(groupId).removeObservers(this);
}
@Override
public void onAnimalVolumeChanged(int groupId, double previousVolume, double currentVolume) {
if(mTotalVolumesMap.get(groupId) == null){
mTotalVolumesMap.put(groupId,new MutableLiveData<>(0.0));
}
double newTotalVolume = (mTotalVolumesMap.get(groupId).getValue()-previousVolume)+currentVolume;
mTotalVolumesMap.get(groupId).setValue(newTotalVolume);
}
}
希望这可以帮助。
添加回答
举报