I've subclassed HorizontalScrollView so that I can have some custom scrolling behavior, but have found that smoothScrollTo doesn't always fire.
I've had to work around this problem by using the following code:
smoothScrollTo(x, y);
scrollTo(x, y);
This makes sure the scrolling actually gets done even if smoothScrollTo doesn't work, since scrollTo works every time. Why is this happening? How can I get smoothScrollTo to work every time?
try this:
mScrollView.post(new Runnable() {
#Override
public void run() {
mScrollView.smoothScrollTo(x, y);
}
});
Following code will work:
final int scrollposition = Math.round(hr/24.0f * 1440f);
final ScrollView sv = (ScrollView)findViewById(R.id.graphScrollView);
//sv.smoothScrollTo(0, scrollposition);
sv.post(new Runnable() {
#Override
public void run() {
sv.smoothScrollTo(0, scrollposition);
}
});
Reason:
It will wait for the scrollview to be posted before running the underlying code.
Related
I have multiple views in my layout inside a ScrollView and there is a validation on certain items, in case of any error I scroll to that view using the following:
view.post(new Runnable() {
#Override
public void run() {
view.scrollTo(0, view.getBottom());
view.getParent().requestChildFocus(view, view);
}
});
But the problem here is as soon as this code runs the scroll is achieved but the view passed to this makes itself invisible. After removing this everything is working fine.
I think this is some sort of bug with scrollview.
Your view is inside scrollView and you have added scrollTo() method in your view not in scrollView. Replace view.scrollTo(0,view.getBottom()) to scrollview.scrollTo(0, view.getBottom()).
Try below solution this might work for you.
view.post(new Runnable() {
#Override
public void run() {
scrollview.scrollTo(0, view.getBottom());
view.getParent().requestChildFocus(view, view);
}
});
In my app, I have a ScrollView that listens to Scroll Changes, thanks to the ViewTreeObserver class.
scrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
#Override
public void onScrollChanged() {
// I want to directly target this scrollview changes
// if specific scrollview { do calculations }
}
});
However, that class listens to global scroll changes, and I have 3 ScrollViews. So, the main ScrollView is activated and performs the calculations and causes everything to go awry.
Is there a way to ignore other ScrollViews and only target the main one?
What you can do to overcome it is store the getScrollX() values (if horizontal scrollview) or the getScrollY() values (if vertical scrollview) in some int and every time an onScrollChanged() is fired, just check if the new scroll Values are different from the ones previously stored.
If they're different, the correct scrollview is being called. If they are the same, the wrong scrollview is being called and therefore ignore it.
int prevScrollX_for1 = -1;
int prevScrollX_for2 = -1;
scrollView1.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
#Override
public void onScrollChanged() {
// Assuming horizontal scrollview
if(scrollView1.getScrollX() != prevScrollX_for1)
{
// Do something
}
prevScrollX_for1 = getScrollX();
}
});
scrollView2.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
#Override
public void onScrollChanged() {
// Assuming horizontal scrollview
if(scrollView2.getScrollX() != prevScrollX_for2)
{
// Do something
}
prevScrollX_for2 = getScrollX();
}
});
Is there anyway I can make a Scrollview start on bottom? I tried to:
post(new Runnable() {
#Override
public void run() {
fullScroll(ScrollView.FOCUS_DOWN);
}
});
And also setting the android:focusableInTouchMode="true" on the lowest element in the layout.
But I can see it scrolling to the bottom sometimes. The idea is to make it imperceptible to the user.
Thanks a lot.
try with scrollView.fullScroll(View.FOCUS_DOWN)
Try this
scrollView.scrollTo(0, scrollView.getBottom());
Since I was adding Views dynamically, I also had to allow Android to complete the layout on the content view inside the ScrollView. I just added a post at the end of the View's queue, that will run after it has completed its layout. Otherwise, Android was trying to use the old size of the content view, and wasn't scrolling all the way down.
mMessagesLayout.addView(messageLayout);
mMessagesLayout.requestLayout();
mMessagesLayout.post(new Runnable() {
#Override
public void run() {
mScrollView.scrollTo(0, mScrollView.getBottom());
}
});
I have an Android program with a ScrollView that will correctly do an automatic scroll when I call the scrollBy method on the emulator on my computer but will not do it on my Android phone.
Here is the code:
public class RecordGameActivity3 extends Activity {
ScrollView myView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.recordgame3);
myView = (ScrollView)findViewById(R.id.scrollView1);
}
public void addPlayer(View v)
{
//Removed non-related code
myView.smoothScrollBy(0, 50);
}
}
Also, the regular scrollBy method doesn't work or the scrollTo method (although I may just not be using that correctly since that doesn't work on the computer either). Does anyone have an idea what might be wrong?
EDIT:
My problem as Darrell's answer showed me was that I was calling my smoothScrollBy method from within a function where I was making changes to the layout that would make the scroll area big enough to be able to be scrolled. Apparently, by the time I was calling it in the function, the changes weren't actually applied and so it couldn't be scrolled.
Thus, I changed the code using his advice to the following:
public class RecordGameActivity3 extends Activity {
ScrollView myView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.recordgame3);
myView = (ScrollView)findViewById(R.id.scrollView1);
// New code that listens for a change in the scrollView and then calls the scrollBy method.
ViewTreeObserver vto = myView.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
public void onGlobalLayout() {
myView.smoothScrollBy(0, 100);
}});
}
public void addPlayer(View v)
{
//Code that is called on an onClick listener that adds things to the ScrollView making it scrollable.
}
}
Are you calling smoothScrollBy from the onCreate method? Try waiting until after the views are set up, for instance from onResume. (If you must do it from onCreate you could register a ViewTreeObserver for your view with a OnGlobalLayoutListener, and do the scrolling from there.)
In my case, I need to scroll the ScrollView when there is a MotionEvent.ACTION_UP event triggered in the exact ScrollView , scrollTo() works, but smoothScrollTo() doesn't . Thanks to you guys, I figured it out now, use a handler to smoothScroll the view after a while will work.
Would it be possible to hide a view off the top edge of the screen, and only have it appear if the user scrolls upwards?
My first attempt used a scrollview, but it seems that scrollTo() doesn't work unless I used postDelayed (it doesn't even work with Post()). I tried adding it to the scrollview's view tree observer onPreDraw() event and it still doesn't work unless I delay it, so there is an ugly glitch when the activity is first launched.
The second issue is that if the onscreen keyboard is minimized, the view no longer needs to scroll so hiding things by using a scroll offset no longer works. I thought about manipulating the height in code, but this seems pretty hackish.
Is there a better way to do this than by using a scrollview? Alternatively, Does anyone have any tips on the best place to place the scrollTo (the end of onCreate does not work nor the other places I have tried) so I don't need to use postDelayed? That would at least eliminate one glitch.
Thanks!
This is the code I'm using right now, which is the least glitchy but I don't understand why it doesn't work until the third time onPreDraw() is called.
mScrollView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener()
{
#Override
public boolean onPreDraw()
{
final int fieldYStart = mFieldIWantAtTheTop.getTop();
if (mFieldIWantAtTheTopYStart != fieldYStart
|| mScrollView.getScrollY() < 10)
{
mFieldIWantAtTheTopYStart = fieldYStart;
mScrollView.post(new Runnable()
{
#Override
public void run()
{
Log.v("Testing", "scrolling!");
mScrollView.scrollTo(0, mFieldIWantAtTheTopYStart);
Log.v("Testing", "scroll is now=" + mScrollView.getScrollY());
}
});
}
return true;
}
});
I also tried using a custom scrollview as mentioned below, but this does not solve the issue of the graphical glitch:
#Override
public void onMeasure(int measureWidthSpec, int measureHeightSpec) {
super.onMeasure(measureWidthSpec, measureHeightSpec);
Log.v("Testing", "Scrolling");
post(
new Runnable()
{
public void run()
{
scrollTo(0, 100);
Log.v("Testing", "ScrollY = " + getScrollY());
}
});
}
This code works as does the onPreDraw() code above but there is still a glitch when the activity is launched because the activity is first drawn with the scroll at 0.
I haven't tried this, but you may want to create a custom ScrollView and override onMeasure:
ScrollView scroll = new ScrollView(this) {
#Override
public void onMeasure(int measureWidthSpec, int measureHeightSpec) {
super.onMeasure(measureWidthSpec, measureHeightSpec);
scrollTo(...);
}
};
It seems like this would be the earliest point that scrollTo would be valid.
Edit - I found this answer, which apparently worked for the asker. Is this the method you tried?