开发者

Android layout - How to implement a fixed/freezed header and column

I would like to create a table-like view that contains a large number of columns (7-10) while the headers row is always visible (even when scrolling down) and the first column also always visible while scrolling horizontally.

Tried to put a list view inside an HorizontalScrollView which let me display a list with horizontal and vertical scrolling but no static column/header. I am trying to avoid using multiple views and sync between them while the user scrolls.

Later on I will h开发者_开发技巧ave to control events inside the view like row/columns clicks, so something with a custom adapter should be used.

any ideas?


I would go with TableLayout populated by TableRow's.

The following code demonstrates how to achieve that.

package com.test;

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.Gravity;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TableRow.LayoutParams;
import android.widget.TextView;

public class TableLayoutTest extends Activity {

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.table_layout);

        TableRow.LayoutParams wrapWrapTableRowParams = new TableRow.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        int[] fixedColumnWidths = new int[]{20, 20, 20, 20, 20};
        int[] scrollableColumnWidths = new int[]{20, 20, 20, 30, 30};
        int fixedRowHeight = 50;
        int fixedHeaderHeight = 60;

        TableRow row = new TableRow(this);
        //header (fixed vertically)
        TableLayout header = (TableLayout) findViewById(R.id.table_header);
        row.setLayoutParams(wrapWrapTableRowParams);
        row.setGravity(Gravity.CENTER);
        row.setBackgroundColor(Color.YELLOW);
        row.addView(makeTableRowWithText("col 1", fixedColumnWidths[0], fixedHeaderHeight));
        row.addView(makeTableRowWithText("col 2", fixedColumnWidths[1], fixedHeaderHeight));
        row.addView(makeTableRowWithText("col 3", fixedColumnWidths[2], fixedHeaderHeight));
        row.addView(makeTableRowWithText("col 4", fixedColumnWidths[3], fixedHeaderHeight));
        row.addView(makeTableRowWithText("col 5", fixedColumnWidths[4], fixedHeaderHeight));
        header.addView(row);
        //header (fixed horizontally)
        TableLayout fixedColumn = (TableLayout) findViewById(R.id.fixed_column);
        //rest of the table (within a scroll view)
        TableLayout scrollablePart = (TableLayout) findViewById(R.id.scrollable_part);
        for(int i = 0; i < 10; i++) {
            TextView fixedView = makeTableRowWithText("row number " + i, scrollableColumnWidths[0], fixedRowHeight);
            fixedView.setBackgroundColor(Color.BLUE);
            fixedColumn.addView(fixedView);
            row = new TableRow(this);
            row.setLayoutParams(wrapWrapTableRowParams);
            row.setGravity(Gravity.CENTER);
            row.setBackgroundColor(Color.WHITE);
            row.addView(makeTableRowWithText("value 2", scrollableColumnWidths[1], fixedRowHeight));
            row.addView(makeTableRowWithText("value 3", scrollableColumnWidths[2], fixedRowHeight));
            row.addView(makeTableRowWithText("value 4", scrollableColumnWidths[3], fixedRowHeight));
            row.addView(makeTableRowWithText("value 5", scrollableColumnWidths[4], fixedRowHeight));
            scrollablePart.addView(row);
        }

    }


    //util method
    private TextView recyclableTextView;

    public TextView makeTableRowWithText(String text, int widthInPercentOfScreenWidth, int fixedHeightInPixels) {
        int screenWidth = getResources().getDisplayMetrics().widthPixels;
        recyclableTextView = new TextView(this);
        recyclableTextView.setText(text);
        recyclableTextView.setTextColor(Color.BLACK);
        recyclableTextView.setTextSize(20);
        recyclableTextView.setWidth(widthInPercentOfScreenWidth * screenWidth / 100);
        recyclableTextView.setHeight(fixedHeightInPixels);
        return recyclableTextView;
    }

}

Header is the part that doesn't scroll vertically; that's the reason you need to set fixed width on columns. As of the first column that you don't want to scroll, you'll have to set a fixed height on rows for that purpose.

Here's the layout XML

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:gravity="center_horizontal"
    android:id="@+id/fillable_area">
    <TableLayout
        android:id="@+id/table_header"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"/>
    <ScrollView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content">
        <LinearLayout android:orientation="horizontal"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:gravity="center_horizontal"
            android:id="@+id/fillable_area">
            <TableLayout
                android:id="@+id/fixed_column"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>
            <HorizontalScrollView
                android:layout_width="fill_parent"
                android:layout_height="wrap_content">
                <TableLayout
                    android:id="@+id/scrollable_part"
                    android:layout_width="fill_parent"
                    android:layout_height="fill_parent"/>
            </HorizontalScrollView>
        </LinearLayout>
    </ScrollView>
</LinearLayout>

And the output looks like this when just loaded

Android layout - How to implement a fixed/freezed header and column

and like this when scrolled to the right and to the bottom

Android layout - How to implement a fixed/freezed header and column


You can check this library that I made: https://github.com/InQBarna/TableFixHeaders

I think that it implements the widget you're looking for.


Create TableLayout that will be a header and under it place a Table itself within a ScrollView like this:

<TableLayout
        android:id="@+id/tbl_header"
        android:orientation="horizontal"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:divider="@drawable/table_divider"
        android:showDividers="middle"
        android:background="@drawable/table_header_backdround"
        />

    <ScrollView android:layout_width="fill_parent"
                android:layout_height="wrap_content">
        <TableLayout
                android:id="@+id/tbl_relesed_wake_locks"
                android:orientation="horizontal"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:divider="@drawable/table_divider"
                android:showDividers="middle"
                android:stretchColumns="1,2"
                android:background="@drawable/table_backdround"

                />
    </ScrollView>

When you will populate your header with data add next code:

table.post(new Runnable() {
        @Override
        public void run() {
            TableRow tableRow = (TableRow)table.getChildAt(0);
            for(int i = 0; i < headerRow.getChildCount(); i++){
                headerRow.getChildAt(i).setLayoutParams(new TableRow.LayoutParams(tableRow.getChildAt(i).getMeasuredWidth(), tableRow.getChildAt(i).getMeasuredHeight()));
            }
        }
    });

That's it.


If wanna fix first column, you can try the following layout:

<TableLayout
    android:id="@+id/tbl_header"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:background="@drawable/cell_shape_header"
    android:divider="?android:dividerHorizontal"
    android:orientation="horizontal"
    android:showDividers="middle">

    <TableRow
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="0.5dp">

        <TextView
            style="@style/TextViewStyle"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="Fragment A" />

    </TableRow>

    <TableRow
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:padding="0.5dp">

        <TextView
            style="@style/TextViewStyle"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="Fragment A" />

    </TableRow>

    <TableRow
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:padding="0.5dp">

        <TextView
            style="@style/TextViewStyle"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="Fragment A" />

    </TableRow>
</TableLayout>

