Sometimes programmer need to customize the layout of application they are developing.
Like what I have experienced a couple month in developing android application.
I need to develop android table with fixed header column and fixed row.
Android has Table kind of element but it just a table like in Html, no fixed header and row.
Search... search... search and search, but there is nothing such table with fixed header column and fixed row.
I figured out that, that I have to do it by my self.
Watch the actual result.
Then, below is the drawing that I started up.
Android table with fixed header and column. |
and here is the result.
And now here are the codes.
1. MainActivity.java
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Table table = new Table(this); setContentView(table); } }
Nothing special in this code. It is just a simple activity which set our Table as contentView.
By the way, the Table class is not the android table. That table is our own created.
2. 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; } }
That is the Table. It hold everything.
3. HeaderRow.java
public class HeaderRow extends LinearLayout{ protected final static int NEXT_PAGINATION_TAG = 19860116; protected final static int PREVIUOS_PAGINATION_TAG = 19860117; final int PADDING = 5; LinearLayout firtLvlLinearLayout; LinearLayout secondLvlLinearLayout; /** * @nextTextView and @previousTextView = for pagination */ TextView nextTextView; TextView previousTextView; Object firstLvlLabel; Object[] secondLvlLabel; String scrollViewTag; OnClickListenerOfPagination onClickListenerOfPagination; Table table; public HeaderRow(Table table, Object firstLvlLabel, Object[] secondLvlLabel, String scrollViewTag) { super(table.getContext()); this.table = table; this.firstLvlLabel = firstLvlLabel; this.secondLvlLabel = secondLvlLabel; this.scrollViewTag = scrollViewTag; this.properties(); this.init(); this.initFirstLvlHeaders(); this.initSecondLvlHeader(); this.analizeFirstAndSecondHeaderWidth(); } private void properties(){ this.setOrientation(LinearLayout.VERTICAL); } /** * initialization */ private void init(){ this.onClickListenerOfPagination = new OnClickListenerOfPagination(table); this.firtLvlLinearLayout = new LinearLayout(this.getContext()); this.firtLvlLinearLayout.setOrientation(LinearLayout.HORIZONTAL); this.secondLvlLinearLayout = new LinearLayout(this.getContext()); this.secondLvlLinearLayout.setOrientation(LinearLayout.HORIZONTAL); if(Table.IS_TWO_COLUMN_HEADER){ this.addView(firtLvlLinearLayout); this.addView(secondLvlLinearLayout); }else{ this.addView(secondLvlLinearLayout); } } /** * top most header column */ private void initFirstLvlHeaders(){ LinearLayout.LayoutParams firstLvlTextViewParams = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); firstLvlTextViewParams.setMargins(1, 1, 1, 1); firstLvlTextViewParams.weight = 1; TextView firstLvlTextView = new TextView(this.getContext()); firstLvlTextView.setText(firstLvlLabel.toString()); firstLvlTextView.setPadding(PADDING, PADDING, PADDING, PADDING); firstLvlTextView.setBackgroundColor(Table.HEADER_BACKROUND_COLOR); firstLvlTextView.setGravity(Gravity.CENTER); firstLvlTextView.setLayoutParams(firstLvlTextViewParams); this.firtLvlLinearLayout.addView(firstLvlTextView); } /** * second header column */ private void initSecondLvlHeader(){ int secondLvlHeaderLblCount = this.secondLvlLabel.length; for(int x = 0 ; x < secondLvlHeaderLblCount ; x++){ LinearLayout.LayoutParams firstLvlTextViewParams = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT); firstLvlTextViewParams.setMargins(1, 1, 1, 1); String labelString = secondLvlLabel[x].toString(); if(labelString.equalsIgnoreCase(Table.NAME)){ LinearLayout paginationLinearLayout = this.paginationLinearLayout(labelString); paginationLinearLayout.setPadding(PADDING, PADDING, PADDING, PADDING); paginationLinearLayout.setBackgroundColor(Table.HEADER_BACKROUND_COLOR); paginationLinearLayout.setLayoutParams(firstLvlTextViewParams); this.secondLvlLinearLayout.addView(paginationLinearLayout); }else{ TextView secondLvlTextView = new TextView(this.getContext()); secondLvlTextView.setText(labelString.equalsIgnoreCase("Product") ? "Product": labelString); secondLvlTextView.setPadding(PADDING, PADDING, PADDING, PADDING); secondLvlTextView.setBackgroundColor(Table.HEADER_BACKROUND_COLOR); secondLvlTextView.setGravity(Gravity.CENTER); secondLvlTextView.setLayoutParams(firstLvlTextViewParams); this.secondLvlLinearLayout.addView(secondLvlTextView); } } } /** * layout for pagination * @param label * @return */ private LinearLayout paginationLinearLayout(String label){ LinearLayout paginationLinearLayout = new LinearLayout(this.getContext()); TextView labelTextView = new TextView(this.getContext()); labelTextView.setGravity(Gravity.CENTER); labelTextView.setText(label); LinearLayout.LayoutParams labelTextViewParams = new LinearLayout.LayoutParams(0,LayoutParams.MATCH_PARENT); labelTextViewParams.weight = 1; this.nextTextView = new TextView(this.getContext()); this.nextTextView.setText(" "+Table.NEXT_ARROW+" "); this.nextTextView.setGravity(Gravity.CENTER); this.nextTextView.setTag(NEXT_PAGINATION_TAG); this.nextTextView.setBackgroundDrawable(new CustomStateListDrawable(nextTextView)); this.nextTextView.setOnClickListener(this.onClickListenerOfPagination); LinearLayout.LayoutParams nextTextViewParams = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.MATCH_PARENT); this.previousTextView = new TextView(this.getContext()); this.previousTextView.setText(" "+Table.PREVIOUS_ARROW+" "); this.previousTextView.setGravity(Gravity.CENTER); this.previousTextView.setTag(PREVIUOS_PAGINATION_TAG); this.previousTextView.setTextColor(Table.HEADER_BACKROUND_COLOR); this.previousTextView.setBackgroundDrawable(new CustomStateListDrawable(previousTextView)); this.previousTextView.setOnClickListener(this.onClickListenerOfPagination); LinearLayout.LayoutParams previousTextViewParams = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.MATCH_PARENT); paginationLinearLayout.addView(previousTextView,previousTextViewParams); paginationLinearLayout.addView(labelTextView,labelTextViewParams); paginationLinearLayout.addView(nextTextView,nextTextViewParams); return paginationLinearLayout; } /** * adjust the width of headers to match in screen size */ private void analizeFirstAndSecondHeaderWidth(){ int headerSecondLvlChildrenCount = secondLvlLinearLayout.getChildCount(); /** * LEFT = 1; * RIGHT = 1; * get first lvl header width + (number of second lvl * (PADDING * (LEFT + RIGHT)) ) */ int headerFirstLvlWidth = ViewSizeUtils.getViewWidth(firtLvlLinearLayout.getChildAt(0)) + (headerSecondLvlChildrenCount * (PADDING * 2)); int headerSecondLvlChildrenTotalWidth = 0; for(int x = 0 ; x < headerSecondLvlChildrenCount ;x++){ headerSecondLvlChildrenTotalWidth += ViewSizeUtils.getViewWidth(secondLvlLinearLayout.getChildAt(x)); } int availableWidht = headerFirstLvlWidth - headerSecondLvlChildrenTotalWidth; int widhtForEachChild = (int) Math.ceil(availableWidht / headerSecondLvlChildrenCount); if(availableWidht <= 0){ // if no available width, do nothing return; } for(int x = 0 ; x < headerSecondLvlChildrenCount ;x++){ View view = secondLvlLinearLayout.getChildAt(x); LinearLayout.LayoutParams params = (LayoutParams) view.getLayoutParams(); params.width = params.width <=0 ? ViewSizeUtils.getViewWidth(view) + widhtForEachChild : params.width + widhtForEachChild; } } }
That is the HeaderRow.java. This is a left and right header of our table.
4. OnClickListenerOfPagination.java
class OnClickListenerOfPagination implements OnClickListener { Table table; OnClickListenerOfPagination(Table table){ this.table = table; } @Override public void onClick(View view) { // show loading dialog table.loadingDialog.show(); int tag = (Integer) view.getTag(); switch (tag) { case HeaderRow.NEXT_PAGINATION_TAG: table.pageNumber++; table.loadData(); table.leftTable.headerRow.previousTextView.setTextColor(Color.BLACK); table.leftTable.headerRow.previousTextView.setEnabled(true); if(table.pageNumber == table.totalPage){ table.leftTable.headerRow.nextTextView.setEnabled(false); table.leftTable.headerRow.nextTextView.setTextColor(Table.HEADER_BACKROUND_COLOR); } break; case HeaderRow.PREVIUOS_PAGINATION_TAG: table.pageNumber--; table.loadData(); // set text color black table.leftTable.headerRow.nextTextView.setTextColor(Color.BLACK); table.leftTable.headerRow.nextTextView.setEnabled(true); if(table.pageNumber == 1){ table.leftTable.headerRow.previousTextView.setEnabled(false); table.leftTable.headerRow.previousTextView.setTextColor(Table.HEADER_BACKROUND_COLOR); } break; default: break; } table.loadingDialog.dismiss(); } }
That is OnClickListenerOfPagination. This class is responsible for pagination.
That are the important java file in our custom android table with fixed header, header with column span and fixed row.
Download Source Code Here
Happy coding everyone.
Hi! Thanks for the useful code. Would you mind stating the license for it?
ReplyDeleteWe'd love to use it in our opensource project but for that to happen it needs to be GPLv3+ compatible.
I don't know how to apply/create license in source code. By the way, you can use the source code.
ReplyDeleteThank you!
DeleteP.S. If you want your code to be used as widely as possible, with reference to you as its author, it makes sense to choose one of the permissive opensource licenses (like MIT or BSD license). They are easy to read and understand, and come with instructions how to apply them to your code.
There's more info - https://opensource.org/faq#apply-license
Thank's for info.
DeleteCan not download this code.
ReplyDeleteplease share the source code with me on lokesh@altius.cc
ReplyDeleteThis comment has been removed by the author.
ReplyDeletehii,how can i get this code
ReplyDeleteplease share the code with me on joylobo404@gmail.com
ReplyDeleteplease share the source code with me on kamdem.yves@gmail.com
ReplyDeleteCould you please share the source code with me on ntanduc2288@gmail.com.
ReplyDeleteThanks,
Please help, could you please just post here or send me by email the source code of the class BodyTable? I think the rest will be fine. I had no answer since my last query here and on google+. please. Thanks
ReplyDeleteWould you please share the cource code with me on nasper.2458@gmail.com.
ReplyDeleteThank you so much.
please share the code with me on apnair007@gmail.com
ReplyDeleteplease share the code with me on chengpanchng@gmail.com
ReplyDeleteVery impressive and useful.
ReplyDeleteA Direct download link would be nice...
Thanks
please share the code with me on cristianpreciado93@gmail.com
ReplyDeleteHi, share the code on my email, nalinapowlika99@gmail.com.
ReplyDeleteplease send me this code .my email is rumeshdissanayaka@gmil.com
ReplyDeleteplease send me code madhurashetty95@gmail.com
ReplyDeletePlease send me code on aeshashah1310@gmail.com
ReplyDeleteThis comment has been removed by the author.
ReplyDelete20930726@students.liu.edu.lb
ReplyDeleteThis comment has been removed by the author.
ReplyDeletenguyenthanhluan.ntc@gmail.com.. tks
ReplyDeleteWell done! and thank you for sharing - please email me the direct D/L link at frederique.martines@gmail.com
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteplease share the code with me on bransonlee0426@gmail.com
ReplyDeletety~
This is an awesome article. One quick question, will it work on all APIs?
ReplyDeleteI think it'll only work in API 7
Deletesource code please
ReplyDeletecode please
ReplyDeletesource code please
ReplyDeleteThis comment has been removed by the author.
ReplyDeletesource code please
ReplyDeletesource code please
ReplyDeletesource code please crudoperational@gmail.com
ReplyDeletePlease share your source code to pictaro@gmail.com
ReplyDeleteThank you.
hi, please share the source code to haalikes216@gmail.com
ReplyDeleteThank you!
Hi, Can you please share source code with rajaeshwar@gmai.com
ReplyDeleteplease share source code with phuochuudo@gmai.com
ReplyDeleteThanks for the code...it really helped me a lot..just one question..how to make header width size to its maximum length of text in that column i.e wrap content
ReplyDeletecan you please send me source code as soon as possible, I need this code for my project.
ReplyDeletesahil.kashyap@triologic.com
DeleteHi,
ReplyDeleteNice post. Please share the code.
email ID : telang.trupti@gmail.com
Regards,
Very nice Table! I was looking for something like this!
ReplyDeleteCould you send me the Source Code?
email: giopromolla@gmail.com
Good idea!.
ReplyDeleteplease share the code with me on Email : porntep@gmail.com
Thank You.^^
Hai,
ReplyDeleteThis is kalyan Email billstash14@gmail.com can u share Code
Hi, excelent code. I really appreciate if you can share your code with me too. Thanks in advance. My email abnerh69@gmail.com
ReplyDeletehi, please share the source code to pankajdhomkar007@gmail.com
ReplyDeleteThank you
Please share the code to disha.aseum@gmail.com
ReplyDeleteThank you
Please share the source code on pankajdhomkar@gmail.com
ReplyDeleteThank you.
HELLO SIR. VERY NICE CODE... Can you guide me on how to change each cell's data ??? i want to edit each rows and columns data .. you can put a mail at deepgagan100@hotmail.coom
ReplyDeleteThis comment has been removed by the author.
ReplyDeletejustpi0313@gmail.com
ReplyDeleteThank you
alanmoraes100@gmail.com
ReplyDeleteThank you
hii,how can i get this code amitmehta.babbu07@gmail.com
ReplyDeleteCould you please share me your source code? my email is: ttdat.0410@gmail.com .. Thanks so much.:)
ReplyDeleteplease share the code with itclubonline@gmail.com
ReplyDeletePlease share the code. jawagag@gmail.com
ReplyDeleteFrom Indonesia, its a great thanks if you send me the code samueltambunan1991@gmail.com
ReplyDeleteplease share the code with newrcname@gmail.com
ReplyDeleteplease share the code with me on satenterus@gmail.com
ReplyDeleteGreat project. Please share the code with me on thmstong@gmail.com. Thanks a lot
ReplyDeleteGreat Project, Thank You For The Information, Can You Share The Source Code In My E-mail rigelarmanda@gmail.com
ReplyDeleteThank You
Nice code, but I have a question. But I have problem, I need the table starting not on top of the layout, coz there is a menu on top. How modify the code???
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteHi, Can you please send me code with adding spinner for one column to the same table. It will be great help.
ReplyDeletethanks in advance.
my E-mail:sharath.shetty.r@gmail.com
Please send me the code to my e-mai:sharath.shetty.r@gmail.com
ReplyDeletehow can we add new row in this table?
ReplyDeletedynamically
Delete