You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 06:23:02