6

Here's the scenario conceptually (excluding linearlayouts)

ScrollView
  Button
  Checkboxes
  Spinner
  ListView (full-size, non-scrolling)
AdMob advert

i.e. a scrolling pane, which has a filtering UI at the top, followed by results, but the advert must always remain visible, and when scrolling down the filter UI must scroll away, leaving maximum space for results.

I'm aware there are issues with a ListView inside a ScrollView, though for me it is working well in many ways (I'm fixing the length of the ListView to stop it collapsing). So the screen scrolls nicely, the ad stays put at the bottom, and it looks good.

But the problem I'm seeing is, inexplicably, when the activity opens, the ScrollView is scrolled down a bit, so the ListView is at the top of the screen. I assume this is a default behaviour, so I set about trying to force the scroll position of the ScrollView to the top, but I've tried various methods, and see no effect:

scrollview.scrollTo(0, 1000/-1000);
scrollview.smoothScrollBy(0, 1000/-1000);
scrollview.fullScroll(View.FOCUS_UP);

Is there any way to force the ScrollView to start with the scroll position at the top?

If not, how can I have an ad that doesn't scroll off the bottom, but a filter UI that always scrolls off the top? Using ListView seems overkill as I don't need scrolling but it does provide many benefits so would be nice to avoid starting from scratch and rendering everything myself.

Ollie C
  • 28,313
  • 34
  • 134
  • 217
  • Any real solution for this issue? – Tony Jan 25 '12 at 18:59
  • This not a good practice to do but if you try to give height to listview on runtime than its possible. see below link :- http://stackoverflow.com/questions/3495890/how-can-i-put-a-listview-into-a-scrollview-without-it-collapsing/3495908#3495908 – duggu Jun 24 '13 at 11:59

6 Answers6

1

Use the following method and enjoy!

    private void setListViewScrollable(final ListView list) {
    list.setOnTouchListener(new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            listViewTouchAction = event.getAction();
            if (listViewTouchAction == MotionEvent.ACTION_MOVE)
            {
                list.scrollBy(0, 1);
            }
            return false;
        }
    });
    list.setOnScrollListener(new OnScrollListener() {
        @Override
        public void onScrollStateChanged(AbsListView view,
                int scrollState) {
        }

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem,
                int visibleItemCount, int totalItemCount) {
            if (listViewTouchAction == MotionEvent.ACTION_MOVE)
            {
                list.scrollBy(0, -1);
            }
        }
    });
}

listViewTouchAction is a global integer value. If you can replace the line

list.scrollBy(0, 1);

with something else please share it with us.

Bob
  • 22,810
  • 38
  • 143
  • 225
0

Why are you using a listview if you're not scrolling? Why can't you just use a linearlayout or something more fit to this situation? You mention a filter, you could very easily roll your own filter especially since apparently you just have a few items in your listview.

