如何在RecyclerView Viewholder中根据航班经停数加载对应XML布局
如何在RecyclerView中根据航班经停数加载不同布局
嘿,这个需求我在做航班查询列表的时候正好实现过,其实核心就是利用RecyclerView Adapter的多布局类型特性来搞定,步骤很清晰,给你一步步拆解:
1. 定义布局类型常量
首先在你的Adapter类里,先把不同经停情况对应的布局类型定义成常量,避免用魔法数字,可读性更高:
public class FlightAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { // 无经停布局类型 private static final int TYPE_NON_STOP = 0; // 两经停布局类型 private static final int TYPE_TWO_STOPS = 1; // 可以根据需求加更多类型,比如一经停、三经停等 private List<Flight> mFlightList; // 构造方法初始化数据列表 public FlightAdapter(List<Flight> flightList) { this.mFlightList = flightList; } }
2. 重写getItemViewType方法
这是实现多布局的核心:根据当前位置的航班数据(经停数),返回对应的布局类型。
@Override public int getItemViewType(int position) { Flight flight = mFlightList.get(position); // 假设Flight类里有getStopCount()方法返回经停数量 int stopCount = flight.getStopCount(); if (stopCount == 0) { return TYPE_NON_STOP; } else if (stopCount == 2) { return TYPE_TWO_STOPS; } // 默认返回无经停类型,或者根据你的需求调整 return TYPE_NON_STOP; }
3. 创建对应布局的ViewHolder
如果不同布局的控件差异比较大,建议为每种布局单独写一个ViewHolder类,这样代码更清晰:
// 无经停航班的ViewHolder public static class NonStopViewHolder extends RecyclerView.ViewHolder { TextView tvFlightNumber; TextView tvDepartureArrival; public NonStopViewHolder(@NonNull View itemView) { super(itemView); tvFlightNumber = itemView.findViewById(R.id.tv_non_stop_flight_num); tvDepartureArrival = itemView.findViewById(R.id.tv_non_stop_dep_arr); } } // 两经停航班的ViewHolder public static class TwoStopsViewHolder extends RecyclerView.ViewHolder { TextView tvFlightNumber; TextView tvFirstStop; TextView tvSecondStop; TextView tvDepartureArrival; public TwoStopsViewHolder(@NonNull View itemView) { super(itemView); tvFlightNumber = itemView.findViewById(R.id.tv_two_stops_flight_num); tvFirstStop = itemView.findViewById(R.id.tv_first_stop); tvSecondStop = itemView.findViewById(R.id.tv_second_stop); tvDepartureArrival = itemView.findViewById(R.id.tv_two_stops_dep_arr); } }
4. 在onCreateViewHolder中加载对应布局
根据getItemViewType返回的类型,inflate对应的XML布局,并返回对应的ViewHolder:
@NonNull @Override public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { LayoutInflater inflater = LayoutInflater.from(parent.getContext()); if (viewType == TYPE_NON_STOP) { View view = inflater.inflate(R.layout.item_flight_non_stop, parent, false); return new NonStopViewHolder(view); } else if (viewType == TYPE_TWO_STOPS) { View view = inflater.inflate(R.layout.item_flight_two_stops, parent, false); return new TwoStopsViewHolder(view); } // 默认返回无经停布局的ViewHolder View view = inflater.inflate(R.layout.item_flight_non_stop, parent, false); return new NonStopViewHolder(view); }
5. 在onBindViewHolder中绑定对应数据
这里需要判断ViewHolder的类型,然后针对性地绑定数据:
@Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { Flight flight = mFlightList.get(position); if (holder instanceof NonStopViewHolder) { NonStopViewHolder nonStopHolder = (NonStopViewHolder) holder; nonStopHolder.tvFlightNumber.setText(flight.getFlightNumber()); nonStopHolder.tvDepartureArrival.setText(flight.getDepartureCity() + " → " + flight.getArrivalCity()); } else if (holder instanceof TwoStopsViewHolder) { TwoStopsViewHolder twoStopsHolder = (TwoStopsViewHolder) holder; twoStopsHolder.tvFlightNumber.setText(flight.getFlightNumber()); twoStopsHolder.tvDepartureArrival.setText(flight.getDepartureCity() + " → " + flight.getArrivalCity()); // 绑定经停点数据 twoStopsHolder.tvFirstStop.setText("经停1:" + flight.getFirstStopCity()); twoStopsHolder.tvSecondStop.setText("经停2:" + flight.getSecondStopCity()); } }
一些额外的小提示
- 如果不同布局的控件差异很小,也可以用同一个布局文件,通过
setVisibility()来显示/隐藏不同控件,但如果布局结构差异大,还是分开布局更利于后续维护。 - 记得在Adapter里重写
getItemCount()方法,返回数据列表的长度:
@Override public int getItemCount() { return mFlightList == null ? 0 : mFlightList.size(); }
这样就能完美实现根据航班经停数加载对应布局的需求啦!
内容的提问来源于stack exchange,提问作者Sai Jayant
相关产品推荐
相关产品推荐

