如何在Android RecyclerView中展示PHP返回的JSON表格数据?
没问题,这完全可以实现!咱们一步步来解决这个问题:
第一步:解析JSON响应
首先得把PHP返回的JSON转换成Android端可用的数据结构。你的JSON是一个包含两个数组的大集合:第一个数组存列名,第二个数组是所有行的列值(按顺序拼接,每8个值对应一行,刚好匹配列名的数量)。
这里用Gson来解析示例代码(如果用原生JSONObject逻辑类似):
// 临时类用于解析列名 class ColumnName { String column_name; } // 临时类用于解析列值 class ColumnValue { String column_value; } // 假设response是你从网络请求拿到的JSON字符串 Type listType = new TypeToken<List<List<Object>>>() {}.getType(); List<List<Object>> jsonData = new Gson().fromJson(response, listType); // 提取列名列表 List<ColumnName> columnNames = new Gson().fromJson( new Gson().toJson(jsonData.get(0)), new TypeToken<List<ColumnName>>() {}.getType() ); List<String> headers = new ArrayList<>(); for (ColumnName name : columnNames) { headers.add(name.column_name.trim()); } int columnCount = headers.size(); // 这里固定为8 // 提取列值并分组为行数据 List<ColumnValue> allValues = new Gson().fromJson( new Gson().toJson(jsonData.get(1)), new TypeToken<List<ColumnValue>>() {}.getType() ); List<List<String>> rows = new ArrayList<>(); for (int i = 0; i < allValues.size(); i += columnCount) { List<String> row = new ArrayList<>(); for (int j = 0; j < columnCount; j++) { if (i + j < allValues.size()) { row.add(allValues.get(i + j).column_value.trim()); // 清理多余空格 } } rows.add(row); }
解析完成后,你会得到两个核心集合:headers(所有列名)和rows(每行对应的列值)。
第二步:设计RecyclerView的布局
我们需要两种布局:表头布局和数据行布局,都用水平LinearLayout来排列每列内容:
表头布局 item_table_header.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/ll_header" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#f5f5f5" android:orientation="horizontal" android:paddingVertical="10dp" android:paddingHorizontal="4dp"> </LinearLayout>
数据行布局 item_table_row.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/ll_row" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:paddingVertical="8dp" android:paddingHorizontal="4dp"> </LinearLayout>
第三步:自定义RecyclerView Adapter
因为要区分表头和数据行,我们用多类型Adapter来实现:
public class TableAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private static final int TYPE_HEADER = 0; private static final int TYPE_ROW = 1; private List<String> headers; private List<List<String>> rows; private Context context; public TableAdapter(Context context, List<String> headers, List<List<String>> rows) { this.context = context; this.headers = headers; this.rows = rows; } @Override public int getItemViewType(int position) { return position == 0 ? TYPE_HEADER : TYPE_ROW; } @NonNull @Override public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { LayoutInflater inflater = LayoutInflater.from(context); if (viewType == TYPE_HEADER) { View view = inflater.inflate(R.layout.item_table_header, parent, false); return new HeaderViewHolder(view); } else { View view = inflater.inflate(R.layout.item_table_row, parent, false); return new RowViewHolder(view); } } @Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { if (holder instanceof HeaderViewHolder) { HeaderViewHolder headerHolder = (HeaderViewHolder) holder; headerHolder.linearLayout.removeAllViews(); // 动态添加表头文本框 for (String header : headers) { TextView tv = createTextView(true); tv.setText(header); headerHolder.linearLayout.addView(tv); } } else if (holder instanceof RowViewHolder) { RowViewHolder rowHolder = (RowViewHolder) holder; List<String> rowData = rows.get(position - 1); // 跳过表头位置 rowHolder.linearLayout.removeAllViews(); // 动态添加行数据文本框 for (String value : rowData) { TextView tv = createTextView(false); tv.setText(value); rowHolder.linearLayout.addView(tv); } } } // 统一创建文本框的工具方法 private TextView createTextView(boolean isHeader) { TextView tv = new TextView(context); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( 0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f // 让所有列平分宽度 ); params.setMargins(4, 0, 4, 0); tv.setLayoutParams(params); tv.setTextSize(14); if (isHeader) { tv.setTypeface(tv.getTypeface(), Typeface.BOLD); tv.setTextColor(Color.BLACK); } else { tv.setTextColor(Color.DKGRAY); } tv.setGravity(Gravity.CENTER_VERTICAL); return tv; } @Override public int getItemCount() { return rows.size() + 1; // 加上表头的1个Item } static class HeaderViewHolder extends RecyclerView.ViewHolder { LinearLayout linearLayout; public HeaderViewHolder(@NonNull View itemView) { super(itemView); linearLayout = itemView.findViewById(R.id.ll_header); } } static class RowViewHolder extends RecyclerView.ViewHolder { LinearLayout linearLayout; public RowViewHolder(@NonNull View itemView) { super(itemView); linearLayout = itemView.findViewById(R.id.ll_row); } } }
第四步:初始化RecyclerView
在你的Activity/Fragment里完成RecyclerView的配置:
RecyclerView recyclerView = findViewById(R.id.recyclerView); recyclerView.setLayoutManager(new LinearLayoutManager(this)); // 添加行分割线(可选) recyclerView.addItemDecoration(new TableDividerItemDecoration(this)); // 设置Adapter TableAdapter adapter = new TableAdapter(this, headers, rows); recyclerView.setAdapter(adapter);
可选:添加行分割线
创建一个自定义的ItemDecoration来实现表格的横线:
public class TableDividerItemDecoration extends RecyclerView.ItemDecoration { private Drawable divider; public TableDividerItemDecoration(Context context) { divider = ContextCompat.getDrawable(context, R.drawable/divider); } @Override public void onDrawOver(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { int left = parent.getPaddingLeft(); int right = parent.getWidth() - parent.getPaddingRight(); int childCount = parent.getChildCount(); for (int i = 0; i < childCount; i++) { View child = parent.getChildAt(i); RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); int top = child.getBottom() + params.bottomMargin; int bottom = top + divider.getIntrinsicHeight(); divider.setBounds(left, top, right, bottom); divider.draw(c); } } }
对应的divider.xml:
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <size android:height="1dp" /> <solid android:color="#e0e0e0" /> </shape>
额外优化提示
- 如果列数固定,也可以直接在布局里写好对应数量的TextView,不用动态添加,性能会更好。
- 可以给特定列设置固定宽度,或者让文本自动换行,适配不同内容长度。
- 数据量大时建议做分页加载,避免一次性加载过多数据导致卡顿。
内容的提问来源于stack exchange,提问作者prashant kumar singh
相关产品推荐
相关产品推荐

