I have a GXT LiveGridView grid - works great, loading fine, but will not scroll all the way to the bottom record using the scroll bar. The only way to see the last record is to select the last visible record and use the down arrow key to force the display down, one record at a time.
By overriding the 'getCalculatedRowHeight' method, since it was returning a wrong value (compared with the Firebug analysis) the issue was resolved.
private class MyLiveGridView<T> extends LiveGridView<T> {
// deal with wrong value of 22 from this method currently.
#Override
protected int getCalculatedRowHeight(){
return 28;
}
}
(A real fix would be to dynamically acquire the correct row height. For now this will suffice since I'm on the hook for a lot of code still).
Related
On RecyclerView addOnScrollListener the property SCROLL_STATE_IDLE takes time to get called at end of the item size and when scrolled up to the top of the RecyclerView. But it works fine in middle of the scrolling.
The root view of the layout is CoordinatorLayout.
Having the same issue, the only workaround I've found is to send a stopScroll() whenever the RecyclerView gets a SCROLL_STATE_SETTLING, though not the ideal solution. Probably would be better to detect if it has reached the top or bottom edge, taking into account the scrolling direction, and then call stopScroll():
#Override
public void onScrollStateChanged(final int state)
{
super.onScrollStateChanged(state);
if (state == RecyclerView.SCROLL_STATE_SETTLING)
{
this.stopScroll();
}
}
Update
This issue seems to be a bug in the support library, though it was reported as fixed its clear that the problem still exists, so hopefully we should see an adequate solution in the future:
https://issuetracker.google.com/issues/66996774
Invoke stopScroll() when your recyclerview has been reached to to bottom.
I think Since it's support library version up, velocity is calulated and it makes delay a little.
I have a custom MvxTableViewCell that is associated with an MvxStandardTableViewSource. That Source is then applied to a UITableView. The custom table cell is defined without any Storyboard or NIB. It is laid out in code and uses AutoLayout.
this.searchResultsTable = new UITableView();
this.searchResultsTable.AccessibilityIdentifier = "SearchView_SearchResultsTable";
this.searchResultsTable.TranslatesAutoresizingMaskIntoConstraints = false;
this.searchResultsTable.RowHeight = UITableView.AutomaticDimension;
this.searchResultsTable.EstimatedRowHeight = 44.0f;
this.searchResultsTable.RegisterClassForCellReuse(typeof(CustomerItemCell), new NSString("CustomerItemCell"));
this.searchResultsTable.AllowsMultipleSelectionDuringEditing = true;
this.searchResultsTable.TableFooterView = new UIView();
this.searchResultsTableDataSource = new MvxStandardTableViewSource(this.searchResultsTable, new NSString("CustomerItemCell"));
this.searchResultsTable.Source = this.searchResultsTableDataSource;
The MVxStandardTableViewSource is databound to a ViewModel property of type List
var set = this.CreateBindingSet<SearchView, SearchViewModel>();
set.Bind(this.searchResultsTableDataSource).To(vm => vm.SearchResults);
set.Bind(this.searchBar).For(x => x.Text).To(vm => vm.CurrentSearchCriteria);
set.Apply();
This all works fine until an item in the data source causes some text wrapping in one of the UILabels and consequently a different height to the other cells.
The cell height is mostly correctly calculated but the UILabel within the
cell does not get redrawn until the device is rotated. I am using iOS AutoLayout to layout the various UIViews in the Cell.
Here are some examples of the large cell in my layout, see the
person "THISISAPATIENTWITHA-" (note this is test data not real people's data)
Initial display of cells
Same cells but device has been rotated
Still the same cells with device rotated back to original
How do I get the UILabel to redraw? We only need to support iOS8 and above.
I cannot see an event or method that gets called when the data binding has happened that would allow me to effectively tell the custom cell "You now have your subviews populated with bound data so redraw them"
The table has another issue too that is covered by this question, Implementing cell reuse for varying height cells in UITableView
Simple Repro on Github
https://github.com/munkii/TableCellResizeIssue
UPDATE:
I've forked your GitHub project and submitted a pull request. But here's my updates to your project.
https://github.com/SharpMobileCode/TableCellResizeIssue
First, you're using FluentLayout for your constraints. Nothing wrong with that actually, but that's some good info to tell others. :)
Second, in order for UITableView.AutomaticDimension to work on TableView Cells, there must be enough autolayout constraints defined in order for the cell to calculate the height of the cell. UITableView.AutomaticDimension depends on proper AutoLayout constraints.
Since you were using FluentLayout to abstract iOS AutoLayout constraints, this was not obvious as no warnings were present in the application output window. Though FluentLayout was technically correct, it however wasn't enough for UITableView.AutomaticDimension to automatically calculate each cell height.
So what I did was added a few more constraints. Look in CustomerItemCell.CreateView() in the pull request (or my github link). You can see that I added additional constraints for all the bottom labels so that they add a Bottom Constraint to the ContentView (Just like you did with this.bornLabel). This had to be applied to all the labels on the bottom of the cell. This gives AutoLayout enough information to properly calculate the cell height.
Third, This almost works, but if you rotate to Landscape, you'll notice that the long name cells will be bigger and have extra padding. To fix this, I created another class called AutoLayoutLabel that inherits from UILabel. I overrode the Bounds property so that it changes the PreferredMaxLayoutWidth to the proper width when rotated to Landscape, and back to Portrait. You then will need to use AutoLayoutLabel instead of UILabel. You'll need this for all labels that need to wrap. I'm not sure how to set PreferredMaxLayoutWidth to auto in code, but this is how to do it programmatically (which also works for iOS 7).
public class AutoLayoutLabel : UILabel
{
public override CGRect Bounds
{
get
{
return base.Bounds;
}
set
{
base.Bounds = value;
if(this.Lines == 0 && Bounds.Size.Width != PreferredMaxLayoutWidth)
{
PreferredMaxLayoutWidth = Bounds.Size.Width;
SetNeedsUpdateConstraints();
}
}
}
}
Well, that should do it!
I now have a solution to this part of my issue. Prompted by #SharpMobileCode reference to PreferredMaxLayoutWidth I decided to give that another go. Rather that setting it to Automatic (which seems impossible in code) I am setting it Explicitly, once AutoLayout has done its thing. Like this
/// <summary>
/// Lays out subviews.
/// </summary>
public override void LayoutSubviews()
{
base.LayoutSubviews();
this.nameLabel.PreferredMaxLayoutWidth = this.nameLabel.Frame.Size.Width;
}
I am no longer seeing the Labels not wrap (hurrah!) however I am seeing an issue with what looks like cell reuse. Once I scroll all of the cell off the top of the screen I can scroll it back on and it has reverted to the same height as all the other cells. I can see the label is still wrapping but the cell height is wrong.
The standard table views in MvvmCross date back to iOS4 - while the new UITableViewAutomaticDimension sizing wasn't really added until much more recently (iOS8?)
Most real apps tend to use custom cells rather than the standard ones, but if you do want to use the standard ones, then I'd guess you could try adding some code to the setters in the cell which would trigger resize recalculations - e.g. to setters in https://github.com/MvvmCross/MvvmCross/blob/3.5/Cirrious/Cirrious.MvvmCross.Binding.Touch/Views/MvxStandardTableViewCell.cs#L73
I would guess that judiciously placed calls in there to request layout recalc would cause the parent cell and table to redraw.
I am trying to implement a similar effect like the iPhone-alike sliding header in the iPhone contact app (the sliding header that group the contacts by it's starting letter).
This is the screen of my app, and what I want to achieve is the following:
I have a 'guide header' and three 'tabs' for sorting the list. When the user scrolls the list up, I want everything to scroll up (guide header, tabs, list). However, when the tabs reach the top of the screen (and the guide header will just be gone off the screen), I want the tabs to stop and stay there (remain as "sticky header"), and only the list items scroll as in any regular list view.
I have a view group (guide header) above a list view.
First of all, I want to have the guide header adjust it's position depending on the scrolling position of the list view.
First approach:
My idea was to set an onScrollListener to the list view and change the top margin of the guide header to whatever the scroll position of the first item in the list view is (which would be a negative value).
The logic is correct, but the problem I'm facing is that the guide header view doesn't get redrawn fast enough while I'm scrolling in the list view. The guide header view only updates (to my changed top margin value) when the list view fling comes to an end. Even slow scrolling doesn't work. Invalidating (invalidate()) the guide header view or it's parent also doesn't help, since it would just put an invalidation request to the queue, but the invalidation and redrawing doesn't happen immediately, but only when the UI thread becomes idle, which doesn't seem to happen while the user still has his fingers on the scroll list view. Seems that flinging the list view blocks the whole UI thread or keeps it busy for itself.
So the main problem is: changing the margin of the guide header view doesn't become visible immediately while the user is scrolling the list view. The code I'm using it this:
#Override
public void onScroll(final AbsListView view, final int firstVisibleItem,
final int visibleItemCount, final int totalItemCount) {
// Get the first list item and check it's scroll position. This will be the value (top), that we also
// use the scroll the header parallel.
View v = mainList.getChildAt(0);
final int top = (v==null)?0:v.getTop();
// This logs the current scroll position of the first list item element/view group.
Log.d("onScroll", "onScroll: " + top);
// Here we finally change the margin (setting a negative margin) to the header element.
((LinearLayout.LayoutParams)(findViewById(R.id.header_container).getLayoutParams())).setMargins(0, top, 0, 0);
// was just a test: invalidating the outer container/view group, doesn't help
// findViewById(R.id.ll_container).invalidate();
}
I do see the "onScroll:" log output I inserted in the code above in the logcat, but the following adjustment of the top margin just doesn't become visible.
My second approach: is to use a scrollview for the guide header + tabs and work with those. Scrolling the guide header (which is then a scroll view) from code with scrollView.scrollTo(0,Math.abs(Math.abs(top)) from the onScroll method of the list view does work and almost immediately shows on the screen, however, it's not very accurate/stable when the user flings the list view very fast - meaning it jumps in intervals and doesn't look smooth; it's only accurate/stable when scrolling slowly.
My question is now: is there any best practice to accomplish such a sliding header effect, and more concrete: is there a way to force the guide header view to be redrawn while the user is still scrolling the list view (in my first mentioned approach).
For this you should use some tricks (afaik there is no ready-to-use implementation of such a feature).
For instance, you could detect gestures on your view, and
if the current gesture matches a
scroll down, and the first list item
is visible, animate-shrink the
header's size to 0, the tab view's
size to match_parent. Start scrolling
the list only when the header is not
present anymore.
if the current gesture matches scroll
up, and the first is already visible,
animate-expand the header to it's
original size.
So using Animation on the header view might be your solution.
Update
An other workaround would be to extend your List (the value array of your adapter):
Inster a new (dummy) item at the top for the header representation, and modify your ListAdapter's getView method:
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
if (position == 0)
{
convertView = inflater.inflate(R.layout.sliding_header, parent,
false);
return convertView;
}
//TODO: your original method body comes here
}
where the xml referenced by R.layout.sliding_header should contain the header layout of your list.
A custom OnScrollListener implementation applied to the ListView would make unnoticeable that the header actually is an item of the list, since it would hide the scrollbar.
You should add this listener to your listView in the activity's onCreate method:
listView.setOnScrollListener(new MyScrollListener());
where MyScrollListener is:
/**
* Custom OnScrollListener
*/
private final class MyScrollListener implements OnScrollListener
{
#Override
public void onScrollStateChanged(AbsListView view, int scrollState)
{}
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount)
{
if (view.getFirstVisiblePosition() == 0)
view.setVerticalScrollBarEnabled(false);
else if (!view.isVerticalScrollBarEnabled())
view.setVerticalScrollBarEnabled(true);
}
}
I think you can also try and use my ExpandAnimation for that.
http://udinic.wordpress.com/2011/09/03/expanding-listview-items/
Just pass the animation class that "guide header" view, and let the animation do the work for you, no scrolling is needed in that case, and it's smooth.
I need to show the only component on the form - HTMLComponent. Reaching the bottom of the form/component while vertical scrolling scroll bar jumps back to the top of the form. I need to prevent this.
I've tried to turn on/off scrolling on the form and HTMLComponent but anyway if there's a scroll bar - it will return to the top from the bottom. Also I've tried border and box layouts and additional container for HTMLComponent - no use.
Any ideas how to prevent such scrolling issue?
Try this (it works for me - LWUIT 1.5):
htmlComponent.getComponentForm().setCyclicFocus(false);
If you get a NullPointerException, call it after adding to the HtmlComponent to a form.
If you want to get rid of the bottom/top jump scroll, you can use
form.setCyclicFocus(false)
You should stick with border layout and place the HTML component in the center for this particular use case. You can disable form scrolling since the HTML component is indeed scrollable by default:
form.setScrollable(false);
HTMLComponent is itself scrollable
to prevent scrolling
setScrollable(false);
for horizontal scroll off
setScrollableX(false);
hope this will solve your issue
...or, you can paste this code on your Form class
public void keyPressed(int keyCode) {
int tecla = Display.getInstance().getGameAction(keyCode);
if(tecla == 8){
//if hit ENTER or principal key in mobile keyboard
}else if(tecla == 6){//down key
if(this.list_component_name.getSelectedIndex() < this.list_component_name.size() - 1)
this.list_component_name.setSelectedIndex(this.lista_bodegas.getSelectedIndex() + 1);
}else if(tecla == 1){//up key
if(this.list_component_name.getSelectedIndex() > 0)
this.list_component_name.setSelectedIndex(this.list_component_name.getSelectedIndex() - 1);
}
}
That's also work for me
form.serScrollable(false) or form.setCyclicFocus(false) didn't work for me.
I have a form and just a single HTMLComponent in it.
The problem is in HTMLComponent itself and disabling focus of the form won't affect it.
You can try with making the whole component focusable which might help in scrolling in a proper way. Along with this you should add your html component in Boderlayout.center of form and make form scrollable true and cyclic focus false.
In LWUITImplementation we have function getDragPathTime(). This javaDoc about this function:
/**
* Indicates what drag points are valid for the drag speed calculation.
* Points that are older then the current time - the path time are ignored
*
* #return the relevance time per point
*/
I also was problem especially in devices with OS S-60 Nokia. Lists was jumped from buttom to top. i solved this problem by change the return value. I change the value to 600( from 200). this occurs to fewer sampling and prevent the "jump".
According to the documentation, Display.setCurrent doesn't work if the current displayable is an alert. This is a problem as I would like to pop up another alert when the user selects a command. Does anyone know how to work around this so that we can go from one alert to another? I am using CLDC 1.0 and MIDP 2.0.
Additional Information
The spec does allow us to edit an alert while it is on screen, but some Nokia phones don't handle it well at all. So I am now trying to go from the alert to a blank canvas, then back to the alert. Of course I don't want the user to interact with the previous canvas, so it seems that I am forced to create a new blank canvas. As a sidenote, this has the slight disadvantage of looking worse on phones which still have the previous screen when an alert is shown.
The bigger problem is how to transition from the blank canvas back to an alert once the canvas is loaded. Testing on the Motorola emulator revealed that showNotify is not called after returning from an alert to the previous screen. I guess I could create the next alert in the paint method, but this seems like a ugly hack.
OK, so your problem is that you can't set it up to do:
Display.setCurrent(alert1, alert2);
and
Display.setCurrent(alert2);
is also not possible if the current Displayable is already alert1.
So how about put an intermediate Displayable item that is blank and that immediately changes to the next alert? Assuming the current Displayable is alert1, like this in your alert1's command block:
Display.setCurrent(blankForm);
Display.setCurrent(alert2);
That should work assuming you are not using the default 'Dismiss' command. So basically it goes from alert1->(blankForm->alert2).
I couldn't find a way around this, so I just used the paint hack.
public class AlertPage extends Canvas{
MIDlet midlet;
Alert alert;
private AlertPage(MIDlet midlet){
this.midlet=midlet;
}
protected void paint(Graphics arg0){
//Yep, this is a hack, but showNotify doesn't seem to work well for Motorola
if(alert!=null){
Display d=Display.getDisplay(midlet);
d.setCurrent(alert);
alert=null;
}
}
public static void showAlert(MIDlet m, Alert a){
AlertPage page=new AlertPage(m);
Display d=Display.getDisplay(m);
page.alert=a;
d.setCurrent(page);
}
}