<HorizontalScrollView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentRight="true"
    android:layout_toRightOf="@+id/tbl_header">

    <TableLayout
        android:id="@+id/tbl_relesed_wake_locks"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/cell_shape_header"
        android:divider="?android:dividerHorizontal"
        android:orientation="horizontal"
        android:showDividers="middle"
        android:stretchColumns="1,2">

        <TableRow
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:padding="0.5dp">

            <TextView
                style="@style/TextViewStyle"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:text="Fragment 01" />

            <TextView
                style="@style/TextViewStyle"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:text="Fragment 01" />

            <TextView
                style="@style/TextViewStyle"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:text="Fragment 01" />

        </TableRow>

        <TableRow
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:padding="0.5dp">

            <TextView
                style="@style/TextViewStyle"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:text="Fragment 01" />

            <TextView
                style="@style/TextViewStyle"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:text="Fragment 01" />

            <TextView
                style="@style/TextViewStyle"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:text="Fragment 01" />

        </TableRow>

        <TableRow
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:padding="0.5dp">

            <TextView
                style="@style/TextViewStyle"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:text="Fragment 01" />

            <TextView
                style="@style/TextViewStyle"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:text="Fragment 01" />

            <TextView
                style="@style/TextViewStyle"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:text="Fragment 01" />

        </TableRow>
    </TableLayout>
</HorizontalScrollView>


Android layout - How to implement a fixed/freezed header and column

Android layout - How to implement a fixed/freezed header and column

github link

Recently I came across a situation where I need first two row & first column freeze. I got this library I modified it according to my requirement & fixed some bugs. Now work smoothly.


Ten years on, and this is still amazingly difficult! Jetpack Compose now has a DataTable control, but this is not yet available for Android: Jetpack Compose: Data Tables.

I have been working on a Kotlin App for my own learning, and wanted to display a data table. I have taken the ideas from this thread, together with the linked scrolling from: Synchronise ScrollView scroll positions - android.

The full code is available on GitHub: CovidStatistics.

The table is shown in the screenshot below. You can see that the Data Table has grid lines, and scrolls in both directions. Also, it display icons on some of the cells.

My solution adds the following to those presented above in this thread:

  • The data cell is defined in a layout file, not in code, which makes it easier to display complex layouts in a cell. The icons are shown randomly as an example of this.
  • The column widths are automatically set after the data is added to the table, rather than having to be chosen beforehand.

I had hoped to use RecyclerViews, instead of creating rows and columns in code. I got part way towards this but just couldn't get the horizontal scroll bar to work with RecyclerView.

Android layout - How to implement a fixed/freezed header and column

This is the layout code for the table fragment:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:gravity="center_horizontal"
    android:id="@+id/main_area"
    android:layout_marginTop="0in"
    android:layout_marginBottom="0in"
    android:layout_marginLeft="0in"
    android:layout_marginRight="0in"
    android:background="@android:color/holo_green_dark">

    <ProgressBar
        android:id="@+id/progressBar1"
        style="?android:attr/progressBarStyleLarge"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:tooltipText="Loading data"
        android:visibility="visible" />

    <LinearLayout android:orientation="horizontal"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:id="@+id/header_area"
        >

        <!-- Top left cell, in a table of its own-->
        <TableLayout
            android:id="@+id/top_left_cell"
            android:layout_width="wrap_content"
            android:layout_height="fill_parent"
            app:layout_constraintStart_toStartOf="parent"
            android:paddingLeft="0in"
            android:paddingRight="0in"
            android:paddingTop="0in"
            android:paddingBottom="0in"
            />

        <!-- Column header horizontal scroll-->
        <com.ant_waters.covidstatistics.ui.ObservableHorizontalScrollView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:id="@+id/column_header_scroll"
            >

            <!-- Column Headers-->
            <TableLayout
                android:id="@+id/table_header"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                >
            </TableLayout>
        </com.ant_waters.covidstatistics.ui.ObservableHorizontalScrollView>
    </LinearLayout>

    <!-- Data area vertical scroll-->
    <ScrollView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        >
        <LinearLayout android:orientation="horizontal"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:gravity="center_horizontal"
            android:id="@+id/fillable_area"
            >

            <!-- Data row headers-->
            <TableLayout
                android:id="@+id/fixed_column"
                android:layout_width="wrap_content"
                android:layout_height="fill_parent"
                app:layout_constraintStart_toStartOf="@+id/table_header"
                android:paddingLeft="0in"
                android:paddingRight="0in"
                android:paddingTop="0in"
                android:paddingBottom="0in"
                />

            <!-- Data rows horizontal scroll-->
            <com.ant_waters.covidstatistics.ui.ObservableHorizontalScrollView
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:id="@+id/data_horizontal_scroll"
                >

                <!-- Data rows-->
                <TableLayout
                    android:id="@+id/scrollable_part"
                    android:layout_width="fill_parent"
                    android:layout_height="fill_parent"
                    android:paddingLeft="0in"
                    android:paddingRight="0in"
                    android:paddingTop="0in"
                    android:paddingBottom="0in"
                    />
            </com.ant_waters.covidstatistics.ui.ObservableHorizontalScrollView>
        </LinearLayout>
    </ScrollView>
</LinearLayout>

These are the layout codes for other key pieces:

Header_cell:

<!--This defines the layout for a header cell in the data table-->

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="horizontal"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/cell_linear_layout"
    android:layout_marginTop="0in"
    android:layout_marginBottom="0in"
    android:layout_marginLeft="0in"
    android:layout_marginRight="0in"
    >
    <!--    android:gravity="center_horizontal"-->
    <!--    android:background="@android:color/holo_green_dark"-->

    <TextView
        android:id="@+id/cell_text_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="2dp"
        android:layout_marginTop="2dp"
        android:layout_marginEnd="2dp"
        android:layout_marginBottom="2dp"
        android:textColor="@color/black"
        android:textSize="20.0sp"
        android:layout_gravity="center_horizontal|center_vertical"
        android:paddingStart="15sp"
        android:paddingEnd="15sp"
        android:paddingTop="5sp"
        android:paddingBottom="5sp"
        android:background="#4b8ba1"
        ></TextView>
</LinearLayout>

Data cell containing an icon:

    <!--This defines the layout for a data cell that includes a warning icon in the data table-->

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/cell_linear_layout"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <!--    This layer is needed to set the margin, as that doesn't seem to work at the top level -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="2dp"
        android:layout_marginTop="2dp"
        android:layout_marginEnd="2dp"
        android:layout_marginBottom="2dp"
        android:background="@android:color/white"
        android:orientation="horizontal">

        <ImageView
            android:layout_width="20dp"
            android:layout_height="20dp"
            android:layout_gravity="center_vertical"
            android:src="@drawable/ic_baseline_warning_24" />

        <TextView
            android:id="@+id/cell_text_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal|center_vertical"
            android:paddingStart="15sp"
            android:paddingTop="5sp"
            android:paddingEnd="15sp"
            android:paddingBottom="5sp"
            android:textColor="@color/black"
            android:textSize="20.0sp"></TextView>
    </LinearLayout>
</LinearLayout>

Header cell background:

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="@android:color/darker_gray" />
</shape>

While the table is built it fills in a 2-d array of Views for all the cells being display.

