Looking for a GWT DataGrid component which implements infinite scroll, BUT also makes sure to discard the results no longer visible on the screen : such as the previously loaded results that are not shown anymore.
This is to avoid a memory hog.
I've been trying to find this on Google, but no luck so far.
Please note : I could take a JS library and adapt it to what I need, but I don't think it would work good with GWT's DataGrid component.
Edit: I am interested specifically in an infinite scroll which ALSO discards/releases the topmost results that are not visible (and loads them up as appropriate).
Any ideas ?
As a matter of fact the showcase example has an infinite scrolling CellList. (you can find the code there).
Although this was done with a CellList the same principles should also apply to a DataGrid.
Check out the ShowMorePagerPanel.java file.
Update:
The onScroll function of ShowMorePagerPanel.java will add the new records at the bottom. However you can easily change the behavior:
Something along the lines (not tested tough):
HasRows display = getDisplay();
if (display == null) {
return;
}
boolean loadData = false;
// If scrolling up, change newStart
int oldScrollPos = lastScrollPos;
lastScrollPos = scrollable.getVerticalScrollPosition();
// get the current visible Range
Range currentRange = display.getVisibleRange();
if (oldScrollPos >= lastScrollPos) {
int newStart = Math.max(
currentRange.getStart() - incrementSize,0);
loadData = true;
}
int maxScrollTop = scrollable.getWidget().getOffsetHeight()
- scrollable.getOffsetHeight();
if (lastScrollPos >= maxScrollTop) {
// We are near the end, so increase the page size.
int newPageSize = Math.min(
display.getVisibleRange().getLength() + incrementSize,
display.getRowCount());
loadData = true;
}
if (loadData) {
display.setVisibleRange(newStart, newPageSize);
}
Related
1) I'm practicing stuff with graphs in order to add that feture to my app, I want the upper labels ( the xAxis base ) to be shown only where entries occur.
I haven't found a suitable solution online yet, and currently it appears on every xAxis from first entry to last entry as in the picture below:
I want it to be without the one sI deleted, as shown in the picture below:
2) and the second question I'm struggling with it is that I want to be able to draw for example in (x=5, y=7) and after it to draw at (x=1, y =3), but it wont let me add an entry with a smaller x that any other entry that already in the graph.
You have to extend from ValueFormatter class.
for more detail take a look at link
You can pick your desired logic to make the label disappear with returning "".
for example:
public String getFormattedValue(float value) {
if ((int)value <= 0) //your logic to evaluate correctness
return ""; // make lable go away
//...
}
UPDATE 2 (in Kotlin):
There is another overload for getFormattedValue which have a AxisBase parameter and you can use mEntryCount or mEntries.
override fun getFormattedValue(value: Float, axis: AxisBase?): String {
if (axis?.mEntryCount!! <= 0)
return ""
}
There I have a loop:
public void updateDrawee(View view) {
if (begin) {
begin = false;
for (int i = 0; i < 5; i++) {
CloseableReference<CloseableImage> reference = createBitmapRefer(i);
Log.i("reference", reference+"");
imgList.add(reference);
}Log.i("imgList", imgList.toString());Log.i("imgList.0", imgList.get(0)+"");
}
//...some code
}
and the method createBitmapRefer(int count) follow:
public CloseableReference<CloseableImage> createBitmapRefer(int count) {
ImagePipeline pipeline = Fresco.getImagePipeline();
int[] drawableIds = {R.drawable.alpha1, R.drawable.alpha2,
R.drawable.alpha3, R.drawable.alpha4, R.drawable.alpha5};
ImageRequest levelRequest
= ImageRequestBuilder.newBuilderWithResourceId(drawableIds[count])//++
.setProgressiveRenderingEnabled(true)//逐行加载
.build();
CloseableReference<CloseableImage> bmpReference = null;
DataSource<CloseableReference<CloseableImage>> dataSource
= pipeline.fetchImageFromBitmapCache(levelRequest, this);
try {
if (!dataSource.hasResult()) {
dataSource = pipeline.fetchDecodedImage(levelRequest, this);
}
//count %= 5;
Log.i("dataSource has result", dataSource.hasResult() +"");
Log.i("dataSource fail?", dataSource.hasFailed() + "");
bmpReference = dataSource.getResult();
Log.i("bmpRefer", bmpReference+"");
if (bmpReference != null) {
CloseableReference<CloseableImage> returnRef;
returnRef = bmpReference.clone();
return returnRef;
}else {
return null;
}
}finally {
dataSource.close();
CloseableReference.closeSafely(bmpReference);
}
}
when I debug, if i click step into and see the code step by step, it will return a CloseableReference just as I want, and the imgList(its a ArrayList) can get the element too.BUT if I step over the for loop, it return nothing!
Is there any different between keep looking at it or not???
the watches show elements in imgList, when index=1 and 4, I clicked step into.
and the logcat show what Log.i() print.
Or because I have not use this classCloseableReference in Standardized way?
Let me try to explain what happens here.
You are not using Fresco in the intended way. I will step back for a moment and strongly suggest that you use SimpleDraweView if you just need to display images. If however you really need the underlying bitmap, you can get it from the ImagePipeline in way similar to what you already doing, but with one key difference. Fetching images happens asynchronously. What that means is that you can't just do dataSource = pipeline.fetchDecodedImage(...) and then immediately dataSource.getResult. If the image was not found in the memory cache, getResult will just return null. What you need to do instead is to subscribe to the DataSource as explained in the Fresco documentation. I strongly suggest that you read those few chapters about ImagePipeline if you intend to use it directly. Otherwise you may cause your app to leak the memory or to crash because of rendering recycled bitmap.
What you see in debugger is exactly what I described above. The array of size 5 looks like this:
0 = null,
1 = CloseableReference#4908,
2 = null,
3 = null,
4 = CloseableReference#5231
The AndroidStudio UI just hides the null entries for brevity. You can turn this off if you don't like it by right-clicking there and opening options. The reason you get something for 1 and 4 is because the image has been found in the bitmap memory cache and was retrieved from it immediately. The reason you get null for 0, 2 and 3 is because the image has not been loaded yet. Fresco might need to download the image, and even if it is already downloaded and in the disk cache, it may need to decode the image. All of this takes some time and is not instantaneous. That's why you need to subscribe your callback and ImagePipeline will notify you when the image is ready.
I have a problem that I have been unable to solve in a way that I am very happy with.
I have a view that I am dragging and dropping into a list. That list is created using a recyclerView. The drag object works fine, and the recyclerView's items can all receive the events no problem. Now I want to make the list scroll as the user drags their finger close to the top or bottom of the list. My first step was to add a dragEvent listener to the recyclerView, and attempt to start scrolling each time I got a location near the top or bottom edge. So, my DragEvent.Location case looks something like this:
case DragEvent.ACTION_DRAG_LOCATION: {
removeDragScrollCallBack();
float y = event.getY();
final int scrollAreaHeight = v.getHeight()/4;
final int delayMills = 16;
int scrollAmount = 0;
if (y > v.getHeight() - scrollAreaHeight) {
scrollAmount = 10;
} else if (y < scrollAreaHeight) {
scrollAmount = -10;
}
if (Math.abs(scrollAmount) > 0) {
final int finalScrollAmount = scrollAmount;
dragScrollRunnable = new Runnable() {
#Override
public void run() {
if (canScrollVertically(finalScrollAmount)) {
scrollBy(0, finalScrollAmount);
if (dragScrollHandler != null && dragScrollRunnable != null) {
dragScrollHandler.postDelayed(this, delayMills);
}
}
}
};
dragScrollRunnable.run();
}
return true;
}
It kinda works. Things scroll in the right direction. It seems to sputter a bit though, and generally not scroll very smoothly. Additionally, the drag and drop drop event sometimes doesn't make it to the children while the recycler view is still scrolling.
So, I went to the google example of doing a similar thing in a using a list view - link. I modified the code they used for their list view and tried to handle my recyclerView in a similar manner. This had even poorer results for me.
I have tried various other alterations of these techniques, and swapped to using the smoothScroll function instead of the standard scroll function, but I'm not too happy with any of the results.
Does anyone have a good solution for how to handle this?
Update: I now believe that many of my problems with this functionality are due to the drag listener being fairly unreliable. At sometimes the recycler fails to get events when it's children are receiving events.
Turns out the drag listener on a view is not terribly reliable. At random times as I moved my finger around the screen, the drag listener wouldn't recieve all of the events. I believe the reason for this was the way that the children of the recyclerView were also recieving the on drag callbacks. The solution was to do what I had tried originally, but through a listener on the fragment itself. Now when I get an event, I check the coordinates to see what view it is in, and then convert it to local coordinates for that view. Then I can determine exactly how I need to handle it.
I made a note card program that can help you study with JavaFX. It saves the class through XML and on boot up, it finds the XML files and adds them to an ArrayList called allProjects of type NoteCardSet, an ArrayList of NoteCards. With this, I made a dynamic amount of buttons that puts them 4 columns wide. Here is the code for that:
int amountPerRow = 4;
int current = 0;
int row = 0;
for (NoteCardSet noteCardSet : allProjects) {
Button b = new Button(noteCardSet.getName());
GridPane.setConstraints(b, current, row);
centerMenu.getChildren().add(b);
b.setOnAction(e -> {
border.setCenter(noteCardSetLayout(noteCardSet));
});
if (current < amountPerRow - 1)
{
current++;
}
else if (current >= amountPerRow - 1)
{
current = 0;
row++;
}
}
Obviously this is creatable in JavaFX but is it possible to created this in FXML?
No you cannot do this in FXML. There is no way to write a LOOP in fxml. If you are just considered about a Button, then you may use SceneBuilder and drag-drop multiple buttons.
Though, if you are considered about a more complex UI and want to repeat them, you can create a separate FXML and include it as many time as you need using <fx:include>.
You can also load the same fxml multiple times using a loop and put all the concerned data inside the initialize(), but this might not be the best solution you are looking for.
I am using GWT 2.5.1. I have a CellTable in which paging is done by SimplePager. I am seeing following issues with the SimplePager.
The number of rows displayed in the last page is incorrect. Let's say there are total 22 rows and the page size is set to 10. So, the third page should show 21-22 of 22. Instead, it shows 13-22 of 22. The last page always shows 10 rows, it takes some from the previous page.
There is no Last page button. There is a fast forward button which is also disabled.
When there is no data, the text says 1-1 of 0.
I know these are known issues as I did a lot of research on this topic. Wanted to know if this is still not fixed in GWT 2.5.1. Any wrappers that are available yet? Any workaround for this bug?
I am writing my custom pager which extends SimplePager as below.
public class MySimplePager extends SimplePager {
public MySimplePager() {
this.setRangeLimited(true);
}
public MySimplePager(TextLocation location, Resources resources, boolean showFastForwardButton, int fastForwardRows, boolean showLastPageButton) {
super(location, resources, showFastForwardButton, fastForwardRows, showLastPageButton);
this.setRangeLimited(true);
}
#Override
public void setPageStart(int index) {
if (this.getDisplay() != null) {
Range range = getDisplay().getVisibleRange();
int pageSize = range.getLength();
if (!isRangeLimited() && getDisplay().isRowCountExact()) {
index = Math.min(index, getDisplay().getRowCount() - pageSize);
}
index = Math.max(0, index);
if (index != range.getStart()) {
getDisplay().setVisibleRange(index, pageSize);
}
}
}
}
I am instantiating the pager as:
SimplePager.Resources resources = GWT.create(SimplePager.Resources.class);
usersPager = new MySimplePager(SimplePager.TextLocation.CENTER, resources, false,10, true);
But, this does not work at all. Strange thing is, the method setPageStart() is not being invoked at any point. I put some log messages in it, but they did not get displayed. Anything I am doing wrong here or missing?
Any help would be greatly appreciated.
Thanks.
I don't face your first 2 problems. Third issue was there in 2.5.1 RC1 release but it has been rectified in the 2.5.1 release.
1) There are hacks to overcome this, but I forgot what is it.
2) Use the following constructor to enable fastforwardbutton and last page button
public SimplePager(TextLocation location, boolean showFastForwardButton,
boolean showLastPageButton)
3) This is fixed in latest release.
For more info check out this.