前言
最近遇到一個需求,以表格的形式模擬樣本盒的顯示,最初設想是利用RecyclerView網格形式實現,然而需求是盒子行列數目不固定,可能存在手機屏幕一屏顯示不下的情況,因此需要做成可以上下左右滑動的表格。具體效果圖如下:
思路
採用RecyclerView+HorizontalScrollView嵌套的方式實現。左上角空白區域預留,可以用於顯示行列的標題,左邊Row列表是RecyclerView用於顯示行標題,Row列表右邊爲HorizontalScrollView,內部是兩個RecyclerView,分別用戶顯示列標題和具體的數據。
實現
佈局代碼如下:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"></FrameLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView_l"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_below="@+id/title"
app:layoutManager="android.support.v7.widget.LinearLayoutManager"
tools:listitem="@layout/item_text_grid" />
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_toEndOf="@id/recyclerView_l"
android:layout_toRightOf="@id/recyclerView_l"
android:fillViewport="true"
android:overScrollMode="never"
android:scrollbars="none">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView_t"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:overScrollMode="never"
app:layoutManager="android.support.v7.widget.GridLayoutManager"
app:spanCount="9"
tools:listitem="@layout/item_text_grid" />
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView_r"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:overScrollMode="never"
app:layoutManager="android.support.v7.widget.GridLayoutManager"
app:spanCount="9"
tools:listitem="@layout/item_text_grid" />
</LinearLayout>
</HorizontalScrollView>
</RelativeLayout>
其中title佈局爲左上角空白區域,recyclerView_l爲Row標題列表,recyclerView_t爲列標題列表,recyclerView_r爲內容區域。Row列表使用LinearLayoutManager,頭部列表和內容列表需要保持一致,
注意這兩個屬性:
app:layoutManager="android.support.v7.widget.GridLayoutManager" app:spanCount="9"
顯示的行列數,可以根據具體的業務場景在代碼中進行設置。
分別對3個RecyclerView綁定數據後,可以看到基本結構已經出現,但是還會存在一些問題,如內容上下滑動的時候,Row列表沒有產生聯動,而我們的預期是內容區域的上下左右滑動,行標題及列標題會與內容區域一起移動,因此這裏需要建立滑動關聯。
建立關聯的關鍵點就是監聽recyclerView的滑動事件,代碼如下:
recyclerViewLeft.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (recyclerView.getScrollState() != RecyclerView.SCROLL_STATE_IDLE) {
recyclerViewRight.scrollBy(dx, dy);
}
}
});
recyclerViewRight.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (recyclerView.getScrollState() != RecyclerView.SCROLL_STATE_IDLE) {
recyclerViewLeft.scrollBy(dx, dy);
}
}
});
此時再次運行,即可達到想要的效果。
Activity 詳細代碼:
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.widget.RelativeLayout;
import com.code.common.adapter.BaseRecyclerAdapter;
import com.code.common.adapter.BaseRecyclerViewHolder;
import com.tono.biobank.BaseActivity;
import com.tono.biobank.R;
import java.util.ArrayList;
import java.util.List;
/**
* 掃描盒子結果頁面
*
* @author yinbiao
* @date 2018/11/22
*/
public class ScanBoxResultActivity extends BaseActivity {
private RecyclerView recyclerViewLeft;
private RecyclerView recyclerViewRight;
private RecyclerView recyclerViewTop;
private List<String> left = new ArrayList<>();
private List<String> right = new ArrayList<>();
private List<String> top = new ArrayList<>();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scanbox_result);
initView();
}
private void initView() {
recyclerViewLeft = findViewById(R.id.recyclerView_l);
recyclerViewRight = findViewById(R.id.recyclerView_r);
recyclerViewTop = findViewById(R.id.recyclerView_t);
for (int i = 0; i < 50; i++) {
left.add("row" + (i + 1));
}
findViewById(R.id.title).post(new Runnable() {
@Override
public void run() {
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
lp.width = recyclerViewLeft.getWidth();
lp.height = recyclerViewTop.getHeight();
findViewById(R.id.title).setLayoutParams(lp);
}
});
for (int i = 0; i < 9; i++) {
top.add("第" + (i + 1) + "列");
}
for (int i = 0; i < 450; i++) {
right.add("item" + (i + 1));
}
recyclerViewLeft.setAdapter(new BaseRecyclerAdapter<String>(this, left, R.layout.item_text_grid) {
@Override
protected void convert(BaseRecyclerViewHolder holder, String s, int position) {
holder.setText(R.id.tv, s);
}
});
recyclerViewRight.setAdapter(new BaseRecyclerAdapter<String>(this, right, R.layout.item_text_grid) {
@Override
protected void convert(BaseRecyclerViewHolder holder, String s, int position) {
holder.setText(R.id.tv, s);
}
});
recyclerViewTop.setAdapter(new BaseRecyclerAdapter<String>(this, top, R.layout.item_text_grid) {
@Override
protected void convert(BaseRecyclerViewHolder holder, String s, int position) {
holder.setText(R.id.tv, s);
}
});
recyclerViewLeft.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (recyclerView.getScrollState() != RecyclerView.SCROLL_STATE_IDLE) {
recyclerViewRight.scrollBy(dx, dy);
}
}
});
recyclerViewRight.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (recyclerView.getScrollState() != RecyclerView.SCROLL_STATE_IDLE) {
recyclerViewLeft.scrollBy(dx, dy);
}
}
});
}
}
其中適配器就是RecyclerView的適配器,自行實現即可。由於時間有限,未對其進行封裝優化,僅留作記錄,並提供思路給大家。