fun displayTheDataTable(inflater: LayoutInflater)
{
    if (MainViewModel.DataInitialised.value==enDataLoaded.All) {
        // Display the table by creating Views for cells, headers etc.
        val allCells = displayDataTable(inflater)

        // Add a callback to set the column widths at the end (when onGlobalLayout is called)
        val content: View = _binding!!.mainArea
        content.viewTreeObserver.addOnGlobalLayoutListener(object : OnGlobalLayoutListener {
            override fun onGlobalLayout() {
                //Remove the observer so we don't get this callback for EVERY layout pass
                content.viewTreeObserver.removeGlobalOnLayoutListener(this)

                //Resize the columns to match the maximum width
                setColumnWidths(allCells, fun (v: View, w: Int) {
                    val tv = v.findViewById<View>(com.ant_waters.covidstatistics.R.id.cell_text_view) as TextView
                    var lp  = LayoutParams(w, LayoutParams.WRAP_CONTENT)
                    v.layoutParams = lp

                    tv.setGravity(Gravity.CENTER)
                })
            }
        })
    }
}

This is used to set the column widths at the end:

fun setColumnWidths(allCells: Array<Array<View?>>, setItemWidth: (v: View, w: Int) -> Unit)
{
    val numColumns: Int = allCells[0].size
    val colWidths = Array<Int>(numColumns, {0})
    for (r in 0..allCells.size-1)
    {
        if ((allCells[r] == null) || (allCells[r][0] == null)) { continue }    // Row was skipped
        for (c in 0..numColumns-1)
        {
            val vw : View = allCells[r][c]!!
            if (vw.width > colWidths[c]) { colWidths[c] = vw.width}
        }
    }
    for (r in 0..allCells.size-1)
    {
        if ((allCells[r] == null) || (allCells[r][0] == null)) { continue }    // Row was skipped
        for (c in 0..numColumns-1)
        {
            val vw = allCells[r][c]!! as LinearLayout
            setItemWidth(vw, colWidths[c])
        }
    }
}

These are the methods to build the individual cells from the "templates" defined in layout files:

fun createHeaderCellFromTemplate(inflater: LayoutInflater, text: String?): View {
    val cellView: View = inflater.inflate(com.ant_waters.covidstatistics.R.layout.header_cell, null)
    val tv = cellView.findViewById<View>(com.ant_waters.covidstatistics.R.id.cell_text_view) as TextView
    tv.text = text

    return cellView
}
fun <TRowHdr>createRowHeaderCellFromTemplate(inflater: LayoutInflater, rowHdr: TRowHdr): View {
    val cellView: View = inflater.inflate(com.ant_waters.covidstatistics.R.layout.header_cell, null)
    val tv = cellView.findViewById<View>(com.ant_waters.covidstatistics.R.id.cell_text_view) as TextView

    if  (rowHdr is Date)
    {
        val dt = rowHdr as Date
        var formatter = SimpleDateFormat("dd/MM/yy")
        tv.text = formatter.format(dt)
    }
    else {
        tv.text = rowHdr.toString()
    }

    return cellView
}

fun <Tval>createDataCellFromTemplate(inflater: LayoutInflater, theVal: Tval,
                                     showWarning: Boolean, countryName: String
): View {
    var templateId = com.ant_waters.covidstatistics.R.layout.data_cell

    var text = theVal.toString()
    if (theVal is Double) {
        val df1 = DecimalFormat("#")
        val df2 = DecimalFormat("#.0")
        text = getProportionalDisplayText(text.toDouble(), df1, df2)
    }

    if (showWarning) { templateId = com.ant_waters.covidstatistics.R.layout.warning_data_cell }
    val cellView: View = inflater.inflate(templateId, null)

    val tv = cellView.findViewById<View>(com.ant_waters.covidstatistics.R.id.cell_text_view) as TextView
    tv.text = text


    if (DataManager.CountriesByName.containsKey(countryName)) {
        cellView.setOnClickListener(View.OnClickListener {
            val cpf = CountryPopupFragment()

            // Supply country as an argument.
            val args = Bundle()

            args.putString("geoId", DataManager.CountriesByName[countryName]!!.geoId)
            cpf.setArguments(args)

            cpf.show(requireActivity()?.getSupportFragmentManager(), "countrypopup_from_datatable")
        })
    }

    return cellView
}

For the rest of the code see the Github repo.


I found two working examples. http://justsimpleinfo.blogspot.com/2015/04/android-scrolling-table-with-fixed.html

and

https://www.codeofaninja.com/2013/08/android-scroll-table-fixed-header-column.html (https://www.youtube.com/watch?v=VCjlcV20ftE). In the second case a warning is shown, so it can be fixed with Android - Expected Resource of type ID.

A code from the first link.

MainActivity.java

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Table table = new Table(this);
        setContentView(table);
    }
}

Table.java

public class Table extends LinearLayout {


 public static final String PREVIOUS_ARROW = "\u2190";
 public static final String NEXT_ARROW = "\u2192";
 public static final  int HEADER_BACKROUND_COLOR = Color.parseColor("#339999");
 public static final  int BODY_BACKROUND_COLOR = Color.parseColor("#99cccc");
 public static String LEFT_BODY_SCROLLVIEW_TAG = "LEFT_BODY_SCROLLVIEW_TAG";
 public static String RIGHT_BODY_SCROLLVIEW_TAG = "RIGHT_BODY_SCROLLVIEW_TAG";
 /**
  * @IS_TWO_COLUMN_HEADER = set this to true if you want two column header with span.
  */
 public static final  boolean IS_TWO_COLUMN_HEADER = true;

 LinkedHashMap<Object, Object[]> leftHeaders = new LinkedHashMap<Object, Object[]>();
 LinkedHashMap<Object, Object[]> rightHeaders = new LinkedHashMap<Object, Object[]>();

 BodyTable rightTable;
 BodyTable leftTable;
 /**
  * @leftHeaderChildrenWidht = value will be set on adjust header width to match in screen width
  */
 Integer[] leftHeaderChildrenWidth ;
 /**
  * rightHeaderChildrenWidht = value will be set on adjust header width to match in screen width
  */
 Integer[] rightHeaderChildrenWidht ;


 LoadingDialog loadingDialog;

 public Table(Context context) {
  super(context);

  this.headers();
  this.properties();
  this.init();

  this.resizeFirstLvlHeaderHeight();
  this.resizeSecondLvlHeaderHeight();
  this.resizeHeaderSecondLvlWidhtToMatchInScreen();

  this.leftTable.setHeaderChildrenWidth(this.leftHeaderChildrenWidth);
  this.rightTable.setHeaderChildrenWidth(this.rightHeaderChildrenWidht);


  this.createTestData();
  this.loadData();


 }

 public final static String NAME = "Name";
 public final static String GENDER = "Gender";
 public final static String TICKET_SET_SEQUENCE = "Set Sequence";
 public final static String TICKET_NUMBER = "Ticket Number";
 public final static String TICKET_VALID_UNTIL = "    Valid Until    ";
 public final static String COUNTRY_FROM = "  Country From  ";
 public final static String COUNTRY_TO = "  Country To  ";
 public void headers(){
  leftHeaders.put("Passenger Info", new String[]{NAME,GENDER});
  rightHeaders.put("Ticket Info", new String[]{TICKET_VALID_UNTIL,TICKET_NUMBER,TICKET_SET_SEQUENCE});
  rightHeaders.put("Country Info", new String[]{COUNTRY_FROM,COUNTRY_TO});

 }


