I am having a listview inside a scrollview, but the problem is that the scrollview is scrolling but listview is not scrolling. I think this is due to that scrollView.
Can somebody who has a working solution post it here as reference?
Generally, you cannot put scrollable things inside other scrollable things, where they scroll in the same direction, and have the results be reliable. Occasionally this works (e.g., WebViews in a ViewPager), but that is the exception, not the norm.
Either:
Move the ListView out of the ScrollView, or
Move all the rest of the contents of the ScrollView into the ListView, whether using things like addHeaderView() or my MergeAdapter
If you put your ListView/any scrollable View inside the scrollView it will not work properly because when you touch the screen ,main focus of your touch is on parent view(scrollView ) not the child View (ListView).
ListView must have fixed height as below in your XML file
<ListView android:id="#+id/lv"
android:listSelector="#0f0"
android:layout_width="fill_parent"
android:layout_height="500px" />
In Java file, write below code after setContentView()
lv = (ListView)findViewById(R.id.lv);
lv.setAdapter(your adapter here); // you have to add your adapter here
lv.setOnTouchListener(new ListView.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_MOVE)
{
lv.scrollBy(0, 1);
}
return false;
}
});
Make these changes to your code and test it. After too many experiments i written this code. It is working 100% fine.
Related
I have a RecyclerView wrapped in a LinearLayout and it works perfectly as expected. I can see all the data in the RecyclerView as populated. So far so good.
When I wrap the LinearLayout in a ScrollView, the RecyclerView goes blank. I do not see anything inside RecyclerView. Why? How to make this work.
The page is one of the tabs in a ViewPagerIndicator, so everything in that tab needs to be in a ScrollView.
Thanks for all the help.
Set this property for the ScrollView,
android:fillViewport="true"
ScrollView will extend itself to fill the contents
After checking implementation, the reason appears to be the following. If RecyclerView gets put into a ScrollView, then during measure step its height is unspecified (because ScrollView allows any height) and, as a result, gets equal to minimum height (as per implementation) which is apparently zero.
You have couple of options for fixing this:
Set a certain height to RecyclerView
Set ScrollView.fillViewport to true
Or keep RecyclerView outside of ScrollView. I my opinion, this is the best option by far. If RecyclerView height is not limited - which is the case when it's put into ScrollView - then all Adapter's views have enough place vertically and get created all at once. There is no view recycling anymore which kinda breaks the purpose of RecyclerView.
Nothing helped me except this:
mRecyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
#Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
int action = e.getAction();
switch (action) {
case MotionEvent.ACTION_MOVE:
rv.getParent().requestDisallowInterceptTouchEvent(true);
break;
}
return false;
}
#Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
#Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
});
I got this answer there. Thank you Piyush Gupta for that.
Hope this helps :
Add this line to your recyclerView xml :
android:nestedScrollingEnabled="false"
Try it ,recyclerview will be smoothly scrolled with flexible height inside scrollview .
I have two rows of imageViews in a ScrollView. The imageViews all have onClickListener and when i want to scroll in this area it doesn't work. So i guess the Click listeners intercept the scrolling of the ScrollView. What's the best way to change this behaviour ?
My View hierarchy is like this:
<ScrollView>
<RelativeLayout>
<FrameLayout>
</FrameLayout>
<RelativeLayout>
</ScrollView>
in the FrameLayout i put a Fragment which has a LinearLayout in which i inflate other LinearLayouts like this:
productHolder.productLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View v) {
}
});
Maybe you could use an OnTouchListener instead of an OnClickListener.
In the OnTouchListener you can check if the action of the motion event was a click and consume the event (return true). Otherwise you can leave the event for other listeners (return false) to consume.
Note, that you might need to add some additional implementation for figuring out which image view was clicked, however without seeing your layout, it's hard to give you a hint how to do it.
I have a ScrollView that contains a complex LinearLayout with various elements, among which there are several TextView with maxHeight defined and a long text inside. I need to enable scrolling the text inside the TextView when touch-and-dragging inside it, and the normal scroll of the ScrollView when touch-and-drag outside of them.
Is there a proper and elegant way to do this - if at all possible - or do I have to get dirty and start overriding the onTouchEvent handlers on all elements involved?
UPD 1: Judging from this there is no elegant solution, and the UI will have to be rethinked to include only one layer of scrollable elements.
So it's not pretty, but you can extend from TextView and block the scrollview from scrolling. It's not as nice unless your textviews are large enough. After using this solution we found that it is best if you have a "show more" label that the users can click to show the full thing. Anyway, extend from TextView and override the onTouchEvent method:
public boolean onTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
this.getParent().requestDisallowInterceptTouchEvent(true);
}
if (ev.getAction() == MotionEvent.ACTION_UP) {
this.getParent().requestDisallowInterceptTouchEvent(false);
}
return super.onTouchEvent(ev);
}
A ScrollView is a FrameLayout, meaning you should place one child in it containing the entire contents to scroll; this child may itself be a layout manager with a complex hierarchy of objects. A child that is often used is a LinearLayout in a vertical orientation, presenting a vertical array of top-level items that the user can scroll through.
<ScrollView
android:id="#+id/ScrollView01"
android:layout_height="150px"
android:layout_width="fill_parent">
<TextView
android:id="#+id/TEXT_VIEW"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="This text view should act as header This text view should act as header This text view should act as header This text view should act as header This text view should act as header This text view should act as header This text view should act as header" />
</ScrollView>
you can see the APIdemos for more information, there is a a view of lot of text's with their own stylized scrollview in the same windows. For more inforation you can visit:
http://developer.android.com/resources/samples/ApiDemos/index.html
I am using relativelayout and inside it a scrollview and inside it a linear layout and a textview which is ensuring scrolling of textview, but I do not want to scroll the text after the particular condition. So, what can I do for this?
To make the scrollbars invisible use this attribute.
android:scrollbars="none"
Edit:
if there is need of runtime changes on visibility or state of enabling, for that we can use the scrolview.setEnabled(false) or android:enabled=false.
There is no direct way to stop scrollview to scroll but u can do it in other way Like:
//global boolean variable
boolean enable = true;
scrollview.setOnTouchListener(new OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event)
{
return !enable;
}
});
when you set enable variable to true it will start scrolling and when you set it to false it stop scrolling.
If I interpreted your question correctly, you probably want to extend ScrollView and write your own implementation of onInterceptTouchEvent. You could then make your ScrollView conditionally ignore touch events, thus disabling the scrolling behavior. See this question for more details.
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.
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.
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.
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.
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.
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
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();