diff --git a/android/src/main/java/com/qliktrialreactnativestraighttable/CustomHorizontalScrollView.java b/android/src/main/java/com/qliktrialreactnativestraighttable/CustomHorizontalScrollView.java index ea36986e..f79941e0 100644 --- a/android/src/main/java/com/qliktrialreactnativestraighttable/CustomHorizontalScrollView.java +++ b/android/src/main/java/com/qliktrialreactnativestraighttable/CustomHorizontalScrollView.java @@ -2,13 +2,34 @@ import android.content.Context; import android.view.MotionEvent; +import android.view.View; import android.widget.HorizontalScrollView; +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class CustomHorizontalScrollView extends HorizontalScrollView { + MockHorizontalScrollView horizontalScrollBar; boolean disableIntercept = false; public CustomHorizontalScrollView(Context context) { super(context); + setHorizontalScrollBarEnabled(false); + } + + @Override + protected void onScrollChanged(int l, int t, int oldl, int oldt) { + super.onScrollChanged(l, t, oldl, oldt); + if (horizontalScrollBar != null) { + horizontalScrollBar.setContentWidth(computeHorizontalScrollRange()); + horizontalScrollBar.setScrollX(computeHorizontalScrollOffset()); + } + } + + public void setScrollbar(MockHorizontalScrollView verticalScrollBar){ + this.horizontalScrollBar = verticalScrollBar; } + void setDisableIntercept(boolean value) { disableIntercept = value; } diff --git a/android/src/main/java/com/qliktrialreactnativestraighttable/CustomRecyclerView.java b/android/src/main/java/com/qliktrialreactnativestraighttable/CustomRecyclerView.java index 1d636b15..9c6441a5 100644 --- a/android/src/main/java/com/qliktrialreactnativestraighttable/CustomRecyclerView.java +++ b/android/src/main/java/com/qliktrialreactnativestraighttable/CustomRecyclerView.java @@ -26,6 +26,7 @@ public class CustomRecyclerView extends RecyclerView { public boolean firstColumnOnly; public boolean active = false; public CustomRecyclerView scrollCoupledView = null; + public MockVerticalScrollView verticalScrollBar = null; Paint paint = new Paint(); public CustomRecyclerView(Context context, boolean onlyFirstColumn, DataProvider dp, TableView tv, LinearLayoutManager ll, DragBox db, DragBox firstColumnDb) { @@ -47,14 +48,16 @@ public CustomRecyclerView(Context context, boolean onlyFirstColumn, DataProvider if (onlyFirstColumn) { return; } - this.setVerticalScrollBarEnabled(true); - this.setScrollbarFadingEnabled(true); - this.setVerticalScrollbarThumbDrawable(new ScrollBarDrawable()); + this.setVerticalScrollBarEnabled(false); dragBox.setScrollListener(this); firstColumnDb.setScrollListener(this); } + public void setScrollbar(MockVerticalScrollView verticalScrollBar){ + this.verticalScrollBar = verticalScrollBar; + } + @Override public void onDraw(Canvas c) { super.onDraw(c); @@ -102,6 +105,10 @@ public void onScrolled(@NonNull RecyclerView rv, int dx, int dy) { if (active && scrollCoupledView != null) { scrollCoupledView.scrollBy(dx, dy); } + if (verticalScrollBar != null) { + verticalScrollBar.setContentHeight(rv.computeVerticalScrollRange()); + verticalScrollBar.setScrollY(rv.computeVerticalScrollOffset()); + } if (linearLayoutManager.findLastCompletelyVisibleItemPosition() >= dataProvider.getItemCount() - 50 && !dataProvider.isLoading() diff --git a/android/src/main/java/com/qliktrialreactnativestraighttable/DataCell.java b/android/src/main/java/com/qliktrialreactnativestraighttable/DataCell.java index ea632766..0f5aaaa6 100644 --- a/android/src/main/java/com/qliktrialreactnativestraighttable/DataCell.java +++ b/android/src/main/java/com/qliktrialreactnativestraighttable/DataCell.java @@ -36,7 +36,7 @@ public class DataCell { boolean cellForegroundColorValid = false; boolean cellBackgroundColorValid = false; qValues qAttrExpValues; - public DataCell(ReadableMap source, DataColumn column) { + public DataCell(ReadableMap source, DataColumn column, ImageLoader imageLoader) { type = column.representation.type; qText = source.getString("qText"); qElemNumber = source.getInt("qElemNumber"); @@ -68,7 +68,7 @@ public DataCell(ReadableMap source, DataColumn column) { String url = qAttrExpValues.get(urlId).qText; if (URLUtil.isValidUrl(url)) { imageUrl = url; - DataProvider.addImagePath(imageUrl); + imageLoader.addImagePath(imageUrl); } } } diff --git a/android/src/main/java/com/qliktrialreactnativestraighttable/DataProvider.java b/android/src/main/java/com/qliktrialreactnativestraighttable/DataProvider.java index f2733c81..791a7249 100644 --- a/android/src/main/java/com/qliktrialreactnativestraighttable/DataProvider.java +++ b/android/src/main/java/com/qliktrialreactnativestraighttable/DataProvider.java @@ -33,8 +33,6 @@ @SuppressLint("NotifyDataSetChanged") public class DataProvider extends RecyclerView.Adapter { - public static Set imagePaths = new HashSet<>(); - public static Map imageData = new HashMap<>(); private final int NUM_LINES = 1; private final int FONT_SIZE = 14; private final int VIEW_TYPE_ITEM = 0; @@ -96,59 +94,12 @@ public List getDataColumns() { return dataColumns; } - public static Bitmap getImageData(String url) { - return imageData.get(url); - } - public static void addImagePath(String imageUrl) { - if(!URLUtil.isValidUrl(imageUrl)) { - return; - } - imagePaths.add(imageUrl); + public boolean isInitialized() { + return dataColumns != null && rows != null; } - public static void fetchImages() { - final CountDownLatch latch = new CountDownLatch(imagePaths.size()); - Iterator iterator = imagePaths.iterator(); - while (iterator.hasNext()) { - String imageUrl = iterator.next(); - boolean isDuplicateImageUrl = imageData.containsKey(imageUrl); - if(isDuplicateImageUrl || !URLUtil.isValidUrl(imageUrl)) { - latch.countDown(); - continue; - } - imageData.put(imageUrl, null); - try { - HttpUtils.get(imageUrl, new Callback() { - public void onResponse(Call call, Response response) { - InputStream inputStream = response.body().byteStream(); - Bitmap bitmap = PixelUtils.byteStreamToBitmap(inputStream); - imageData.replace(imageUrl, bitmap); - latch.countDown(); - } - - public void onFailure(Call call, IOException e) { - latch.countDown(); - } - }); - } catch(Exception e) { - latch.countDown(); - imageData.remove(imageUrl); - e.printStackTrace(); - } - } - try { - latch.await(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - public boolean isInitialized() { - return dataColumns != null && rows != null; - } - - public class ProgressHolder extends RecyclerView.ViewHolder { + public class ProgressHolder extends RecyclerView.ViewHolder { private final RelativeLayout row; public ProgressHolder(View view) { super(view); @@ -254,7 +205,7 @@ public void setRows(List data, boolean resetData) { } this.notifyDataSetChanged(); } - fetchImages(); + tableView.imageLoader.fetchImages(); setLoading(false); } public void setDataColumns(List cols) { diff --git a/android/src/main/java/com/qliktrialreactnativestraighttable/DataRow.java b/android/src/main/java/com/qliktrialreactnativestraighttable/DataRow.java index 16423506..a6ace49c 100644 --- a/android/src/main/java/com/qliktrialreactnativestraighttable/DataRow.java +++ b/android/src/main/java/com/qliktrialreactnativestraighttable/DataRow.java @@ -13,7 +13,7 @@ public class DataRow { public List cells = new ArrayList<>(); - public DataRow(ReadableMap source, List columns) { + public DataRow(ReadableMap source, List columns, ImageLoader imageLoader) { ReadableMapKeySetIterator iterator = source.keySetIterator(); while (iterator.hasNextKey()) { String key = iterator.nextKey(); @@ -27,7 +27,7 @@ public DataRow(ReadableMap source, List columns) { if(column == null) { continue; } - cells.add(new DataCell(cellItem, column)); + cells.add(new DataCell(cellItem, column, imageLoader)); } } Collections.sort(cells, (a, b) -> a.rawColIdx - b.rawColIdx); diff --git a/android/src/main/java/com/qliktrialreactnativestraighttable/GrabberView.java b/android/src/main/java/com/qliktrialreactnativestraighttable/GrabberView.java index 53a37f98..bdf1a3ac 100644 --- a/android/src/main/java/com/qliktrialreactnativestraighttable/GrabberView.java +++ b/android/src/main/java/com/qliktrialreactnativestraighttable/GrabberView.java @@ -66,6 +66,7 @@ public boolean onTouch(View view, MotionEvent motionEvent) { GrabberView.this.updateHeader(motionDx); GrabberView.this.updateFixedTotalsCell(motionDx); GrabberView.this.updateFirstColumnHeader(motionDx); + GrabberView.this.tableView.tableViewFactory.updateScrollbarBounds(); lastX = motionEvent.getRawX(); if(isLastColumn && motionDx > 0) { GrabberView.this.rootLayout.requestLayout(); @@ -112,11 +113,11 @@ public GrabberView(int column, Context context, CustomHorizontalScrollView scrol this.tableView = tableView; grabberButton = new GrabberButton(this); grabberButton.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, tableView.headerHeight)); - this.addView(grabberButton); grabberButton.setBackgroundColor(Color.TRANSPARENT); grabberButton.setOnTouchListener(new TouchListener()); linePaint.setColor(TableTheme.borderBackgroundColor); linePaint.setStrokeWidth(PixelUtils.dpToPx(1)); + this.addView(grabberButton); } public void setHeaderHeight(int height) { @@ -140,7 +141,7 @@ protected void onDraw(Canvas canvas) { int width = getWidth() / 2; int top = 0; int height = getHeight() - top; - canvas.drawLine(width, top, width, height - TableTheme.DefaultRowHeight, linePaint); + canvas.drawLine(width, top, width, height, linePaint); } public void setFirstColumnHeader(HeaderCell cell) { diff --git a/android/src/main/java/com/qliktrialreactnativestraighttable/HeaderViewFactory.java b/android/src/main/java/com/qliktrialreactnativestraighttable/HeaderViewFactory.java index cc72dfc8..5bd2e29b 100644 --- a/android/src/main/java/com/qliktrialreactnativestraighttable/HeaderViewFactory.java +++ b/android/src/main/java/com/qliktrialreactnativestraighttable/HeaderViewFactory.java @@ -121,7 +121,7 @@ public static TotalsViewCell buildFixedTotalsCell(TableView tableView, DataColum } public static HeaderCell createHeaderCell(Context context, DataColumn column, HeaderContentStyle headerContentStyle, TableView tableView) { - int padding = (int) PixelUtils.dpToPx(16); + int padding = CellView.PADDING_X_2; HeaderCell headerCell = new HeaderCell(context, column, tableView); headerCell.setPadding(padding, 0, 0, 0); TextView text = headerCell.cell; @@ -173,9 +173,6 @@ private void buildTotals(Context context) { totalsView.setBackgroundColor(Color.WHITE); FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, tableView.totalsHeight); layoutParams.topMargin = headerHeight; - if(!topPosition) { - layoutParams.bottomMargin = TableTheme.DefaultRowHeight; - } layoutParams.gravity = topPosition ? Gravity.TOP : Gravity.BOTTOM; totalsView.setLayoutParams(layoutParams); if(!topPosition) { diff --git a/android/src/main/java/com/qliktrialreactnativestraighttable/ImageLoader.java b/android/src/main/java/com/qliktrialreactnativestraighttable/ImageLoader.java new file mode 100644 index 00000000..ed3c7178 --- /dev/null +++ b/android/src/main/java/com/qliktrialreactnativestraighttable/ImageLoader.java @@ -0,0 +1,69 @@ +package com.qliktrialreactnativestraighttable; + +import android.graphics.Bitmap; +import android.webkit.URLUtil; + +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.CountDownLatch; + +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.Response; + +public class ImageLoader { + public Set imagePaths = new HashSet<>(); + public Map imageData = new HashMap<>(); + public Bitmap getImageData(String url) { + return imageData.get(url); + } + + public void addImagePath(String imageUrl) { + if(!URLUtil.isValidUrl(imageUrl)) { + return; + } + imagePaths.add(imageUrl); + } + + public void fetchImages() { + final CountDownLatch latch = new CountDownLatch(imagePaths.size()); + Iterator iterator = imagePaths.iterator(); + while (iterator.hasNext()) { + String imageUrl = iterator.next(); + boolean isDuplicateImageUrl = imageData.containsKey(imageUrl); + if(isDuplicateImageUrl || !URLUtil.isValidUrl(imageUrl)) { + latch.countDown(); + continue; + } + imageData.put(imageUrl, null); + try { + HttpUtils.get(imageUrl, new Callback() { + public void onResponse(Call call, Response response) { + InputStream inputStream = response.body().byteStream(); + Bitmap bitmap = PixelUtils.byteStreamToBitmap(inputStream); + imageData.replace(imageUrl, bitmap); + latch.countDown(); + } + + public void onFailure(Call call, IOException e) { + latch.countDown(); + } + }); + } catch(Exception e) { + latch.countDown(); + imageData.remove(imageUrl); + e.printStackTrace(); + } + } + try { + latch.await(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } +} diff --git a/android/src/main/java/com/qliktrialreactnativestraighttable/MiniChartViewManager.java b/android/src/main/java/com/qliktrialreactnativestraighttable/MiniChartViewManager.java index cdb10d02..9c388a8b 100644 --- a/android/src/main/java/com/qliktrialreactnativestraighttable/MiniChartViewManager.java +++ b/android/src/main/java/com/qliktrialreactnativestraighttable/MiniChartViewManager.java @@ -60,7 +60,7 @@ public void setCell(View view, ReadableMap cell) { public void setupMiniChart(MiniChartView miniChartView) { DataColumn dataColumn = new DataColumn(column, 0); - DataCell dataCell = new DataCell(cell, dataColumn); + DataCell dataCell = new DataCell(cell, dataColumn, null); miniChartView.setData(dataCell, dataColumn); } diff --git a/android/src/main/java/com/qliktrialreactnativestraighttable/MockHorizontalScrollView.java b/android/src/main/java/com/qliktrialreactnativestraighttable/MockHorizontalScrollView.java new file mode 100644 index 00000000..00a0e4f2 --- /dev/null +++ b/android/src/main/java/com/qliktrialreactnativestraighttable/MockHorizontalScrollView.java @@ -0,0 +1,29 @@ +package com.qliktrialreactnativestraighttable; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Color; +import android.view.View; +import android.widget.HorizontalScrollView; +import android.widget.ScrollView; + +@SuppressLint("ViewConstructor") +public class MockHorizontalScrollView extends HorizontalScrollView { + View content; + + public MockHorizontalScrollView(Context context, TableView tableView) { + super(context); + setHorizontalScrollBarEnabled(true); + setZ(PixelUtils.dpToPx(4)); + + content = new View(context); + content.setBackgroundColor(Color.TRANSPARENT); + content.setMinimumWidth(tableView.totalWidth); + content.setMinimumHeight((int) PixelUtils.dpToPx(6)); + addView(content); + } + + public void setContentWidth(int width){ + content.setMinimumWidth(width); + } +} diff --git a/android/src/main/java/com/qliktrialreactnativestraighttable/MockVerticalScrollView.java b/android/src/main/java/com/qliktrialreactnativestraighttable/MockVerticalScrollView.java new file mode 100644 index 00000000..69ec7470 --- /dev/null +++ b/android/src/main/java/com/qliktrialreactnativestraighttable/MockVerticalScrollView.java @@ -0,0 +1,29 @@ +package com.qliktrialreactnativestraighttable; + +import android.content.Context; +import android.graphics.Color; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.ScrollView; + +public class MockVerticalScrollView extends ScrollView { + View content; + + public MockVerticalScrollView(Context context, TableView tableView) { + super(context); + setVerticalScrollBarEnabled(true); + setZ(PixelUtils.dpToPx(4)); + + content = new View(context); + content.setBackgroundColor(Color.TRANSPARENT); + int total = tableView.dataProvider.dataSize.qcy; + content.setMinimumHeight(total * tableView.rowHeight); + addView(content); + } + + public void setContentHeight(int height){ + content.setMinimumHeight(height); + } +} diff --git a/android/src/main/java/com/qliktrialreactnativestraighttable/ReactNativeStraightTableViewManager.java b/android/src/main/java/com/qliktrialreactnativestraighttable/ReactNativeStraightTableViewManager.java index 4bbcc206..3ed34320 100644 --- a/android/src/main/java/com/qliktrialreactnativestraighttable/ReactNativeStraightTableViewManager.java +++ b/android/src/main/java/com/qliktrialreactnativestraighttable/ReactNativeStraightTableViewManager.java @@ -29,9 +29,6 @@ import java.util.concurrent.CountDownLatch; public class ReactNativeStraightTableViewManager extends SimpleViewManager { - ReadableMap cols; - ReadableMap rows; - DataSize dataSize; public static final String REACT_CLASS = "ReactNativeStraightTableView"; @Override @@ -47,21 +44,17 @@ public View createViewInstance(ThemedReactContext reactContext) { return new TableView(reactContext); } - private boolean isAllFetched() { - return cols != null && rows != null; - } - - private void processRows(TableView tableView, List dataColumns) { + private void processRows(TableView tableView, ReadableMap rows) { ReadableArray dataRows = rows.getArray("rows"); if(dataRows != null) { boolean resetData = rows.getBoolean("reset"); - RowFactory factory = new RowFactory(dataRows, dataColumns); + RowFactory factory = new RowFactory(dataRows, tableView.getColumns(), tableView.imageLoader); List transformedRows = factory.getRows(); tableView.setRows(transformedRows, resetData); } } - private List processColumns(TableView tableView) { + private List processColumns(TableView tableView, ReadableMap cols) { String totalsLabel = null, totalsPosition = null; ReadableArray totalsRows = null; @@ -86,16 +79,6 @@ private List processColumns(TableView tableView) { return dataColumns; } - private void initializeWhenReady(TableView tableView) { - if(!isAllFetched()) { - return; - } - - List dataColumns = processColumns(tableView); - processRows(tableView, dataColumns); - tableView.setDataColumns(dataColumns); - } - @ReactProp(name = "theme") public void setTheme(View view, ReadableMap theme) { @@ -118,42 +101,35 @@ public void setFreezeFirstColumn(View view, Boolean isFreezeFirstColumn) { @ReactProp(name = "cols") public void setCols(View view, @Nullable ReadableMap source) { - if(source != null) { - cols = source; - TableView tableView = (TableView) (view); - initializeWhenReady(tableView); + if(source == null) { + return; } + TableView tableView = (TableView) (view); + List dataColumns = processColumns(tableView, source); + tableView.setDataColumns(dataColumns); } @ReactProp(name = "isDataView") public void setDataView(View view, boolean isDataView) { TableView tableView = (TableView) (view); tableView.setDataView(isDataView); - - initializeWhenReady(tableView); } @ReactProp(name = "rows") public void setRows(View view, @Nullable ReadableMap source) { - if(source != null) { - TableView tableView = (TableView) (view); - rows = source; - boolean resetData = rows.getBoolean("reset"); - - if (resetData) { - initializeWhenReady(tableView); - return; - } - - processRows(tableView, tableView.getColumns()); + if(source == null) { + return; } + + TableView tableView = (TableView) (view); + processRows(tableView, source); } @ReactProp(name = "size") public void setSize(View view, @Nullable ReadableMap source) { if(source != null) { TableView tableView = (TableView) view; - dataSize = new DataSize(source); + DataSize dataSize = new DataSize(source); tableView.setDataSize(dataSize); } } diff --git a/android/src/main/java/com/qliktrialreactnativestraighttable/RowCountView.java b/android/src/main/java/com/qliktrialreactnativestraighttable/RowCountView.java index 2ab2aefc..d0873592 100644 --- a/android/src/main/java/com/qliktrialreactnativestraighttable/RowCountView.java +++ b/android/src/main/java/com/qliktrialreactnativestraighttable/RowCountView.java @@ -23,6 +23,7 @@ public RowCountView(Context context, TableView tableView) { super(context); int height = tableView.getMeasuredHeight(); int width = tableView.getMeasuredWidth(); + setElevation(PixelUtils.dpToPx(4)); this.tableView = tableView; @@ -39,8 +40,6 @@ public RowCountView(Context context, TableView tableView) { container.setGravity(Gravity.RIGHT); FrameLayout.LayoutParams frameLayout = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, TableTheme.DefaultRowHeight); container.setLayoutParams(frameLayout); - container.setZ(PixelUtils.dpToPx(4)); - container.setElevation(PixelUtils.dpToPx(4)); container.setY(height - TableTheme.DefaultRowHeight); container.setBackgroundColor(Color.WHITE); diff --git a/android/src/main/java/com/qliktrialreactnativestraighttable/RowFactory.java b/android/src/main/java/com/qliktrialreactnativestraighttable/RowFactory.java index feeba40e..fc044c67 100644 --- a/android/src/main/java/com/qliktrialreactnativestraighttable/RowFactory.java +++ b/android/src/main/java/com/qliktrialreactnativestraighttable/RowFactory.java @@ -13,10 +13,10 @@ public class RowFactory { List rows = new ArrayList<>(); - public RowFactory(ReadableArray source, List columns) { + public RowFactory(ReadableArray source, List columns, ImageLoader imageLoader) { for(int i = 0; i < source.size(); i++ ) { ReadableMap map = source.getMap(i); - DataRow row = new DataRow(map, columns); + DataRow row = new DataRow(map, columns, imageLoader); rows.add(row); } } diff --git a/android/src/main/java/com/qliktrialreactnativestraighttable/RowViewHolder.java b/android/src/main/java/com/qliktrialreactnativestraighttable/RowViewHolder.java index 6a945648..a308eff9 100644 --- a/android/src/main/java/com/qliktrialreactnativestraighttable/RowViewHolder.java +++ b/android/src/main/java/com/qliktrialreactnativestraighttable/RowViewHolder.java @@ -44,7 +44,10 @@ public void setData(DataRow dataRow, int rowHeight, CellContentStyle cellContent if(extraCells > 0) { row.removeViews(numCells - extraCells, extraCells); } - for(int i = 0; i < numColumns; i++) { + if(dataRow.cells.size() < numColumns) { + return; + } + for(int i = 0; i < numColumns; i++) { DataCell cell = dataRow.cells.get(i); DataColumn column = DataProvider.getDataColumnByIdx(cell.colIdx, dataProvider.dataColumns); int columnIndex = cell.rawColIdx; @@ -62,7 +65,7 @@ public void setData(DataRow dataRow, int rowHeight, CellContentStyle cellContent cellView.convertCellContentType("image", column); cellView.setData(cell, dataRow, column); - Bitmap imageBitmap = DataProvider.getImageData(cell.imageUrl); + Bitmap imageBitmap = dataProvider.tableView.imageLoader.getImageData(cell.imageUrl); if(imageBitmap == null) { continue; } diff --git a/android/src/main/java/com/qliktrialreactnativestraighttable/TableView.java b/android/src/main/java/com/qliktrialreactnativestraighttable/TableView.java index 27148f50..e6e19f0b 100644 --- a/android/src/main/java/com/qliktrialreactnativestraighttable/TableView.java +++ b/android/src/main/java/com/qliktrialreactnativestraighttable/TableView.java @@ -36,6 +36,7 @@ public class TableView extends FrameLayout { String totalsLabel = null; RootLayout rootLayout; CustomHorizontalScrollView scrollView; + MockVerticalScrollView verticalScrollBar; final DragBox dragBox; DragBox firstColumnDragBox = null; HeaderView headerView = null; @@ -52,6 +53,7 @@ public class TableView extends FrameLayout { DragBoxEventHandler dragBoxEventHandler = new DragBoxEventHandler(this); HeaderContentStyle headerContentStyle; CellContentStyle cellContentStyle; + ImageLoader imageLoader; List grabbers = null; int rowHeight = 0; int headerHeight = 0; @@ -67,6 +69,7 @@ public class TableView extends FrameLayout { firstColumnDragBox = new DragBox(context, this, dragBoxEventHandler, true); dragBoxEventHandler.setDragBoxes(dragBox, firstColumnDragBox); tableViewFactory = new TableViewFactory(this, columnWidths, dataProvider, dragBox, firstColumnDragBox); + imageLoader = new ImageLoader(); } public boolean isInitialized() { @@ -305,8 +308,12 @@ void createRecyclerView() { headerView = tableViewFactory.headerView; rootLayout = tableViewFactory.rootLayout; scrollView = tableViewFactory.scrollView; + verticalScrollBar = tableViewFactory.verticalScrollBar; screenGuideView = tableViewFactory.screenGuideView; firstColumnView = tableViewFactory.firstColumnRecyclerView; + post(() -> { + tableViewFactory.updateScrollbarBounds(); + }); } void invalidateLayout() { diff --git a/android/src/main/java/com/qliktrialreactnativestraighttable/TableViewFactory.java b/android/src/main/java/com/qliktrialreactnativestraighttable/TableViewFactory.java index 96b6bf53..85275110 100644 --- a/android/src/main/java/com/qliktrialreactnativestraighttable/TableViewFactory.java +++ b/android/src/main/java/com/qliktrialreactnativestraighttable/TableViewFactory.java @@ -23,6 +23,8 @@ public class TableViewFactory { public int extraTopMargin = 0; public HeaderViewFactory headerViewFactory = null; public CustomHorizontalScrollView scrollView = null; + public MockVerticalScrollView verticalScrollBar = null; + public MockHorizontalScrollView horizontalScrollView = null; public RootLayout rootLayout = null; public HeaderView headerView = null; public RowCountView rowCountView = null; @@ -60,9 +62,12 @@ public void createAll() { updateRowHeights(); createHeaderFactory(); createScrollView(); + createMockScrollBar(); tableView.addView(scrollView); scrollView.addView(rootLayout); + tableView.addView(verticalScrollBar); + tableView.addView(horizontalScrollView); if(tableView.headerContentStyle.wrap) { if(totalsView != null) { @@ -87,6 +92,26 @@ public void run() { }); } + private void setMockScrollLayouts() { + FrameLayout.LayoutParams verticalFrameLayout = new FrameLayout.LayoutParams((int) PixelUtils.dpToPx(5), FrameLayout.LayoutParams.MATCH_PARENT); + verticalFrameLayout.gravity = Gravity.RIGHT; + int headerHeight = headerView.getMeasuredHeight() > 0 ? headerView.getMeasuredHeight() : tableView.headerHeight; + verticalFrameLayout.topMargin = headerHeight + extraTopMargin; + verticalFrameLayout.bottomMargin = TableTheme.DefaultRowHeight; + verticalScrollBar.setLayoutParams(verticalFrameLayout); + + FrameLayout.LayoutParams horizontalFrameLayout = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, (int) PixelUtils.dpToPx(5)); + horizontalFrameLayout.gravity = Gravity.BOTTOM; + horizontalFrameLayout.bottomMargin = TableTheme.DefaultRowHeight; + horizontalScrollView.setLayoutParams(horizontalFrameLayout); + } + + protected void updateScrollbarBounds() { + setMockScrollLayouts(); + this.verticalScrollBar.requestLayout(); + this.horizontalScrollView.requestLayout(); + } + protected void updateRowHeights() { tableView.cellContentStyle.themedRowHeight = (tableView.cellContentStyle.getLineHeight() * tableView.cellContentStyle.lineCount) + CellView.PADDING_X_2; tableView.rowHeight = tableView.cellContentStyle.themedRowHeight; @@ -94,9 +119,19 @@ protected void updateRowHeights() { tableView.totalsHeight = tableView.cellContentStyle.getLineHeight() + CellView.PADDING_X_2; } + protected void createMockScrollBar() { + verticalScrollBar = new MockVerticalScrollView(context, tableView); + horizontalScrollView = new MockHorizontalScrollView(context, tableView); + + scrollView.setScrollbar(horizontalScrollView); + coupledRecyclerView.setScrollbar(verticalScrollBar); + } + protected void createScrollView() { this.scrollView = new CustomHorizontalScrollView(context); - this.scrollView.setLayoutParams(new ScrollView.LayoutParams(ScrollView.LayoutParams.MATCH_PARENT, ScrollView.LayoutParams.MATCH_PARENT)); + ScrollView.LayoutParams scrollLayoutParams = new ScrollView.LayoutParams(ScrollView.LayoutParams.MATCH_PARENT, ScrollView.LayoutParams.MATCH_PARENT); + scrollLayoutParams.bottomMargin = TableTheme.DefaultRowHeight; + this.scrollView.setLayoutParams(scrollLayoutParams); this.scrollView.setFillViewport(true); createRootLayout(); @@ -141,20 +176,19 @@ protected void createRecyclerViews() { int headerHeight = tableView.headerHeight; int marginTop = headerHeight + extraTopMargin; - int marginBottom = TableTheme.DefaultRowHeight; linearLayout.recyclerView = coupledRecyclerView; coupledRecyclerView.setAdapter(dataProvider); recyclerViewLayoutParams.topMargin = marginTop; - recyclerViewLayoutParams.bottomMargin = marginBottom; rootLayout.addView(coupledRecyclerView, recyclerViewLayoutParams); firstColumnLinearLayout.recyclerView = firstColumnRecyclerView; firstColumnRecyclerView.setAdapter(dataProvider); FrameLayout.LayoutParams firstColumnViewLayoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT); firstColumnViewLayoutParams.topMargin = marginTop; - firstColumnViewLayoutParams.bottomMargin = marginBottom; + firstColumnViewLayoutParams.bottomMargin = TableTheme.DefaultRowHeight; + firstColumnRecyclerView.setLayoutParams(firstColumnViewLayoutParams); if(tableView.isFirstColumnFrozen) { firstColumnHeaderCell = HeaderViewFactory.buildFixedColumnCell(rootLayout, dataColumns.get(0), tableView, headerViewFactory.topPosition); @@ -166,7 +200,7 @@ protected void createRecyclerViews() { firstColumnTotalsCell = HeaderViewFactory.buildFixedTotalsCell(tableView, dataColumns.get(0), totalsCells.get(0), headerViewFactory.topPosition); tableView.addView(firstColumnTotalsCell); } - tableView.addView(firstColumnRecyclerView, firstColumnViewLayoutParams); + tableView.addView(firstColumnRecyclerView); tableView.addView(firstColumnHeaderCell); tableView.addView(firstColumnDragBox); } @@ -196,15 +230,15 @@ protected void createGrabbers() { startOffset += (dataColumns.get(i).width) - offset; offset = 0; - grabberView.setLayoutParams(layoutParams); grabberView.setBackgroundColor(Color.TRANSPARENT); grabberView.setTranslationX(startOffset); grabbers.add(grabberView); if (tableView.isFirstColumnFrozen && i == 0) { - tableView.addView(grabberView); + layoutParams.bottomMargin = TableTheme.DefaultRowHeight; + tableView.addView(grabberView, layoutParams); grabberView.setElevation(PixelUtils.dpToPx(19)); } else { - rootLayout.addView(grabberView); + rootLayout.addView(grabberView, layoutParams); } } } @@ -251,6 +285,15 @@ protected void setupGrabbers() { void invalidateLayout() { if (this.coupledRecyclerView != null) { int width = dataColumns.get(0).width; + int marginTop = tableView.headerHeight + extraTopMargin; + + FrameLayout.LayoutParams recyclerViewLayoutParams = (FrameLayout.LayoutParams) coupledRecyclerView.getLayoutParams(); + recyclerViewLayoutParams.topMargin = marginTop; + coupledRecyclerView.setLayoutParams(recyclerViewLayoutParams); + + FrameLayout.LayoutParams firstColumnRecyclerViewLayoutParams = (FrameLayout.LayoutParams) firstColumnRecyclerView.getLayoutParams(); + firstColumnRecyclerViewLayoutParams.topMargin = marginTop; + firstColumnRecyclerView.setLayoutParams(firstColumnRecyclerViewLayoutParams); if (this.firstColumnHeaderCell != null) { ViewGroup.LayoutParams params = firstColumnHeaderCell.getLayoutParams(); @@ -272,6 +315,8 @@ void invalidateLayout() { this.headerView.updateLayout(); this.headerView.requestLayout(); + updateScrollbarBounds(); + this.dataProvider.invalidateLayout(); if (this.firstColumnRecyclerView != null) { this.firstColumnRecyclerView.requestLayout();