 List<Passenger> testData = new ArrayList<Table.Passenger>();
 List<Passenger> dataToBeLoad = new ArrayList<Table.Passenger>();
 int pagination = 20;
 int totalPage = 0;
 int pageNumber = 1;

 public void loadData() {



  // TODO Auto-generated method stub
  this.dataToBeLoad = this.getDataToBeLoad();

  leftTable.loadData(dataToBeLoad);
  rightTable.loadData(dataToBeLoad);


  this.resizeBodyChildrenHeight();

 }

 private void createTestData(){
  for(int x = 0 ; x < 102; x++){
   Passenger passenger = new Passenger();
   passenger.name = "Passenger "+x;
   passenger.gender = x%2 == 0 ? 'F':'M';
   passenger.ticketNum = x;
   passenger.setSequence = "Set "+x;
   passenger.validUntil = "May 01, 2015";
   passenger.countryFrom = "Country "+x;
   passenger.countryTo = x%2 == 0 ? "Philippines" :"Country "+x;

   testData.add(passenger);
  }

  this.totalPage = this.totalPage(testData, pagination);
  /*this.dataToBeLoad = this.getDataToBeLoad();*/
 }
 private List<Passenger> getDataToBeLoad(){
  List<Passenger> passengers = new ArrayList<Table.Passenger>();
  int startingIndex = (pageNumber -1) * pagination;

  int totalPassenger = testData.size();
  //dataToBeLoad.clear();

  for(int x = 0 ; x < pagination ; x++){

   int index = startingIndex + x;

   if(index < totalPassenger){

    passengers.add(testData.get(index));

   }else{
    Log.e("no data","no data");
   }

  }



  return passengers;
 }
 private int totalPage(List<Passenger> testData,int pagination){

  int totalPage = testData.size() / pagination;
  totalPage = totalPage + (testData.size() % 20 == 0 ? 0 : 1);

  return totalPage;

 }
 private void properties(){ 
  this.setBackgroundColor(Color.WHITE);
  this.setOrientation(LinearLayout.HORIZONTAL);
 }

