我希望有一个类似于结构的表,其中包含标题行和数据行。 第一列应该是固定的,而其他列应该是水平可滚动的。类似地,数据行也应该是垂直可滚动的。如何在android中实现这一点。我应该采取哪种方法
答案 0 :(得分:0)
尝试创建两个表,一个用于将要修复的列,另一个表包含可以使用scollview标记滚动的其余数据。
答案 1 :(得分:0)
我通过以下链接中的代码帮助完成了这项工作 https://www.codeofaninja.com/2013/08/android-scroll-table-fixed-header-column.html
package com.Table;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Color;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
public class TableMainLayout extends RelativeLayout {
public final String TAG = "TableMainLayout.java";
// set the header titles
String headers[] = { "Header 1 \n multi-lines", "Header 2", "Header 3",
"Header 4", "Header 5", "Header 6", "Header 7", "Header 8",
"Header 9", "Header 10", "Header 11", "Header 12", "Header 13",
"Header 14",
};
TableLayout tableA;
TableLayout tableB;
TableLayout tableC;
TableLayout tableD;
HorizontalScrollView horizontalScrollViewB;
HorizontalScrollView horizontalScrollViewD;
ScrollView scrollViewC;
ScrollView scrollViewD;
Context context;
List<SampleObject> sampleObjects = this.sampleObjects();
int headerCellsWidth[] = new int[headers.length];
int screenWidthDp, screenHeightDp;
public TableMainLayout(Context context) {
super(context);
this.context = context;
// initialize the main components (TableLayouts, HorizontalScrollView,
// ScrollView)
this.initComponents();
this.setComponentsId();
this.setScrollViewAndHorizontalScrollViewTag();
Configuration configuration = this.getResources().getConfiguration();
screenWidthDp = configuration.screenWidthDp; // The current width of
// the available
// screen space, in
// dp units,
// corresponding to
// screen width
// resource
// qualifier.
screenHeightDp = configuration.screenHeightDp;
// no need to assemble component A, since it is just a table
this.horizontalScrollViewB.addView(this.tableB);
this.scrollViewC.addView(this.tableC);
this.scrollViewD.addView(this.horizontalScrollViewD);
this.horizontalScrollViewD.addView(this.tableD);
// add the components to be part of the main layout
this.addComponentToMainLayout();
// add some table rows
this.addTableRowToTableA();
this.addTableRowToTableB();
this.resizeHeaderHeight();
this.getTableRowHeaderCellWidth();
this.generateTableC_AndTable_B();
this.resizeBodyTableRowHeight();
}
// this is just the sample data
List<SampleObject> sampleObjects() {
List<SampleObject> sampleObjects = new ArrayList<SampleObject>();
for (int x = 1; x <= 25; x++) {
SampleObject sampleObject = new SampleObject("Col 1, Row " + x,
"Col 2, Row " + x + " - multi-lines", "Col 3, Row " + x,
"Col 4, Row " + x, "Col 5, Row " + x, "Col 6, Row " + x,
"Col 7, Row " + x, "Col 8, Row " + x, "Col 9, Row " + x,
"Col 10, Row " + x, "Col 11, Row " + x, "Col 12, Row " + x,
"Col 13, Row " + x, "Col 14, Row " + x
);
sampleObjects.add(sampleObject);
}
return sampleObjects;
}
// initalized components
private void initComponents() {
this.tableA = new TableLayout(this.context);
this.tableB = new TableLayout(this.context);
this.tableC = new TableLayout(this.context);
this.tableD = new TableLayout(this.context);
this.horizontalScrollViewB = new MyHorizontalScrollView(this.context);
this.horizontalScrollViewD = new MyHorizontalScrollView(this.context);
this.scrollViewC = new MyScrollView(this.context);
this.scrollViewD = new MyScrollView(this.context);
this.tableA.setBackgroundColor(Color.GREEN);
this.horizontalScrollViewB.setBackgroundColor(Color.LTGRAY);
}
// set essential component IDs
private void setComponentsId() {
this.tableA.setId(1);
this.horizontalScrollViewB.setId(2);
this.scrollViewC.setId(3);
this.scrollViewD.setId(4);
}
// set tags for some horizontal and vertical scroll view
private void setScrollViewAndHorizontalScrollViewTag() {
this.horizontalScrollViewB.setTag("horizontal scroll view b");
this.horizontalScrollViewD.setTag("horizontal scroll view d");
this.scrollViewC.setTag("scroll view c");
this.scrollViewD.setTag("scroll view d");
}
// we add the components here in our TableMainLayout
private void addComponentToMainLayout() {
// RelativeLayout params were very useful here
// the addRule method is the key to arrange the components properly
RelativeLayout.LayoutParams componentB_Params = new RelativeLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
componentB_Params.addRule(RelativeLayout.RIGHT_OF, this.tableA.getId());
RelativeLayout.LayoutParams componentC_Params = new RelativeLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
componentC_Params.addRule(RelativeLayout.BELOW, this.tableA.getId());
RelativeLayout.LayoutParams componentD_Params = new RelativeLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
componentD_Params.addRule(RelativeLayout.RIGHT_OF,
this.scrollViewC.getId());
componentD_Params.addRule(RelativeLayout.BELOW,
this.horizontalScrollViewB.getId());
// 'this' is a relative layout,
// we extend this table layout as relative layout as seen during the
// creation of this class
this.addView(this.tableA);
this.addView(this.horizontalScrollViewB, componentB_Params);
this.addView(this.scrollViewC, componentC_Params);
this.addView(this.scrollViewD, componentD_Params);
tableA.setBackgroundColor(Color.YELLOW);
horizontalScrollViewB.setBackgroundColor(Color.BLUE);
}
private void addTableRowToTableA() {
this.tableA.addView(this.componentATableRow());
}
private void addTableRowToTableB() {
this.tableB.addView(this.componentBTableRow());
}
// generate table row of table A
TableRow componentATableRow() {
TableRow componentATableRow = new TableRow(this.context);
TextView textView = this.headerTextView(this.headers[0]);
componentATableRow.addView(textView);
return componentATableRow;
}
// generate table row of table B
TableRow componentBTableRow() {
TableRow componentBTableRow = new TableRow(this.context);
int headerFieldCount = this.headers.length;
TableRow.LayoutParams params = new TableRow.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
params.setMargins(2, 0, 0, 0);
for (int x = 0; x < (headerFieldCount - 1); x++) {
TextView textView = this.headerTextView(this.headers[x + 1]);
textView.setLayoutParams(params);
componentBTableRow.addView(textView);
}
return componentBTableRow;
}
// generate table row of table C and table D
private void generateTableC_AndTable_B() {
// just seeing some header cell width
for (int x = 0; x < this.headerCellsWidth.length; x++) {
Log.v("TableMainLayout.java", this.headerCellsWidth[x] + "");
}
for (SampleObject sampleObject : this.sampleObjects) {
TableRow tableRowForTableC = this.tableRowForTableC(sampleObject);
TableRow taleRowForTableD = this.taleRowForTableD(sampleObject);
tableRowForTableC.setBackgroundColor(Color.LTGRAY);
taleRowForTableD.setBackgroundColor(Color.LTGRAY);
this.tableC.addView(tableRowForTableC);
this.tableD.addView(taleRowForTableD);
}
}
// a TableRow for table C
TableRow tableRowForTableC(SampleObject sampleObject) {
TableRow.LayoutParams params = new TableRow.LayoutParams(
this.headerCellsWidth[0], LayoutParams.MATCH_PARENT);
params.setMargins(0, 2, 0, 0);
TableRow tableRowForTableC = new TableRow(this.context);
TextView textView = this.bodyTextView(sampleObject.header1);
tableRowForTableC.addView(textView, params);
return tableRowForTableC;
}
TableRow taleRowForTableD(SampleObject sampleObject) {
TableRow taleRowForTableD = new TableRow(this.context);
int loopCount = ((TableRow) this.tableB.getChildAt(0)).getChildCount();
String info[] = { sampleObject.header2, sampleObject.header3,
sampleObject.header4, sampleObject.header5,
sampleObject.header6, sampleObject.header7,
sampleObject.header8, sampleObject.header9,
sampleObject.header10, sampleObject.header11,
sampleObject.header12, sampleObject.header13,
sampleObject.header14
};
for (int x = 0; x < loopCount; x++) {
TableRow.LayoutParams params = new TableRow.LayoutParams(
headerCellsWidth[x + 1], LayoutParams.MATCH_PARENT);
params.setMargins(2, 2, 0, 0);
TextView textViewB = this.bodyTextView(info[x]);
taleRowForTableD.addView(textViewB, params);
}
return taleRowForTableD;
}
// table cell standard TextView
TextView bodyTextView(String label) {
TextView bodyTextView = new TextView(this.context);
bodyTextView.setBackgroundColor(Color.WHITE);
bodyTextView.setText(label);
bodyTextView.setGravity(Gravity.CENTER);
bodyTextView.setPadding(5, 5, 5, 5);
bodyTextView.setWidth(screenWidthDp / 3);
return bodyTextView;
}
// header standard TextView
TextView headerTextView(String label) {
TextView headerTextView = new TextView(this.context);
headerTextView.setBackgroundColor(Color.WHITE);
headerTextView.setText(label);
headerTextView.setGravity(Gravity.CENTER);
headerTextView.setWidth(screenWidthDp / 3);
headerTextView.setPadding(5, 5, 5, 5);
return headerTextView;
}
// resizing TableRow height starts here
void resizeHeaderHeight() {
TableRow productNameHeaderTableRow = (TableRow) this.tableA
.getChildAt(0);
TableRow productInfoTableRow = (TableRow) this.tableB.getChildAt(0);
int rowAHeight = this.viewHeight(productNameHeaderTableRow);
int rowBHeight = this.viewHeight(productInfoTableRow);
TableRow tableRow = rowAHeight < rowBHeight ? productNameHeaderTableRow
: productInfoTableRow;
int finalHeight = rowAHeight > rowBHeight ? rowAHeight : rowBHeight;
this.matchLayoutHeight(tableRow, finalHeight);
}
void getTableRowHeaderCellWidth() {
int tableAChildCount = ((TableRow) this.tableA.getChildAt(0))
.getChildCount();
int tableBChildCount = ((TableRow) this.tableB.getChildAt(0))
.getChildCount();
for (int x = 0; x < (tableAChildCount + tableBChildCount); x++) {
if (x == 0) {
this.headerCellsWidth[x] = this
.viewWidth(((TableRow) this.tableA.getChildAt(0))
.getChildAt(x));
} else {
this.headerCellsWidth[x] = this
.viewWidth(((TableRow) this.tableB.getChildAt(0))
.getChildAt(x - 1));
}
}
}
// resize body table row height
void resizeBodyTableRowHeight() {
int tableC_ChildCount = this.tableC.getChildCount();
for (int x = 0; x < tableC_ChildCount; x++) {
TableRow productNameHeaderTableRow = (TableRow) this.tableC
.getChildAt(x);
TableRow productInfoTableRow = (TableRow) this.tableD.getChildAt(x);
int rowAHeight = this.viewHeight(productNameHeaderTableRow);
int rowBHeight = this.viewHeight(productInfoTableRow);
TableRow tableRow = rowAHeight < rowBHeight ? productNameHeaderTableRow
: productInfoTableRow;
int finalHeight = rowAHeight > rowBHeight ? rowAHeight : rowBHeight;
this.matchLayoutHeight(tableRow, finalHeight);
}
}
// match all height in a table row
// to make a standard TableRow height
private void matchLayoutHeight(TableRow tableRow, int height) {
int tableRowChildCount = tableRow.getChildCount();
// if a TableRow has only 1 child
if (tableRow.getChildCount() == 1) {
View view = tableRow.getChildAt(0);
TableRow.LayoutParams params = (TableRow.LayoutParams) view
.getLayoutParams();
params.height = height - (params.bottomMargin + params.topMargin);
return;
}
// if a TableRow has more than 1 child
for (int x = 0; x < tableRowChildCount; x++) {
View view = tableRow.getChildAt(x);
TableRow.LayoutParams params = (TableRow.LayoutParams) view
.getLayoutParams();
if (!isTheHeighestLayout(tableRow, x)) {
params.height = height
- (params.bottomMargin + params.topMargin);
return;
}
}
}
// check if the view has the highest height in a TableRow
private boolean isTheHeighestLayout(TableRow tableRow, int layoutPosition) {
int tableRowChildCount = tableRow.getChildCount();
int heighestViewPosition = -1;
int viewHeight = 0;
for (int x = 0; x < tableRowChildCount; x++) {
View view = tableRow.getChildAt(x);
int height = this.viewHeight(view);
if (viewHeight < height) {
heighestViewPosition = x;
viewHeight = height;
}
}
return heighestViewPosition == layoutPosition;
}
// read a view's height
private int viewHeight(View view) {
view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
return view.getMeasuredHeight();
}
// read a view's width
private int viewWidth(View view) {
// view.measure(View.MeasureSpec.UNSPECIFIED,
// View.MeasureSpec.UNSPECIFIED);
view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
return view.getMeasuredWidth();
}
// horizontal scroll view custom class
class MyHorizontalScrollView extends HorizontalScrollView {
public MyHorizontalScrollView(Context context) {
super(context);
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
String tag = (String) this.getTag();
if (tag.equalsIgnoreCase("horizontal scroll view b")) {
horizontalScrollViewD.scrollTo(l, 0);
} else {
horizontalScrollViewB.scrollTo(l, 0);
}
}
}
// scroll view custom class
class MyScrollView extends ScrollView {
public MyScrollView(Context context) {
super(context);
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
String tag = (String) this.getTag();
if (tag.equalsIgnoreCase("scroll view c")) {
scrollViewD.scrollTo(0, t);
} else {
scrollViewC.scrollTo(0, t);
}
}
}
}
package com.Table;
public class SampleObject {
String header1;
String header2;
String header3;
String header4;
String header5;
String header6;
String header7;
String header8;
String header9;
String header10;
String header11;
String header12;
String header13;
String header14;
public SampleObject(String header1, String header2, String header3,
String header4, String header5, String header6,
String header7, String header8, String header9,String header10, String header11, String header12,String header13, String header14){
this.header1 = header1;
this.header2 = header2;
this.header3 = header3;
this.header4 = header4;
this.header5 = header5;
this.header6 = header6;
this.header7 = header7;
this.header8 = header8;
this.header9 = header9;
this.header10 = header10;
this.header11= header11;
this.header12 = header12;
this.header13= header13;
this.header14 = header14;
}
}