Skip to content

Commit

Permalink
feat(md-3350): column totals android (#106)
Browse files Browse the repository at this point in the history
* feat: column totals

* feat: cleaup

* feat: rebase & measure header height
  • Loading branch information
gruskal authored Nov 2, 2022
1 parent cb0517c commit de75078
Show file tree
Hide file tree
Showing 11 changed files with 239 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ public void setData(DataCell cell) {
if (cell.isDim) {
selectionsEngine.observe(this);
content.setSelected(selectionsEngine.contains(cell));
content.updateBackgroundColor();
content.updateBackgroundColor(false);
postInvalidate();
}
}
Expand Down Expand Up @@ -137,13 +137,13 @@ public void onSelectionsChanged(String s) {
String me = SelectionsEngine.getKeyFrom(cell);
if(received.equalsIgnoreCase(me)) {
content.toggleSelected();
content.updateBackgroundColor();
content.updateBackgroundColor(true);
}
}

public void onClear() {
content.setSelected(false);
content.updateBackgroundColor();
content.updateBackgroundColor(false);
}

public void onRecycled() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,11 +151,13 @@ public void setAlignment(DataColumn column) {
}
}

public void updateBackgroundColor() {
public void updateBackgroundColor(boolean shouldAnimate) {
int color = selected ? TableTheme.selectedBackground : Color.TRANSPARENT;
ViewGroup wrapper = (ViewGroup) cellView.getParent().getParent();
wrapper.setBackgroundColor(color);
startAnimation(fadeIn);
if(shouldAnimate) {
startAnimation(fadeIn);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ private Rect getMeasuredTextBounds() {
return bounds;
}

public void updateBackgroundColor() {
public void updateBackgroundColor(boolean shouldAnimate) {
int bgColor = cell.cellBackgroundColorValid ? cell.cellBackgroundColor : Color.TRANSPARENT;
int fgColor = cell.cellForegroundColorValid ? cell.cellForegroundColor : tableView.cellContentStyle.color;
int color = selected ? TableTheme.selectedBackground : bgColor ;
Expand All @@ -91,7 +91,9 @@ public void updateBackgroundColor() {
setBackgroundColor(color);
setTextColor(textColor);
postInvalidate();
startAnimation(fadeIn);
if(shouldAnimate) {
startAnimation(fadeIn);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import android.view.MotionEvent;

public interface Content {
void updateBackgroundColor();
void updateBackgroundColor(boolean shouldAnimate);
void setGestureDetector(GestureDetector gestureDetector);
void setSelected(boolean selected);
void toggleSelected();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
import android.widget.RelativeLayout;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import com.facebook.react.bridge.ReadableArray;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
Expand All @@ -38,11 +41,14 @@ public class DataProvider extends RecyclerView.Adapter<RecyclerView.ViewHolder>
boolean isDataView = false;
List<DataRow> rows = null;
List<DataColumn> dataColumns = null;
List<TotalsCell> totalsCells = null;
Set<RowViewHolder> cachedViewHolders = new HashSet<>();
Set<RowViewHolder> cachedFirstColumnViewHolders = new HashSet<>();
ColumnWidths columnWidths;
DataSize dataSize = null;
boolean loading = false;
String totalsLabel;
String totalsPosition;
Boolean isFirstColumnFrozen = false;
final TableView tableView;
public static final float minWidth = PixelUtils.dpToPx(80);
Expand All @@ -61,6 +67,12 @@ public void setLoading(boolean loading) {
this.loading = loading;
}

public void setTotals(ReadableArray totals, String totalsLabel, String totalsPosition) {
this.totalsCells = HeaderViewFactory.getTotalsCellList(totals);
this.totalsLabel = totalsLabel;
this.totalsPosition = totalsPosition;
}

public void setFirstColumnFrozen(boolean firstColumnFrozen) {
this.isFirstColumnFrozen = firstColumnFrozen;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@

import android.content.Context;
import android.graphics.Color;
import android.graphics.Outline;
import android.graphics.Typeface;
import android.graphics.text.LineBreaker;
import android.os.Build;
import android.os.Handler;
import android.provider.CalendarContract;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
import android.widget.FrameLayout;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
Expand Down Expand Up @@ -37,11 +40,15 @@ public class HeaderViewFactory {
List<TotalsCell> totalsCells = new ArrayList<>();
List<DataColumn> dataColumns;
final HeaderContentStyle headerContentStyle;
HeaderViewFactory headerViewFactory;
String totalsLabel;
boolean topPosition;
HeaderView headerView = null;
AutoLinearLayout footerView = null;
AutoLinearLayout totalsView = null;
TableView tableView;
public AutoLinearLayout getFooterView() {
return footerView;

public AutoLinearLayout getTotalsView() {
return totalsView;
}

public HeaderView getHeaderView() {
Expand All @@ -53,14 +60,21 @@ public List<DataColumn> getDataColumns() {
}

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public HeaderViewFactory(List<DataColumn> dataColumns, TableView tableView, Context context, HeaderContentStyle contentStyle) {
public HeaderViewFactory(List<DataColumn> dataColumns, List<TotalsCell> totalsCells, String totalsLabel, boolean topPosition, TableView tableView, HeaderContentStyle contentStyle, Context context) {
this.tableView = tableView;
this.dataColumns = dataColumns;
this.totalsCells = totalsCells;
this.totalsLabel = totalsLabel;
this.topPosition = topPosition;
this.headerContentStyle = contentStyle;
buildHeader(context);
if (totalsCells != null) {
buildTotals(context);
}
}

public static HeaderCell buildFixedColumnCell(FrameLayout rootView, DataColumn column, TableView tableView) {
public static HeaderCell buildFixedColumnCell(FrameLayout rootView, DataColumn column, TableView tableView, boolean topPosition) {
int headerHeight = tableView.tableViewFactory.headerView.getMeasuredHeight();
int padding = (int) PixelUtils.dpToPx(16);

HeaderCell fixedFirstHeaderCell = new HeaderCell(rootView.getContext(), column, tableView);
Expand All @@ -70,29 +84,57 @@ public static HeaderCell buildFixedColumnCell(FrameLayout rootView, DataColumn c
fixedFirstHeaderCell.setTextColor(tableView.headerContentStyle.color);
fixedFirstHeaderCell.setText(column.label);
fixedFirstHeaderCell.setPadding(padding, 0, padding, 0);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(column.width, TableTheme.rowHeightFactor);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(column.width, headerHeight);
fixedFirstHeaderCell.setTop(0);
fixedFirstHeaderCell.setLeft(0);
fixedFirstHeaderCell.setZ(PixelUtils.dpToPx(headerZ));
fixedFirstHeaderCell.setLayoutParams(layoutParams);
fixedFirstHeaderCell.setGravity(Gravity.CENTER_VERTICAL);
fixedFirstHeaderCell.setBackgroundColor(TableTheme.headerBackgroundColor);
fixedFirstHeaderCell.setElevation((int)PixelUtils.dpToPx(4));

fixedFirstHeaderCell.setElevation((int) PixelUtils.dpToPx(4));
if (topPosition) {
fixedFirstHeaderCell.setOutlineProvider(null);
}
return fixedFirstHeaderCell;
}

public static TextView buildFixedTotalsCell(TableView tableView, DataColumn column, TotalsCell totalsCell, boolean topPosition) {
int headerHeight = tableView.tableViewFactory.headerView.getMeasuredHeight();
int padding = (int) PixelUtils.dpToPx(16);
TextView text = new TextView(tableView.getContext());
text.setMaxLines(1);
text.setTypeface(text.getTypeface(), Typeface.BOLD);
text.setEllipsize(TextUtils.TruncateAt.END);
if (column.isDim) {
text.setText(tableView.totalsLabel);
text.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
} else {
text.setGravity(Gravity.RIGHT | Gravity.CENTER_VERTICAL);
text.setText(totalsCell.qText);
}
text.setPadding(padding, 0, padding, 0);
text.setLayoutParams(new FrameLayout.LayoutParams(column.width, TableTheme.rowHeightFactor));
text.setBackgroundColor(Color.WHITE);
text.setZ((int) PixelUtils.dpToPx(headerZ));
int y = topPosition ? headerHeight : tableView.getMeasuredHeight() - TableTheme.rowHeightFactor * 2;
text.setY(y);
if (!topPosition) {
text.setOutlineProvider(null);
}

return text;
}

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void buildHeader(Context context) {
int padding = (int) PixelUtils.dpToPx(16);
int headerHeight = TableTheme.rowHeightFactor;
headerView = new HeaderView(context);
headerView.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, headerHeight));
headerView.setOrientation(LinearLayout.HORIZONTAL);
headerView.setElevation((int)PixelUtils.dpToPx(4));
headerView.setElevation((int) PixelUtils.dpToPx(4));
headerView.setBackgroundColor(TableTheme.headerBackgroundColor);
for(int i = 0; i < dataColumns.size(); i++) {

for (int i = 0; i < dataColumns.size(); i++) {
DataColumn column = dataColumns.get(i);

HeaderCell text = new HeaderCell(headerView.getContext(), column, this.tableView);
Expand All @@ -112,4 +154,53 @@ private void buildHeader(Context context) {
headerView.setDataColumns(dataColumns);
}

private void buildTotals(Context context) {
totalsView = new AutoLinearLayout(context);

totalsView.post(() -> {
int headerHeight = headerView.getMeasuredHeight();
int y = topPosition ? headerHeight : tableView.getMeasuredHeight() - TableTheme.rowHeightFactor * 2;

totalsView.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, TableTheme.rowHeightFactor));
totalsView.setOrientation(LinearLayout.HORIZONTAL);
totalsView.setElevation((int) PixelUtils.dpToPx(4));
totalsView.setZ((int) PixelUtils.dpToPx(headerZ));
totalsView.setY(y);
totalsView.setBackgroundColor(Color.WHITE);

// first add all fillers, then populate with the data
int j = 0;
for (int i = 0; i < dataColumns.size(); i++) {
DataColumn column = dataColumns.get(i);
TextView text = new TextView(context);
int padding = (int) PixelUtils.dpToPx(16);
text.setMaxLines(1);
text.setTypeface(text.getTypeface(), Typeface.BOLD);
text.setEllipsize(TextUtils.TruncateAt.END);
if (column.isDim && i == 0) {
text.setText(totalsLabel);
text.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
}
if (!column.isDim) {
if (j < totalsCells.size()) {
text.setGravity(Gravity.RIGHT | Gravity.CENTER_VERTICAL);
text.setText(totalsCells.get(j++).qText);
}
}
text.setPadding(padding, 0, padding, 0);
text.setLayoutParams(new LinearLayout.LayoutParams(column.width, TableTheme.rowHeightFactor));
totalsView.addView(text);
}
});

}

public static List<TotalsCell> getTotalsCellList(ReadableArray source) {
List<TotalsCell> totalsCells = new ArrayList<>();
for (int i = 0; i < source.size(); i++) {
TotalsCell cell = new TotalsCell(source.getMap(i));
totalsCells.add(cell);
}
return totalsCells;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ protected void onDraw(Canvas canvas) {
}

@Override
public void updateBackgroundColor() {
public void updateBackgroundColor(boolean shouldAnimate) {
// no selections
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableNativeMap;
import com.facebook.react.common.MapBuilder;
import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.uimanager.ThemedReactContext;
Expand Down Expand Up @@ -63,10 +64,21 @@ public void setFreezeFirstColumn(View view, Boolean value) {
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@ReactProp(name = "cols")
public void setCols(View view, @Nullable ReadableMap source) {
TableView tableView = (TableView) view;
String totalsLabel = null, totalsPosition = null;
ReadableArray totalsRows = null;
ReadableArray columns = source.getArray("header");
ReadableArray footer = source.getArray("footer");
ReadableMap totals = source.getMap("totals");

if(totals != null) {
totalsPosition = totals.getString("position");
totalsLabel = totals.getString("label");
totalsRows = totals.getArray("rows");
tableView.setTotals(totalsRows, totalsPosition, totalsLabel);
}

List<DataColumn> dataColumns = new ArrayList<>();
TableView tableView = (TableView) view;
for(int i = 0; i < columns.size(); i++) {
DataColumn column = new DataColumn(columns.getMap(i));
dataColumns.add(column);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public RowCountView(Context context, TableView tableView) {
FrameLayout.LayoutParams frameLayout = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, TableTheme.rowHeightFactor);
container.setLayoutParams(frameLayout);
container.setZ(PixelUtils.dpToPx(4));
container.setElevation(PixelUtils.dpToPx(4));
container.setY(height - TableTheme.rowHeightFactor);
container.setBackgroundColor(Color.WHITE);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.qliktrialreactnativestraighttable;


import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.res.AssetManager;
Expand All @@ -16,12 +17,13 @@
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.views.text.ReactFontManager;
import com.facebook.react.bridge.ReadableArray;

import java.util.ArrayList;
import java.util.List;

@SuppressLint("ViewConstructor")
public class TableView extends FrameLayout {

public final static int SCROLL_THUMB_HEIGHT = 12;
RootLayout rootLayout;
CustomHorizontalScrollView scrollView;
Expand All @@ -48,6 +50,8 @@ public class TableView extends FrameLayout {
int rowHeight = TableTheme.rowHeightFactor;
int themedRowHeight = TableTheme.rowHeightFactor;
int headerHeight = TableTheme.rowHeightFactor;
List<TotalsCell> totalsCells = null;
String totalsLabel;
final TableViewFactory tableViewFactory;

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
Expand All @@ -62,6 +66,11 @@ public class TableView extends FrameLayout {
tableViewFactory = new TableViewFactory(this, columnWidths, dataProvider, dragBox, firstColumnDragBox);
}

public void setTotals(ReadableArray totalsRows, String totalsPosition, String totalsLabel) {
this.totalsLabel = totalsLabel;
dataProvider.setTotals(totalsRows, totalsLabel, totalsPosition);
}

public void clearSelections() {
hideDragBoxes();
selectionsEngine.clearSelections();
Expand Down
Loading

0 comments on commit de75078

Please sign in to comment.