 private void init(){

  this.loadingDialog = new LoadingDialog(this.getContext());
  this.rightTable = new BodyTable(this.getContext(),this, rightHeaders, RIGHT_BODY_SCROLLVIEW_TAG);
  this.leftTable = new BodyTable(this.getContext(),this,leftHeaders, LEFT_BODY_SCROLLVIEW_TAG);



  this.addView(this.leftTable);
  this.addView(this.rightTable);
 }
 private void resizeFirstLvlHeaderHeight(){
  int rightHeaderLinearLayoutChildCount = rightTable.headerHorizontalLinearLayout.getChildCount();

  int rightHeaderFirstLvlHeighestHeight = 0;
  int rightHeaderFirstLvlHighestHeightIndex = 0;

  for(int x = 0 ; x < rightHeaderLinearLayoutChildCount; x++){

   HeaderRow row = (HeaderRow) rightTable.headerHorizontalLinearLayout.getChildAt(x);

   int height = ViewSizeUtils.getViewHeight(row.firtLvlLinearLayout);

   if(rightHeaderFirstLvlHeighestHeight  <= height){

    rightHeaderFirstLvlHeighestHeight = height;
    rightHeaderFirstLvlHighestHeightIndex = x;
   }
  }

  int leftHeaderLinearLayoutChildCount = leftTable.headerHorizontalLinearLayout.getChildCount();

  int leftHeaderFirstLvlHeighestHeight = 0;
  int leftHeaderFirstLvlHighestHeightIndex = 0;

  for(int x = 0 ; x < leftHeaderLinearLayoutChildCount; x++){

   HeaderRow row = (HeaderRow) leftTable.headerHorizontalLinearLayout.getChildAt(x);

   int height = ViewSizeUtils.getViewHeight(row.firtLvlLinearLayout);

   if(leftHeaderFirstLvlHeighestHeight  <= height){

    leftHeaderFirstLvlHeighestHeight = height;
    leftHeaderFirstLvlHighestHeightIndex = x;
   }
  }

  boolean isHighestHighInLeft = false;



  if(leftHeaderFirstLvlHeighestHeight < rightHeaderFirstLvlHeighestHeight){
   // apply right header height in left and right except for the index in highest height

   isHighestHighInLeft = false;


  }else{

   isHighestHighInLeft = true;

  }

  for(int x = 0 ; x < rightHeaderLinearLayoutChildCount; x++){

   LinearLayout firstLvlLinearLayout = ((HeaderRow) rightTable.headerHorizontalLinearLayout.getChildAt(x)).firtLvlLinearLayout;


   if(isHighestHighInLeft){

    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,leftHeaderFirstLvlHeighestHeight);
    params.weight = 1;

    firstLvlLinearLayout.setLayoutParams(params);

   }else{

    if(rightHeaderFirstLvlHeighestHeight  != rightHeaderFirstLvlHighestHeightIndex){
     LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,rightHeaderFirstLvlHeighestHeight);
     params.weight = 1;

     firstLvlLinearLayout.setLayoutParams(params);

    }

   }


  }

  for(int x = 0 ; x < leftHeaderLinearLayoutChildCount; x++){

   LinearLayout firstLvlLinearLayout = ((HeaderRow) leftTable.headerHorizontalLinearLayout.getChildAt(x)).firtLvlLinearLayout;


   if(isHighestHighInLeft){

    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,leftHeaderFirstLvlHeighestHeight);
    params.weight = 1;

    firstLvlLinearLayout.setLayoutParams(params);

   }else{

    if(leftHeaderFirstLvlHeighestHeight  != leftHeaderFirstLvlHighestHeightIndex){
     LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,rightHeaderFirstLvlHeighestHeight);
     params.weight = 1;

     firstLvlLinearLayout.setLayoutParams(params);

    }

   }


  }

 }

 private void resizeSecondLvlHeaderHeight(){
  int rightHeaderLinearLayoutChildCount = rightTable.headerHorizontalLinearLayout.getChildCount();

  int rightHeaderFirstLvlHeighestHeight = 0;
  int rightHeaderFirstLvlHighestHeightIndex = 0;

  for(int x = 0 ; x < rightHeaderLinearLayoutChildCount; x++){

   HeaderRow row = (HeaderRow) rightTable.headerHorizontalLinearLayout.getChildAt(x);

   int height = ViewSizeUtils.getViewHeight(row.secondLvlLinearLayout);

   if(rightHeaderFirstLvlHeighestHeight  <= height){

    rightHeaderFirstLvlHeighestHeight = height;
    rightHeaderFirstLvlHighestHeightIndex = x;
   }
  }

  int leftHeaderLinearLayoutChildCount = leftTable.headerHorizontalLinearLayout.getChildCount();

  int leftHeaderFirstLvlHeighestHeight = 0;
  int leftHeaderFirstLvlHighestHeightIndex = 0;

  for(int x = 0 ; x < leftHeaderLinearLayoutChildCount; x++){

   HeaderRow row = (HeaderRow) leftTable.headerHorizontalLinearLayout.getChildAt(x);

   int height = ViewSizeUtils.getViewHeight(row.secondLvlLinearLayout);

   if(leftHeaderFirstLvlHeighestHeight  <= height){

    leftHeaderFirstLvlHeighestHeight = height;
    leftHeaderFirstLvlHighestHeightIndex = x;
   }
  }

  boolean isHighestHighInLeft = false;



  if(leftHeaderFirstLvlHeighestHeight < rightHeaderFirstLvlHeighestHeight){
   // apply right header height in left and right except for the index in highest height

   isHighestHighInLeft = false;


  }else{

   isHighestHighInLeft = true;

  }


  for(int x = 0 ; x < rightHeaderLinearLayoutChildCount; x++){

   LinearLayout secondLvlLinearLayout = ((HeaderRow) rightTable.headerHorizontalLinearLayout.getChildAt(x)).secondLvlLinearLayout;


   if(isHighestHighInLeft){

    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,leftHeaderFirstLvlHeighestHeight);
    params.weight = 1;

    secondLvlLinearLayout.setLayoutParams(params);

   }else{

    if(rightHeaderFirstLvlHeighestHeight  != rightHeaderFirstLvlHighestHeightIndex){
     LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,rightHeaderFirstLvlHeighestHeight);
     params.weight = 1;

     secondLvlLinearLayout.setLayoutParams(params);

    }

   }


  }

  for(int x = 0 ; x < leftHeaderLinearLayoutChildCount; x++){

   LinearLayout secondLvlLinearLayout = ((HeaderRow) leftTable.headerHorizontalLinearLayout.getChildAt(x)).secondLvlLinearLayout;


   if(isHighestHighInLeft){

    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,leftHeaderFirstLvlHeighestHeight);
    params.weight = 1;

    secondLvlLinearLayout.setLayoutParams(params);

   }else{

    if(leftHeaderFirstLvlHeighestHeight  != leftHeaderFirstLvlHighestHeightIndex){
     LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,rightHeaderFirstLvlHeighestHeight);
     params.weight = 1;

     secondLvlLinearLayout.setLayoutParams(params);

    }

   }


  }

 }

 private void resizeHeaderSecondLvlWidhtToMatchInScreen(){
  int screenWidth = ScreenUtils.getScreenWidth(this.getContext());
  int leftHeaderChildrenTotalWidth = this.leftSecondLvlHeaderChildrenTotalWidth();
  int rightHeaderChildrenTotalWidth = this.rightHeaderChildrenTotalWidth();
  int leftHeaderSecondLvlChildrenCount = this.leftSecondLvlHeaderChildrenCount();
  int rightHeaderSecondLvlChildrenCount = this.rightSecondLvlHeaderChildrenCount();
  float availableWidth = screenWidth - (leftHeaderChildrenTotalWidth + rightHeaderChildrenTotalWidth);

  if(availableWidth <=0){
   // set the header width
   this.leftHeaderChildrenWidth = this.getLeftHeaderChildrenWidth();
   this.rightHeaderChildrenWidht = this.getRightHeaderChildrenWidth();

   return;
  }

  int widthForEachHeaderChild = (int) Math.ceil(availableWidth / (leftHeaderSecondLvlChildrenCount + rightHeaderSecondLvlChildrenCount));


  this.addWidthForEachHeaderLeftAndRightChild(widthForEachHeaderChild);
  // set the header width
  this.leftHeaderChildrenWidth = this.getLeftHeaderChildrenWidth();
  this.rightHeaderChildrenWidht = this.getRightHeaderChildrenWidth();

 }
 /**
  * get children count in left header
  * @return
  */
 private int leftSecondLvlHeaderChildrenCount(){
  int totalChildren = 0;
  int leftHeaderLinearLayoutChildCount = leftTable.headerHorizontalLinearLayout.getChildCount();

  for(int x = 0 ; x < leftHeaderLinearLayoutChildCount ; x++){

   LinearLayout secondLvlLinearLayout = ((HeaderRow) leftTable.headerHorizontalLinearLayout.getChildAt(x)).secondLvlLinearLayout;
   totalChildren += secondLvlLinearLayout.getChildCount();


  }

  return totalChildren;
 }
 /**
  * get children count in right header
  * @return
  */
 private int rightSecondLvlHeaderChildrenCount(){
  int totalChildren = 0;
  int leftHeaderLinearLayoutChildCount = rightTable.headerHorizontalLinearLayout.getChildCount();

  for(int x = 0 ; x < leftHeaderLinearLayoutChildCount ; x++){

   LinearLayout secondLvlLinearLayout = ((HeaderRow) rightTable.headerHorizontalLinearLayout.getChildAt(x)).secondLvlLinearLayout;
   totalChildren += secondLvlLinearLayout.getChildCount();


  }

  return totalChildren;
 }
 /**
  * Compute total header width in left header
  * @return
  */
 private int leftSecondLvlHeaderChildrenTotalWidth(){
  int totalWidth = 0;
  int leftHeaderLinearLayoutChildCount = leftTable.headerHorizontalLinearLayout.getChildCount();

  for(int x = 0 ; x < leftHeaderLinearLayoutChildCount ; x++){

   LinearLayout secondLvlLinearLayout = ((HeaderRow) leftTable.headerHorizontalLinearLayout.getChildAt(x)).secondLvlLinearLayout;
   int leftColumnChildrenCount = secondLvlLinearLayout.getChildCount();

   for(int y = 0 ; y < leftColumnChildrenCount ; y++){
    View view  = secondLvlLinearLayout.getChildAt(y);
    LinearLayout.LayoutParams params = (LayoutParams) view.getLayoutParams();

    int width = params.width <=0 ? ViewSizeUtils.getViewWidth(view) : params.width;

    totalWidth += width;

   }

  }

  return totalWidth;
 }
 /**
  * Compute total right header children width
  * @return
  */
 private int rightHeaderChildrenTotalWidth(){
  int totalWidth = 0;
  int leftHeaderLinearLayoutChildCount = rightTable.headerHorizontalLinearLayout.getChildCount();

  for(int x = 0 ; x < leftHeaderLinearLayoutChildCount ; x++){

   LinearLayout secondLvlLinearLayout = ((HeaderRow) rightTable.headerHorizontalLinearLayout.getChildAt(x)).secondLvlLinearLayout;
   int leftColumnChildrenCount = secondLvlLinearLayout.getChildCount();

   for(int y = 0 ; y < leftColumnChildrenCount ; y++){
    View view  = secondLvlLinearLayout.getChildAt(y);
    LinearLayout.LayoutParams params = (LayoutParams) view.getLayoutParams();

    int width = params.width <=0 ? ViewSizeUtils.getViewWidth(view) : params.width;

    totalWidth += width;

   }

  }

  return totalWidth;
 }
 /**
  * Add width in left and right children width if needed to match screen width.
  * @param widthToBeAdded
  */
 private void addWidthForEachHeaderLeftAndRightChild(int widthToBeAdded){

  int leftHeaderColumnCount = leftTable.headerHorizontalLinearLayout.getChildCount();
  int rightHeaderColumnCount = rightTable.headerHorizontalLinearLayout.getChildCount();

  for(int x = 0 ; x < leftHeaderColumnCount ; x++){

   HeaderRow tableRow =  (HeaderRow) leftTable.headerHorizontalLinearLayout.getChildAt(x);
   int headerRowChildCount = tableRow.secondLvlLinearLayout.getChildCount();

   for(int y = 0 ; y < headerRowChildCount ; y++){

    View view = tableRow.secondLvlLinearLayout.getChildAt(y);

    LinearLayout.LayoutParams params = (LayoutParams) view.getLayoutParams();

    int width = params.width <=0 ? ViewSizeUtils.getViewWidth(view) + widthToBeAdded : params.width +widthToBeAdded;
    params.width = width;
   }


  }

  for(int x = 0 ; x < rightHeaderColumnCount ; x++){

   HeaderRow tableRow =  (HeaderRow) rightTable.headerHorizontalLinearLayout.getChildAt(x);
   int headerRowChildCount = tableRow.secondLvlLinearLayout.getChildCount();

   for(int y = 0 ; y < headerRowChildCount ; y++){

    View view = tableRow.secondLvlLinearLayout.getChildAt(y);

    LinearLayout.LayoutParams params = (LayoutParams) view.getLayoutParams();

    int width = params.width <=0 ? ViewSizeUtils.getViewWidth(view) + widthToBeAdded : params.width +widthToBeAdded;
    params.width = width;
   }


  }

 }
 /**
  * Get each width of left header child
  * @return
  */
 private Integer[] getLeftHeaderChildrenWidth(){

  List<Integer> headerChildrenWidth = new ArrayList<Integer>();

  int leftHeaderColumnCount = leftTable.headerHorizontalLinearLayout.getChildCount();


  for(int x = 0 ; x < leftHeaderColumnCount ; x++){

   HeaderRow tableRow =  (HeaderRow) leftTable.headerHorizontalLinearLayout.getChildAt(x);
   int headerRowChildCount = tableRow.secondLvlLinearLayout.getChildCount();

   for(int y = 0 ; y < headerRowChildCount ; y++){

    View view = tableRow.secondLvlLinearLayout.getChildAt(y);

    LinearLayout.LayoutParams params = (LayoutParams) view.getLayoutParams();

    int width = params.width <=0 ? ViewSizeUtils.getViewWidth(view): params.width ;

    headerChildrenWidth.add(width);

   }


  }


  return headerChildrenWidth.toArray(new Integer[headerChildrenWidth.size()]);
 }
 /**
  * Get each width of right header child
  * @return
  */
 private Integer[] getRightHeaderChildrenWidth(){

  List<Integer> headerChildrenWidth = new ArrayList<Integer>();

  int rightHeaderColumnCount = rightTable.headerHorizontalLinearLayout.getChildCount();

  for(int x = 0 ; x < rightHeaderColumnCount ; x++){

   HeaderRow tableRow =  (HeaderRow) rightTable.headerHorizontalLinearLayout.getChildAt(x);
   int headerRowChildCount = tableRow.secondLvlLinearLayout.getChildCount();

   for(int y = 0 ; y < headerRowChildCount ; y++){

    View view = tableRow.secondLvlLinearLayout.getChildAt(y);

    LinearLayout.LayoutParams params = (LayoutParams) view.getLayoutParams();

    int width = params.width <=0 ? ViewSizeUtils.getViewWidth(view) : params.width ;

    headerChildrenWidth.add(width);
   }


  }

  return headerChildrenWidth.toArray(new Integer[headerChildrenWidth.size()]);
 }
 /**
  * Resize each body column to match each other
  */
 private  void resizeBodyChildrenHeight(){

  int leftHeaderFirstLvlHighestHeight = 0;


  for(LinearLayout lin : leftTable.bodyLinearLayoutTempMem){

   int childCount = lin.getChildCount();

   for(int x = 0 ; x < childCount; x++){
    int width = ViewSizeUtils.getViewHeight(lin.getChildAt(x));
    if(leftHeaderFirstLvlHighestHeight < width){
     leftHeaderFirstLvlHighestHeight = width;

    }
   }


  }

  int rightHeaderFirstLvlHighestHeight = 0;
  //int rightHeaderFirstLvlHighestHeightIndex = 0;
  for(LinearLayout lin : rightTable.bodyLinearLayoutTempMem){

   int childCount = lin.getChildCount();

   for(int x = 0 ; x < childCount; x++){
    int width = ViewSizeUtils.getViewHeight(lin.getChildAt(x));
    if(rightHeaderFirstLvlHighestHeight < width){
     rightHeaderFirstLvlHighestHeight = width;
     //rightHeaderFirstLvlHighestHeightIndex = x;
    }
   }


  }

  boolean isHighestHighInLeft = leftHeaderFirstLvlHighestHeight > rightHeaderFirstLvlHighestHeight;


  for(LinearLayout lin : leftTable.bodyLinearLayoutTempMem){

   int childCount = lin.getChildCount();

   for(int x = 0 ; x < childCount; x++){
    LinearLayout.LayoutParams params = (LayoutParams) lin.getChildAt(x).getLayoutParams();
    params.height = isHighestHighInLeft ? leftHeaderFirstLvlHighestHeight : rightHeaderFirstLvlHighestHeight;

   }


  }

  for(LinearLayout lin : rightTable.bodyLinearLayoutTempMem){

   int childCount = lin.getChildCount();

   for(int x = 0 ; x < childCount; x++){
    LinearLayout.LayoutParams params = (LayoutParams) lin.getChildAt(x).getLayoutParams();
    params.height = isHighestHighInLeft ? leftHeaderFirstLvlHighestHeight : rightHeaderFirstLvlHighestHeight;

   }


  }

 }
 /**
  * 
  * @author lau
  *
  */
 class LoadingDialog extends Dialog{

   LoadingDialog(Context context) {
   super(context);
   this.setCancelable(false);
   this.requestWindowFeature(Window.FEATURE_NO_TITLE);
   this.init(context);
  }

   private void init(Context context){
    TextView textView = new TextView(context);
    textView.setText("Please wait loading data..");

    this.setContentView(textView);

   }
 }
 class Passenger{
  String name;
  char gender;
  int ticketNum;
  String validUntil;
  String setSequence;
  String countryFrom;
  String countryTo;
 }
}