Falmarri
  • 47,727
  • 41
  • 151
  • 191
  • I'm filling the ListView from an adapter, and I can't do that with a LinearLayout. The items in the ListView are dynamic, and I'd certainly be very interested to know what would work better as a replacement for the ListView, so I solve the scrolling issue, but retain benefits of the ListView, like data binding and item reuse. Would it makes sense to replace the ListView with an AdapterView? – Ollie C Oct 24 '10 at 20:04
  • You can create an adapter and just not bind it to a listview – Falmarri Oct 24 '10 at 22:02
  • I'm not sure if other views are able to "bind" to adapters. But you could write your own LinearLayout in java that watches for changes in the adapter. I'll bet if you look at the implementation of `ListView.setAdapter()` it would be fairly simple – Falmarri Oct 25 '10 at 17:31
  • If I have to do that then I will, but isn't there a standard component that lets me create a set of consecutive items in a non-scrolling list? Android seems pretty bad sometimes for what would be pretty easy on other platforms :-( This UI pattern is very common. – Ollie C Oct 25 '10 at 19:05
  • Well an adapter will do that just fine. Just create a linearlayout and then you can call adapter.getView() yourself and add those views to your linearlayout. That's all binding it to a listview does anyway. – Falmarri Oct 25 '10 at 19:30
  • As a general note, another solution that can work well for this is to use the Header and Footer within the ListView. This response was provided by Reto Meier who I quizzed about this in an app surgery. i.e. to put an ad on the bottom of a ListView, you just put the ad view into the ListView footer – Ollie C Nov 22 '10 at 21:20
  • The problem with that comes in when you start wanting dividers, which you now have to roll on your own as well. – Artem Russakovskii Jun 16 '11 at 23:02
  • @Tony, yes, this answer is quite old and has already been marked as a solution. If it doesn't meet your needs, then consider asking your own question. This isn't a forum. – Falmarri Jan 27 '12 at 00:54
  • @Falmarri, This is not a solution for the problem, this is just doing it in a different way, which is fine, but does not solves the problem "scroll view is scrolled down". A linear layout has not the same features as the listview, I think that it is not a crazy thing to use a listview, and it should work. – Tony Jan 27 '12 at 13:15
  • @Tony, this is a solution to this problem because the OP accepted it. This is not a forum. Don't hijack 2 year old questions. Ask your own question if this post doesn't help. – Falmarri Jan 30 '12 at 20:20
  • @Falmarri, ok, great, sorry for posting a real solution. Maybe it can help someone. Good bye. – Tony Jan 30 '12 at 20:51
0

Use something other that a ListView, you can dinamically generate linearLayouts to show the data you want. You should never use a listview inside a scrollView, it doesnt work for a simple reason, when you scroll, what should scroll, the listview or the scroll view. A couple of people from google have stated not to do this.

blindstuff
  • 18,298
  • 10
  • 47
  • 48
  • Sure, I understand using a scrolling control inside a scrolling control is bad news (from a UI perspective, let alone the implementation) but in a scenario where the ListView has no scrollbars, this limitations makes less sense. – Ollie C Oct 25 '10 at 12:25
  • How are you guaranteeing that the listview doesn't scroll? – Falmarri Oct 25 '10 at 17:32
  • The fact that is doesnt scroll indicates that there isnt much data to show, that was my main reasoning for thinking that he should need a list view. – blindstuff Oct 25 '10 at 17:34
  • I've forced the length of the ListView using android:layout_height, which ensures it never has a scrollbar. So in my app there is only ONE scrollbar, that on the ScrollView. So it actually works very well, apart from this issue where the ScrollView position is being affected by the ListView's presence. What class would make a good replacement for the ListView, where I can use an adapter, but avoid all the scrolling issues? – Ollie C Oct 25 '10 at 19:04
0

I've experienced the issue of a ScrollView starting off scrolled down slightly, the solution was to post a runnable which called the animateTo(0,0) method to get the list to scroll to the top. I found this only worked using anitmatTo(0,0) scrollTo(0,0) didn't seem to work.

Something along the lines of:

mListView.post(new Runnable(){ public void run() { mListView.animateScrollTo(0,0) });

Now as everyone has already stated you shouldn't do the whole ListView inside a ScrollView, but this may be a fix for the problem you had.

Matt Gaunt
  • 9,434
  • 3
  • 36
  • 57
  • Looking back at this after a few months, the answer to what I was trying to do seems rather obvious - ListView's header. I would never have scrolling inside scrolling, but I did need a ListView and other stuff to scroll as a lump, and the ListView already has all that in it. Easy to miss these things when the public interfaces are so large on some Android classes. – Ollie C Apr 19 '11 at 08:16
0

I have:

ScrollView
 TextView
 Button
 TextView
 ListView

and this work good for me:

scrollView.smoothScrollBy(0, 0);        

without this view start from position of listview, after that it start from top

mtfk
  • 890
  • 6
  • 12
-1

The solution for this issue is to make a request focus to an object in the top of the ScrollView. For example you can use a table layout wrapping the button and request focus to the table layout (If you focus the button it will change its color).

// onCreate method
TableLayout tablelayout = (TableLayout) findViewById(R.id.tablelayout);
tablelayout.setFocusableInTouchMode(true);
tablelayout.requestFocus();
Tony
  • 10,088
  • 20
  • 85
  • 139