Skip to content

Commit

Permalink
fix(md-3839): scrollbars and crash (#155)
Browse files Browse the repository at this point in the history
* fix: scrollbars and crash

* fix: address comments
  • Loading branch information
gruskal authored and enell committed Feb 9, 2023
1 parent 902378d commit 87b6902
Show file tree
Hide file tree
Showing 17 changed files with 253 additions and 119 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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);
Expand Down Expand Up @@ -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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -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);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@

@SuppressLint("NotifyDataSetChanged")
public class DataProvider extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public static Set<String> imagePaths = new HashSet<>();
public static Map<String, Bitmap> imageData = new HashMap<>();
private final int NUM_LINES = 1;
private final int FONT_SIZE = 14;
private final int VIEW_TYPE_ITEM = 0;
Expand Down Expand Up @@ -96,59 +94,12 @@ public List<DataColumn> 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<String> 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);
Expand Down Expand Up @@ -254,7 +205,7 @@ public void setRows(List<DataRow> data, boolean resetData) {
}
this.notifyDataSetChanged();
}
fetchImages();
tableView.imageLoader.fetchImages();
setLoading(false);
}
public void setDataColumns(List<DataColumn> cols) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

public class DataRow {
public List<DataCell> cells = new ArrayList<>();
public DataRow(ReadableMap source, List<DataColumn> columns) {
public DataRow(ReadableMap source, List<DataColumn> columns, ImageLoader imageLoader) {
ReadableMapKeySetIterator iterator = source.keySetIterator();
while (iterator.hasNextKey()) {
String key = iterator.nextKey();
Expand All @@ -27,7 +27,7 @@ public DataRow(ReadableMap source, List<DataColumn> 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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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) {
Expand All @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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<String> imagePaths = new HashSet<>();
public Map<String, Bitmap> 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<String> 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();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}

0 comments on commit 87b6902

Please sign in to comment.