And so on, sorry, an answer is limited to 30 000 characters.


Screenshot of multi-scroll view

Here is my solution using recycler views that sync within nested fragments, available on github: https://github.com/simplyAmazin87/MultiScrollView

Here is the gist of it, first we have the main activity layout:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:background="@color/colorlight"
        android:layout_height="match_parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/tbl_border2"
            android:orientation="horizontal">

            <TextView
                android:text="MultiScroll Table View"
                android:id="@+id/statText"
                android:textSize="24sp"
                android:paddingRight="20dp"
                android:textColor="@color/colorDarkBlue"
                android:gravity="center_horizontal|center_vertical"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
        </LinearLayout>

        <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/main_content"
            tools:context=".activities.MainActivity">

            <!-- TODO: Update blank fragment layout -->

        </FrameLayout>

    </LinearLayout>

Then we have our main fragment where we define the static portion of the header, a recycler view for the horizontal portion of the header, and also a frame layout within a scrollview so we can add the content that we want to scroll vertically:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:splitMotionEvents="true"
        android:layout_width="match_parent"
        android:background="@color/colorlight"
        android:layout_margin="2dp"
        android:layout_height="match_parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:splitMotionEvents="false"
            android:orientation="horizontal">
            <RelativeLayout
                android:layout_width="80dp"
                android:layout_height="wrap_content">
                <TextView
                    android:layout_width="match_parent"
                    android:textAppearance="?android:attr/textAppearanceLarge"
                    android:gravity="center_horizontal"
                    android:background="@drawable/tbl_border"
                    android:layout_height="wrap_content"
                    android:text="Static1"
                    android:id="@+id/hdr_Col_St1"
                    android:textSize="20dp"
                    android:padding="4dp"
                    android:textColor="@color/colorlight"/>
            </RelativeLayout>
            <RelativeLayout
                android:layout_width="80dp"
                android:layout_height="wrap_content">
                <TextView
                    android:layout_width="match_parent"
                    android:textAppearance="?android:attr/textAppearanceLarge"
                    android:gravity="center_horizontal"
                    android:background="@drawable/tbl_border"
                    android:layout_height="wrap_content"
                    android:text="Static2"
                    android:id="@+id/hdr_Col_St2"
                    android:textSize="20dp"
                    android:padding="4dp"
                    android:textColor="@color/colorlight"/>
            </RelativeLayout>
            <android.support.v7.widget.RecyclerView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@drawable/tbl_border"
                android:id="@+id/hdr_recycler_view"
                ></android.support.v7.widget.RecyclerView>

        </LinearLayout>

        <android.support.v4.widget.NestedScrollView
            android:id="@+id/vertical_scroll"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <FrameLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:id="@+id/detail_content">
            </FrameLayout>

        </android.support.v4.widget.NestedScrollView>

    </LinearLayout>

