畫面頂部有標題 TextView,下方是 ListView,希望上下滑動時**整體內容一起滾動**,而非 ListView 內部獨立滾動。
將標題 View 作為 ListView 的 Header 加入,使其成為列表一部分,隨列表整體滾動。
ListView listView = findViewById(R.id.list_view);
TextView headerTitle = findViewById(R.id.header_title); // 或動態建立
// 關鍵:加入 Header (需在 setAdapter 之前)
listView.addHeaderView(headerTitle, null, false);
// 參數:view, data(可為 null), isSelectable(false=不可點選)
// 然後設定 Adapter
listView.setAdapter(adapter);
public class MainActivity extends AppCompatActivity {
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listView = findViewById(R.id.list_view);
// 1. 建立或找到 Header View
TextView header = new TextView(this);
header.setText("我的標題");
header.setTextSize(24);
header.setGravity(Gravity.CENTER);
header.setPadding(0, 32, 0, 32);
header.setBackgroundColor(Color.WHITE);
// 2. 加入 Header (必須在 setAdapter 前)
listView.addHeaderView(header, null, false);
// 3. 設定 Adapter
List data = Arrays.asList("項目 1", "項目 2", "項目 3", "項目 4", "項目 5");
ArrayAdapter adapter = new ArrayAdapter<>(this,
android.R.layout.simple_list_item_1, data);
listView.setAdapter(adapter);
}
}
// 多個 Header
listView.addHeaderView(header1, null, false);
listView.addHeaderView(header2, null, true); // 可點選
// Footer (底部固定)
View footer = LayoutInflater.from(this).inflate(R.layout.footer_layout, listView, false);
listView.addFooterView(footer, null, false);
| 限制 | 說明 |
|---|---|
| 必須在 setAdapter 前呼叫 | 否則拋出 IllegalStateException |
| Header 不可回收 | 不參與 View 回收機制,複雜 Header 可能影響記憶體 |
| Header 位置計算 | Adapter position 0 即為第一個 Header,getItem(0) 回傳 Header data |
| RecyclerView 替代 | 用 ConcatAdapter 或多 ViewType 實現同樣效果 |
// Adapter 實現多 ViewType
public class MyAdapter extends RecyclerView.Adapter {
static final int TYPE_HEADER = 0, TYPE_ITEM = 1;
@Override public int getItemViewType(int position) {
return position == 0 ? TYPE_HEADER : TYPE_ITEM;
}
@NonNull @Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
if (viewType == TYPE_HEADER) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.header_layout, parent, false);
return new HeaderViewHolder(v);
} else {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_layout, parent, false);
return new ItemViewHolder(v);
}
}
@Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if (holder instanceof HeaderViewHolder) {
((HeaderViewHolder) holder).bind(headerData);
} else {
((ItemViewHolder) holder).bind(items.get(position - 1)); // 扣除 header
}
}
@Override public int getItemCount() {
return 1 + items.size(); // 1 header + items
}
}
addHeaderView() 最簡單、效能好setAdapter() **之前**呼叫