我正在尝试制作一个可扩展的RecyclerView适配器
,它将为父视图和子视图提供不同的布局。我以前从来没有做过可扩展的RecyclerView适配器
,所以我不知道这是否可能。下面是我的代码:
public class GroupsAdapter extends ExpandableRecyclerViewAdapter<GroupsAdapter.ParentVehicleViewHolder, GroupsAdapter.ChildItemViewHolder> {
//region final Fields
private final GroupsClickListener mOnItemClickListener;
private final Repository mRepository;
private boolean mIsClicked;
private int mFilterField;
private int mFilterType;
private int viewType;
//endregion
//region Fields
private List<ParentVehicle> mGroups = new ArrayList<>();
//endregion
//region Constructors
public GroupsAdapter(List<ParentVehicle> groups, Repository repository,
GroupsClickListener listener, boolean isClicked, int Layout) {
super(groups);
this.mOnItemClickListener = listener;
this.mRepository = repository;
this.mGroups = groups;
this.mIsClicked = isClicked;
this.viewType = Layout;
}
//endregion
@Override
public int getItemViewType(int position) {
if (position == 0){
viewType = 0;
}else {
viewType=1;
}
return viewType;
}
public int getViewTypeCount() {
return 2;
}
public void setData(List<ParentVehicle> groups, boolean isClicked) {
mGroups.clear();
mGroups.addAll(groups);
mIsClicked = isClicked;
notifyDataSetChanged();
}
public void setGroup(ParentVehicle group) {
mGroups.clear();
mGroups.add(group);
notifyDataSetChanged();
}
public void sortByName() {
if (mFilterField == Constants.FIELD_NAME) {
if (mFilterType == Constants.DECREASING) {
mFilterType = Constants.INCREASING;
Collections.sort(mGroups, new ParentVehicle.NameComparator());
if (mIsClicked) {
Collections.sort(mGroups.get(0).getVehicles(), new Vehicle.NameComparator());
}
} else {
mFilterType = Constants.DECREASING;
Collections.sort(mGroups, Collections.reverseOrder(new ParentVehicle.NameComparator()));
if (mIsClicked) {
Collections.sort(mGroups.get(0).getVehicles(), Collections.reverseOrder(new Vehicle.NameComparator()));
}
}
} else {
mFilterType = Constants.INCREASING;
mFilterField = Constants.FIELD_NAME;
Collections.sort(mGroups, new ParentVehicle.NameComparator());
if (mIsClicked) {
Collections.sort(mGroups.get(0).getVehicles(), new Vehicle.NameComparator());
}
}
notifyDataSetChanged();
}
public void sortByNumber() {
if (mFilterField == Constants.FIELD_ID) {
if (mFilterType == Constants.DECREASING) {
mFilterType = Constants.INCREASING;
Collections.sort(mGroups, new ParentVehicle.IdComparator());
if (mIsClicked) {
Collections.sort(mGroups.get(0).getVehicles(), new Vehicle.IdComparator());
}
} else {
mFilterType = Constants.DECREASING;
Collections.sort(mGroups, Collections.reverseOrder(new ParentVehicle.IdComparator()));
if (mIsClicked) {
Collections.sort(mGroups.get(0).getVehicles(), Collections.reverseOrder(new Vehicle.IdComparator()));
}
}
} else {
mFilterType = Constants.INCREASING;
mFilterField = Constants.FIELD_ID;
Collections.sort(mGroups, new ParentVehicle.IdComparator());
if (mIsClicked) {
Collections.sort(mGroups.get(0).getVehicles(), new Vehicle.IdComparator());
}
}
notifyDataSetChanged();
}
public void sortByDays() {
if (mFilterField == Constants.FIELD_DAYS) {
if (mFilterType == Constants.DECREASING) {
mFilterType = Constants.INCREASING;
Collections.sort(mGroups, new ParentVehicle.DaysComparator());
if (mIsClicked) {
Collections.sort(mGroups.get(0).getVehicles(), new Vehicle.DaysComparator());
}
} else {
mFilterType = Constants.DECREASING;
Collections.sort(mGroups, Collections.reverseOrder(new ParentVehicle.DaysComparator()));
if (mIsClicked) {
Collections.sort(mGroups.get(0).getVehicles(), Collections.reverseOrder(new Vehicle.DaysComparator()));
}
}
} else {
mFilterType = Constants.INCREASING;
mFilterField = Constants.FIELD_DAYS;
Collections.sort(mGroups, new ParentVehicle.DaysComparator());
if (mIsClicked) {
Collections.sort(mGroups.get(0).getVehicles(), new Vehicle.DaysComparator());
}
}
notifyDataSetChanged();
}
public void sortByGeo() {
if (mFilterField == Constants.FIELD_GEO) {
if (mFilterType == Constants.DECREASING) {
mFilterType = Constants.INCREASING;
Collections.sort(mGroups, new ParentVehicle.GeoComparator());
if (mIsClicked) {
Collections.sort(mGroups.get(0).getVehicles(), new Vehicle.GeoComparator());
}
} else {
mFilterType = Constants.DECREASING;
Collections.sort(mGroups, Collections.reverseOrder(new ParentVehicle.GeoComparator()));
if (mIsClicked) {
Collections.sort(mGroups.get(0).getVehicles(), Collections.reverseOrder(new Vehicle.GeoComparator()));
}
}
} else {
mFilterType = Constants.INCREASING;
mFilterField = Constants.FIELD_GEO;
Collections.sort(mGroups, new ParentVehicle.GeoComparator());
if (mIsClicked) {
Collections.sort(mGroups.get(0).getVehicles(), new Vehicle.GeoComparator());
}
}
notifyDataSetChanged();
}
public void sortByWarning() {
if (mFilterField == Constants.FIELD_WARNING) {
if (mFilterType == Constants.DECREASING) {
mFilterType = Constants.INCREASING;
Collections.sort(mGroups, new ParentVehicle.WarningComparator());
if (mIsClicked) {
Collections.sort(mGroups.get(0).getVehicles(), new Vehicle.WarningComparator());
}
} else {
mFilterType = Constants.DECREASING;
Collections.sort(mGroups, Collections.reverseOrder(new ParentVehicle.WarningComparator()));
if (mIsClicked) {
Collections.sort(mGroups.get(0).getVehicles(), Collections.reverseOrder(new Vehicle.WarningComparator()));
}
}
} else {
mFilterType = Constants.INCREASING;
mFilterField = Constants.FIELD_WARNING;
Collections.sort(mGroups, new ParentVehicle.WarningComparator());
if (mIsClicked) {
Collections.sort(mGroups.get(0).getVehicles(), new Vehicle.WarningComparator());
}
}
notifyDataSetChanged();
}
void filter(String text) {
List<Group> temp = new ArrayList();
for (Group group : getAllGroups()) {
if (group.getName().toLowerCase().contains(text)) {
temp.add(group);
}
}
if (TextUtils.isEmpty(text)) {
temp = getAllGroups();
}
//update recyclerview
//setData(temp);
}
private List<Group> getAllGroups() {
final List<Group> tempGroupList = new ArrayList<>();
if (!mRepository.getCompanies().isEmpty()) {
for (Company company : mRepository.getCompanies()) {
tempGroupList.addAll(Arrays.asList(company.getGroups()));
}
}
return tempGroupList;
}
//region expandableAdapterMethods
@Override
public ParentVehicleViewHolder onCreateGroupViewHolder(ViewGroup parent, int viewType) {
View view;
if (viewType==0){
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_table, parent, false);
return new ParentVehicleViewHolder(view,viewType);
} else if (viewType==1) {
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.delete_row, parent, false);
return new ParentVehicleViewHolder(view,viewType);
} return null;
}
@Override
public ChildItemViewHolder onCreateChildViewHolder(ViewGroup child, int viewType) {
View view;
if (viewType == 0) {
view = LayoutInflater.from(child.getContext()).inflate(R.layout.item_table, child, false);
return new ChildItemViewHolder(view, viewType);
} else if (viewType == 1) {
view = LayoutInflater.from(child.getContext()).inflate(R.layout.delete_row, child, false);
return new ChildItemViewHolder(view, viewType);
}return null;
}
@Override
public void onBindChildViewHolder(ChildItemViewHolder holder, int position, ExpandableGroup group, int childIndex) {
int viewType = getItemViewType(position);
if (viewType==0){
final Vehicle vehicle = ((ParentVehicle) group).getItems().get(childIndex);
holder.bind(vehicle, mOnItemClickListener);
} else if (viewType==1){
final Vehicle vehicle = ((ParentVehicle) group).getItems().get(childIndex);
holder.bind2(vehicle, mOnItemClickListener);
}
}
@Override
public void onBindGroupViewHolder(ParentVehicleViewHolder holder, int position, ExpandableGroup group) {
int viewType = getItemViewType(position);
if (viewType==0){
holder.bind(((ParentVehicle) group), mOnItemClickListener, mIsClicked);
} else if (viewType==1){
holder.bind2(((ParentVehicle) group), mIsClicked);
}
}
//endregion
static class ParentVehicleViewHolder extends GroupViewHolder {
TextView novText;
ImageView strelka;
TextView day7;
TextView day6;
TextView day5;
TextView day4;
TextView day3;
TextView day2;
TextView day1;
TextView mId;
TextView mNumber;
ImageView mBattery;
ImageView mGsimbol;
ImageView mWarning;
ImageView mGroupArrow;
private View mView;
public ParentVehicleViewHolder(View itemView, int viewType) {
super(itemView);
this.mView = itemView;
ButterKnife.bind(this, itemView);
if (viewType == 0) {
day7 = itemView.findViewById(R.id.number_7);
day6 = itemView.findViewById(R.id.number_6);
day5=itemView.findViewById(R.id.number_5);
day4=itemView.findViewById(R.id.number_4);
day3=itemView.findViewById(R.id.number_3);
day2=itemView.findViewById(R.id.number_2);
day1=itemView.findViewById(R.id.number_1);
mId=itemView.findViewById(R.id.item_unit_id);
mNumber=itemView.findViewById(R.id.item_number);
mBattery=itemView.findViewById(R.id.item_battery);
mGsimbol=itemView.findViewById(R.id.item_gsimbol);
mWarning=itemView.findViewById(R.id.icon_warning);
mGroupArrow=itemView.findViewById(R.id.group_arrow);
} else if (viewType==1){
novText=itemView.findViewById(R.id.item_numberEden);
strelka=itemView.findViewById(R.id.group_arrowEden);
}
}
public void bind(ParentVehicle parentVehicle, GroupsClickListener groupsClickListener, boolean showArrow) {
mNumber.setText(parentVehicle.getId());
mId.setText(parentVehicle.getName());
mId.setTextColor(mView.getContext().getResources().getColor(R.color.light_blue));
mView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (parentVehicle.isCompany()) {
groupsClickListener.onCompanyItemClick(parentVehicle.getId());
} else {
groupsClickListener.onGroupItemClick(parentVehicle.getId());
}
}
});
mGroupArrow.setVisibility(showArrow ? View.VISIBLE : View.GONE);
if (parentVehicle.getVehicles() != null && !parentVehicle.getVehicles().isEmpty()) {
if (isGeo(parentVehicle.getVehicles())) {
mGsimbol.setVisibility(View.INVISIBLE);
} else {
mGsimbol.setVisibility(View.VISIBLE);
}
if (isWarning(parentVehicle.getVehicles())) {
mWarning.setVisibility(View.VISIBLE);
} else {
mWarning.setVisibility(View.INVISIBLE);
}
}
day1.setBackgroundResource(isActiveDay(parentVehicle.getVehicles(), 0) ? R.drawable.green_rectangle : R.drawable.red_rectangle);
day2.setBackgroundResource(isActiveDay(parentVehicle.getVehicles(), 1) ? R.drawable.green_rectangle : R.drawable.red_rectangle);
day3.setBackgroundResource(isActiveDay(parentVehicle.getVehicles(), 2) ? R.drawable.green_rectangle : R.drawable.red_rectangle);
day4.setBackgroundResource(isActiveDay(parentVehicle.getVehicles(), 3) ? R.drawable.green_rectangle : R.drawable.red_rectangle);
day5.setBackgroundResource(isActiveDay(parentVehicle.getVehicles(), 4) ? R.drawable.green_rectangle : R.drawable.red_rectangle);
day6.setBackgroundResource(isActiveDay(parentVehicle.getVehicles(), 5) ? R.drawable.green_rectangle : R.drawable.red_rectangle);
day7.setBackgroundResource(isActiveDay(parentVehicle.getVehicles(), 6) ? R.drawable.green_rectangle : R.drawable.red_rectangle);
}
private boolean isGeo(List<Vehicle> vehicles) {
if (vehicles == null || vehicles.isEmpty()) {
return true;
}
for (Vehicle vehicle : vehicles) {
if (!vehicle.hasGeofenceAlarm()) {
return false;
}
}
return true;
}
private boolean isWarning(List<Vehicle> vehicles) {
if (vehicles == null || vehicles.isEmpty()) {
return false;
}
for (Vehicle vehicle : vehicles) {
if (vehicle.isWarning()) {
return true;
}
}
return false;
}
private boolean isActiveDay(List<Vehicle> vehicles, int day) {
if (vehicles == null || vehicles.isEmpty()) {
return true;
}
for (Vehicle vehicle : vehicles) {
if (vehicle.getDays() == null || vehicle.getDays().length == 0 || !vehicle.getDays()[day]) {
return false;
}
}
return true;
}
public void bind2(ParentVehicle parentVehicle, boolean showArrow) {
novText.setText(parentVehicle.getName());
strelka.setVisibility(showArrow ? View.VISIBLE : View.GONE);
}
}
static class ChildItemViewHolder extends ChildViewHolder {
TextView novText2;
TextView day7;
TextView day6;
TextView day5;
TextView day4;
TextView day3;
TextView day2;
TextView day1;
TextView mId;
ImageView mBattery;
ImageView mGsimbol;
ImageView mWarning;
private View mView;
public ChildItemViewHolder(View itemView, int viewType) {
super(itemView);
this.mView = itemView;
ButterKnife.bind(this, itemView);
if (viewType==0){
day7 = itemView.findViewById(R.id.number_7);
day6 = itemView.findViewById(R.id.number_6);
day5=itemView.findViewById(R.id.number_5);
day4=itemView.findViewById(R.id.number_4);
day3=itemView.findViewById(R.id.number_3);
day2=itemView.findViewById(R.id.number_2);
day1=itemView.findViewById(R.id.number_1);
mId=itemView.findViewById(R.id.item_unit_id);
mBattery=itemView.findViewById(R.id.item_battery);
mGsimbol=itemView.findViewById(R.id.item_gsimbol);
mWarning=itemView.findViewById(R.id.icon_warning);
} else if (viewType==1){
novText2=itemView.findViewById(R.id.item_numberEden);
}
}
public void bind(Vehicle vehicle, GroupsClickListener onItemClickListener) {
mId.setText(vehicle.getName());
if (vehicle.hasGeofenceAlarm()) {
mGsimbol.setVisibility(View.INVISIBLE);
} else {
mGsimbol.setVisibility(View.VISIBLE);
}
if (vehicle.isWarning()) {
mWarning.setVisibility(View.VISIBLE);
} else {
mWarning.setVisibility(View.INVISIBLE);
}
mView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onItemClickListener.onGroupChildItemClick(vehicle.getId());
}
});
day1.setBackgroundResource(vehicle.getDays()[0] ? R.drawable.green_rectangle : R.drawable.red_rectangle);
day2.setBackgroundResource(vehicle.getDays()[1] ? R.drawable.green_rectangle : R.drawable.red_rectangle);
day3.setBackgroundResource(vehicle.getDays()[2] ? R.drawable.green_rectangle : R.drawable.red_rectangle);
day4.setBackgroundResource(vehicle.getDays()[3] ? R.drawable.green_rectangle : R.drawable.red_rectangle);
day5.setBackgroundResource(vehicle.getDays()[4] ? R.drawable.green_rectangle : R.drawable.red_rectangle);
day6.setBackgroundResource(vehicle.getDays()[5] ? R.drawable.green_rectangle : R.drawable.red_rectangle);
day7.setBackgroundResource(vehicle.getDays()[6] ? R.drawable.green_rectangle : R.drawable.red_rectangle);
}
public void bind2(Vehicle vehicle, GroupsClickListener onItemClickListener) {
novText2.setText(vehicle.getName());}
}
}
我得到了这个错误:
java.lang.IllegalArgumentException:viewType在Com.Thoughtbot.ExpandableRecyclerView.ExpandableRecyclerViewAdapter.OnCreateViewWholder(ExpandableRecyclerViewAdapter.57)在Android.Support.v7.Widget.RecyclerView$Adapter.CreateViewWholder(ExpandableRecyclerView.java:6493)在Android.Support.v7.Widget.RecyclerView在Android.support.v7.Widget.RecyclerView.OnMeasure(RecyclerView.java:3109)在Android.View.View.Measure(View.java:18930)在Android.View.View.Measure(View.java:18930)在Android.View.View.Measure(View.java:5976)在Android.Widget.LinearLayout.MeasureChildWithMargins(ViewGroup.MeasureChildBeforelayout(LinearLayout.java:)在Android.View.ViewGroup.MeasureChildWithMargins(ViewGroup.java:5976)在Android.Widget.LinearLayout.MeasureChildBeforelayout(LinearLayout.java:1486)在Android.Widget.LinearLayout.MeasureHorizonal(LinearLayout.java:1129)在Android.Widget.LinearLayout.OnMeasure(LinearLayout.java:649)在76)在Android.Widget.LinearLayout.MeasureChildbeForelayout(LinearLayout.java:1486)在Android.Widget.LinearLayout.MeasureVertical(LinearLayout.java:765)在Android.Widget.LinearLayout.OnMeasure(LinearLayout.java:647)在Android.View.View.Measure(View.java:18930)在Android.View.View.Measure(View.java:5976)在
块引号
我做错了什么?为什么我得到的viewType无效?
我尝试使用相同的ExpandableRecyclerViewAdapter,我想指出几点。
首先,关于您的错误,之所以会出现这种情况,是因为如果您查看ExpandableRecyclerViewAdapter类的OnCreateViewWholder方法,它需要的是两个值分别为2和1的ExpandableListPosition.Group或ExpandableListPosition.Child中的任何一个。
现在,您犯的第一个错误是将getItemViewType用viewtype值复盖为0和1,其中1已经在library中使用,因此它会按照library类向您抛出非法异常,这是正确的。
为了获得多个子视图,
首先,使用MultiTypeExpandableRecyclerViewAdapter扩展适配器类,并创建两个扩展ChildViewWholder的类,然后,如果您看到类扩展声明,它将如下所示:
public class ScoreCardDataAdapter extends MultiTypeExpandableRecyclerViewAdapter<TeamScoreCardViewHolder, ChildViewHolder> {
此外,我为viewtype使用了2个变量,分别为值3和4的TYPE_HEADER和TYPE_ITEM。您可以使用任何东西,但要确保它大于2。
然后重写以下方法:
@Override
public boolean isChild(int viewType) {
return viewType == TYPE_HEADER || viewType == TYPE_ITEM;
}
在这个方法中,我实现了一个方法,表示第一个位置是头,并返回TYPE_HEADER。
@Override
public int getChildViewType(int position, ExpandableGroup group, int childIndex) {
if(isPositionHeader(childIndex))
return TYPE_HEADER;
else
return TYPE_ITEM;
}
private boolean isPositionHeader(int position) {
return position == 0;
}
然后在OnCreateChildViewWholder中,
您可以检查视图类型并返回预期的ViewWholder。
并通过调用以下方法绑定viewholder:
@Override
public void onBindChildViewHolder(ChildViewHolder holder, int flatPosition, ExpandableGroup group,
int childIndex) {
int viewType = getItemViewType(flatPosition);
//here based on the view type pass the appropriate data.
}
请看下面我完整的适配器类实现,供您参考。
public class ScoreCardDataAdapter extends MultiTypeExpandableRecyclerViewAdapter<TeamScoreCardViewHolder, ChildViewHolder> {
private static final int TYPE_HEADER = 3;
private static final int TYPE_ITEM = 4;
public ScoreCardDataAdapter(Fragment fragment, List<? extends ExpandableGroup> groups) {
super(groups);
}
@Override
public TeamScoreCardViewHolder onCreateGroupViewHolder(ViewGroup parent, int viewType) {
final View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.team_score_card_parent_view_holder, parent, false);
return new TeamScoreCardViewHolder(view);
}
@Override
public ChildViewHolder onCreateChildViewHolder(ViewGroup parent, final int viewType) {
if(viewType == TYPE_ITEM) {
final View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.team_score_card_data_child_view_holder, parent, false);
return new ScoreCardDataViewHolder(view, TYPE_ITEM);
} else if(viewType == TYPE_HEADER) {
final View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.header_item, parent, false);
return new ScoreCardHeaderViewHolder(view, TYPE_HEADER);
}
throw new RuntimeException("there is no type that matches the type " + viewType + " + make sure your using types correctly");
}
@Override
public void onBindChildViewHolder(ChildViewHolder holder, int flatPosition, ExpandableGroup group, int childIndex) {
int viewType = getItemViewType(flatPosition);
if(viewType == TYPE_HEADER) {
//Currently I am passing string and binding it to ScoreCardHeaderViewHolder
// but we can pass any data.
((ScoreCardHeaderViewHolder) holder).onBind("batsman");
} else if(viewType == TYPE_ITEM) {
//here I am getting my data from api passed to adapter and binding it to the ScoreCardDataViewHolder
final BattingData battingData = ((BattingDataExpandable) group).getItems().get(childIndex);
((ScoreCardDataViewHolder) holder).onBind(battingData, group, childIndex);
}
}
@Override
public void onBindGroupViewHolder(TeamScoreCardViewHolder holder, int flatPosition, ExpandableGroup group) {
holder.setTeamName(group);
}
@Override
public boolean isChild(int viewType) {
return viewType == TYPE_HEADER || viewType == TYPE_ITEM;
}
@Override
public int getChildViewType(int position, ExpandableGroup group, int childIndex) {
if(isPositionHeader(position))
return TYPE_HEADER;
else
return TYPE_ITEM;
}
private boolean isPositionHeader(int position) {
return position == 0;
}
}
我想用不同的布局定义2个不同的log4j控制台。我尝试了以下方法: 然而,当我尝试使用这些appender时,我遇到了问题。我将第一个appender连接到root,然后尝试将第二个appender连接到某些祖先记录器: 我遇到的麻烦是,来自这两个祖先记录器的消息最终会转到stdout appender,而不是stdoutMDC appender。我尝试了禁用和不禁用相加,但没有区别。 有什么想法
我得到了这个错误,但我不知道是什么原因导致的...也许是因为它是在一个片段中初始化的,而不是在activity本身。编辑:包含的StatsAdapter代码
在Vuetify中可扩展表的基本代码笔中,我注意到当表中两个条目的名称相同时,单击row to expand也会扩展具有相同名称条目的另一行。有没有办法避免这种情况? 以下是重新创建的问题:https://codepen.io/entropy283/pen/eyjdmlp?editable=true&editors=101%3dhttps%3a%2f%2fvuetifyjs.com%2fen%2f
我正在尝试显示3个选项时,图标设置点击。我想覆盖它,它实际上工作(好好的)。 我的问题是第二个布局高度是手动设置的,我想改变它的高度与正常框(它的一个布局回收器视图项)相同。 有没有人可以帮助我如何设置第二个项目的高度与前一个项目的高度相同?我在OnBindViewWholder中尝试过,但没有成功 在照片下,我将添加来自适配器的xml文件和代码 适配器:
ListPetientFragment。JAVA 错误是:2021-11-17 18:41:02.417 29997-29997/?E/rtphonemedicat:运行时设置的未知位_标志:0x8000 2021-11-17 18:41:03.628 29997-30029/com。尼戈特。smartphonemedicate E/GED:无法获取GED日志Buf,错误(0)2021-11-17
适配器内的代码是