Finally we have our final layout where we define the portion of the table that can scroll vertically, along with a recycler view with a horizontal orientation that will be able to scroll both ways. This recycler view must sync with the recycler view defined for the header in order to work correctly:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="2dp"
        android:splitMotionEvents="false"
        android:orientation="horizontal">
        <RelativeLayout
            android:layout_width="80dp"
            android:layout_height="wrap_content"
            android:background="@drawable/tbl_border2">

            <TextView
                android:layout_width="match_parent"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:layout_height="wrap_content"
                android:gravity="center_horizontal"
                android:text="A1"
                android:layout_marginTop="5dp"
                android:id="@+id/ColA1"
                android:textSize="20dp"
                android:padding="4dp"
                android:textColor="@color/colorDarkBlue"
                />
            <TextView
                android:layout_width="match_parent"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:layout_height="wrap_content"
                android:text="A2"
                android:gravity="center_horizontal"
                android:layout_marginTop="5dp"
                android:layout_below="@id/ColA1"
                android:id="@+id/ColA2"
                android:textSize="20dp"
                android:padding="4dp"
                android:textColor="@color/colorDarkBlue"
                />
            <TextView
                android:layout_width="match_parent"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:layout_height="wrap_content"
                android:text="A3"
                android:layout_marginTop="5dp"
                android:gravity="center_horizontal"
                android:layout_below="@id/ColA2"
                android:id="@+id/ColA3"
                android:textSize="20dp"
                android:padding="4dp"
                android:textColor="@color/colorDarkBlue"
                />
            <TextView
                android:layout_width="match_parent"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:layout_height="wrap_content"
                android:text="A4"
                android:layout_marginTop="5dp"
                android:layout_below="@id/ColA3"
                android:id="@+id/ColA4"
                android:textSize="20dp"
                android:gravity="center_horizontal"
                android:padding="4dp"
                android:textColor="@color/colorDarkBlue"
                />
            <TextView
                android:layout_width="match_parent"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:layout_height="wrap_content"
                android:text="A5"
                android:layout_marginTop="5dp"
                android:layout_below="@id/ColA4"
                android:id="@+id/ColA5"
                android:textSize="20dp"
                android:gravity="center_horizontal"
                android:padding="4dp"
                android:textColor="@color/colorDarkBlue"
                />
            <TextView
                android:layout_width="match_parent"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:layout_height="wrap_content"
                android:text="A6"
                android:layout_marginTop="5dp"
                android:layout_below="@id/ColA5"
                android:id="@+id/ColA6"
                android:textSize="20dp"
                android:gravity="center_horizontal"
                android:padding="4dp"
                android:textColor="@color/colorDarkBlue"
                />
            <TextView
                android:layout_width="match_parent"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:layout_height="wrap_content"
                android:text="A7"
                android:layout_marginTop="5dp"
                android:layout_below="@id/ColA6"
                android:id="@+id/ColA7"
                android:textSize="20dp"
                android:gravity="center_horizontal"
                android:padding="4dp"
                android:textColor="@color/colorDarkBlue"
                />
            <TextView
                android:layout_width="match_parent"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:layout_height="wrap_content"
                android:text="A8"
                android:layout_marginTop="5dp"
                android:layout_below="@id/ColA7"
                android:id="@+id/ColA8"
                android:textSize="20dp"
                android:gravity="center_horizontal"
                android:padding="4dp"
                android:textColor="@color/colorDarkBlue"
                />
            <TextView
                android:layout_width="match_parent"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:layout_height="wrap_content"
                android:text="A9"
                android:layout_marginTop="5dp"
                android:layout_below="@id/ColA8"
                android:id="@+id/ColA9"
                android:textSize="20dp"
                android:gravity="center_horizontal"
                android:padding="4dp"
                android:textColor="@color/colorDarkBlue"
                />
            <TextView
                android:layout_width="match_parent"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:layout_height="wrap_content"
                android:text="A10"
                android:layout_marginTop="5dp"
                android:layout_below="@id/ColA9"
                android:id="@+id/ColA10"
                android:textSize="20dp"
                android:gravity="center_horizontal"
                android:padding="4dp"
                android:textColor="@color/colorDarkBlue"
                />
            <TextView
                android:layout_width="match_parent"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:layout_height="wrap_content"
                android:text="A11"
                android:layout_marginTop="5dp"
                android:layout_below="@id/ColA10"
                android:id="@+id/ColA11"
                android:textSize="20dp"
                android:gravity="center_horizontal"
                android:padding="4dp"
                android:textColor="@color/colorDarkBlue"
                />
            <TextView
                android:layout_width="match_parent"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:layout_height="wrap_content"
                android:text="A12"
                android:layout_marginTop="5dp"
                android:layout_below="@id/ColA11"
                android:id="@+id/ColA12"
                android:textSize="20dp"
                android:padding="4dp"
                android:gravity="center_horizontal"
                android:textColor="@color/colorDarkBlue"
                />
            <TextView
                android:layout_width="match_parent"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:layout_height="wrap_content"
                android:text="A13"
                android:layout_marginTop="5dp"
                android:layout_below="@id/ColA12"
                android:id="@+id/ColA13"
                android:textSize="20dp"
                android:padding="4dp"
                android:gravity="center_horizontal"
                android:textColor="@color/colorDarkBlue"
                />
            <TextView
                android:layout_width="match_parent"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:layout_height="wrap_content"
                android:text="A14"
                android:layout_marginTop="5dp"
                android:layout_below="@id/ColA13"
                android:id="@+id/ColA14"
                android:textSize="20dp"
                android:padding="4dp"
                android:gravity="center_horizontal"
                android:textColor="@color/colorDarkBlue"
                />
            <TextView
                android:layout_width="match_parent"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:layout_height="wrap_content"
                android:text="A15"
                android:layout_marginTop="5dp"
                android:layout_below="@id/ColA14"
                android:id="@+id/ColA15"
                android:textSize="20dp"
                android:padding="4dp"
                android:gravity="center_horizontal"
                android:textColor="@color/colorDarkBlue"
                />

        </RelativeLayout>
        <RelativeLayout
            android:layout_width="80dp"
            android:layout_height="wrap_content"
            android:background="@drawable/tbl_border2">

            <TextView
                android:layout_width="match_parent"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:layout_height="wrap_content"
                android:gravity="center_horizontal"
                android:text="B1"
                android:layout_marginTop="5dp"
                android:id="@+id/ColB1"
                android:textSize="20dp"
                android:padding="4dp"
                android:textColor="@color/colorDarkBlue"
                />
            <TextView
                android:layout_width="match_parent"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:layout_height="wrap_content"
                android:text="B2"
                android:gravity="center_horizontal"
                android:layout_marginTop="5dp"
                android:layout_below="@id/ColB1"
                android:id="@+id/ColB2"
                android:textSize="20dp"
                android:padding="4dp"
                android:textColor="@color/colorDarkBlue"
                />
            <TextView
                android:layout_width="match_parent"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:layout_height="wrap_content"
                android:text="B3"
                android:layout_marginTop="5dp"
                android:gravity="center_horizontal"
                android:layout_below="@id/ColB2"
                android:id="@+id/ColB3"
                android:textSize="20dp"
                android:padding="4dp"
                android:textColor="@color/colorDarkBlue"
                />
            <TextView
                android:layout_width="match_parent"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:layout_height="wrap_content"
                android:text="B4"
                android:layout_marginTop="5dp"
                android:layout_below="@id/ColB3"
                android:id="@+id/ColB4"
                android:textSize="20dp"
                android:gravity="center_horizontal"
                android:padding="4dp"
                android:textColor="@color/colorDarkBlue"
                />
            <TextView
                android:layout_width="match_parent"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:layout_height="wrap_content"
                android:text="B5"
                android:layout_marginTop="5dp"
                android:layout_below="@id/ColB4"
                android:id="@+id/ColB5"
                android:textSize="20dp"
                android:gravity="center_horizontal"
                android:padding="4dp"
                android:textColor="@color/colorDarkBlue"
                />
            <TextView
                android:layout_width="match_parent"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:layout_height="wrap_content"
                android:text="B6"
                android:layout_marginTop="5dp"
                android:layout_below="@id/ColB5"
                android:id="@+id/ColB6"
                android:textSize="20dp"
                android:gravity="center_horizontal"
                android:padding="4dp"
                android:textColor="@color/colorDarkBlue"
                />
            <TextView
                android:layout_width="match_parent"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:layout_height="wrap_content"
                android:text="B7"
                android:layout_marginTop="5dp"
                android:layout_below="@id/ColB6"
                android:id="@+id/ColB7"
                android:textSize="20dp"
                android:gravity="center_horizontal"
                android:padding="4dp"
                android:textColor="@color/colorDarkBlue"
                />
            <TextView
                android:layout_width="match_parent"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:layout_height="wrap_content"
                android:text="B8"
                android:layout_marginTop="5dp"
                android:layout_below="@id/ColB7"
                android:id="@+id/ColB8"
                android:textSize="20dp"
                android:gravity="center_horizontal"
                android:padding="4dp"
                android:textColor="@color/colorDarkBlue"
                />
            <TextView
                android:layout_width="match_parent"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:layout_height="wrap_content"
                android:text="B9"
                android:layout_marginTop="5dp"
                android:layout_below="@id/ColB8"
                android:id="@+id/ColB9"
                android:textSize="20dp"
                android:gravity="center_horizontal"
                android:padding="4dp"
                android:textColor="@color/colorDarkBlue"
                />
            <TextView
                android:layout_width="match_parent"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:layout_height="wrap_content"
                android:text="B10"
                android:layout_marginTop="5dp"
                android:layout_below="@id/ColB9"
                android:id="@+id/ColB10"
                android:textSize="20dp"
                android:gravity="center_horizontal"
                android:padding="4dp"
                android:textColor="@color/colorDarkBlue"
                />
            <TextView
                android:layout_width="match_parent"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:layout_height="wrap_content"
                android:text="B11"
                android:layout_marginTop="5dp"
                android:layout_below="@id/ColB10"
                android:id="@+id/ColB11"
                android:textSize="20dp"
                android:gravity="center_horizontal"
                android:padding="4dp"
                android:textColor="@color/colorDarkBlue"
                />
            <TextView
                android:layout_width="match_parent"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:layout_height="wrap_content"
                android:text="B12"
                android:layout_marginTop="5dp"
                android:layout_below="@id/ColB11"
                android:id="@+id/ColB12"
                android:textSize="20dp"
                android:padding="4dp"
                android:gravity="center_horizontal"
                android:textColor="@color/colorDarkBlue"
                />
            <TextView
                android:layout_width="match_parent"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:layout_height="wrap_content"
                android:text="B13"
                android:layout_marginTop="5dp"
                android:layout_below="@id/ColB12"
                android:id="@+id/ColB13"
                android:textSize="20dp"
                android:padding="4dp"
                android:gravity="center_horizontal"
                android:textColor="@color/colorDarkBlue"
                />
            <TextView
                android:layout_width="match_parent"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:layout_height="wrap_content"
                android:text="B14"
                android:layout_marginTop="5dp"
                android:layout_below="@id/ColB13"
                android:id="@+id/ColB14"
                android:textSize="20dp"
                android:padding="4dp"
                android:gravity="center_horizontal"
                android:textColor="@color/colorDarkBlue"
                />
            <TextView
                android:layout_width="match_parent"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:layout_height="wrap_content"
                android:text="B15"
                android:layout_marginTop="5dp"
                android:layout_below="@id/ColB14"
                android:id="@+id/ColB15"
                android:textSize="20dp"
                android:padding="4dp"
                android:gravity="center_horizontal"
                android:textColor="@color/colorDarkBlue"
                />
        </RelativeLayout>

        <android.support.v7.widget.RecyclerView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/tbl_border2"
            android:id="@+id/dtl_recyler_view"
            ></android.support.v7.widget.RecyclerView>

    </LinearLayout>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