I have a layout which requires me to put a grid view inside a scroll view, i have read this is not suggested but my layout requires this.
When inserting a GridView in a ScrollView the grid does not scroll! I have got around this with the following.
The problem i have is that i have is the grid view will not scroll smoothly, if i hold my finger down and drag it scrolls, but if i do a swipe type of gesture it does not do a smooth scroll as expected. as soon as i remove my finger the scrolling stops on the grid view.
gridView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN
|| event.getAction() == MotionEvent.ACTION_MOVE) {
gridView.requestDisallowInterceptTouchEvent(true);
}
return false;
}
});
i tried adding this but no luck
gridView.setOnScrollListener(new OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView view,
int scrollState) { // TODO Auto-generated method
// stub
}
#Override
public void onScroll(AbsListView view,
int firstVisibleItem, int visibleItemCount,
int totalItemCount) {
// TODO Auto-generated method stub
gridView.requestDisallowInterceptTouchEvent(true);
}
});
EDIT:
Just to give a bit more information
the grid view is inserted programatically, inside a relative layout which sits in a linear layout inside a scrollview
I would Suggest you to use ExpandableHeightGridView. It works for me very fine.Hope this will help you :)
To Answer my own question, i found a solution taking some parts from this example, works perfectly
https://github.com/Durgadass/ScrollInsideScroll
Related
My ultimate goal is to stop the scroll in specific locations, so the objects being viewed are shown completely, and the solution I came up with is by checking the scrollX location of the view when the touch is released. I did have a momentum issue, as the scroll could still continue due to the scroll velocity also after catching the touch event, I solved that using MotionEvent.ACTION_CANCEL, which I am not happy with, as the scrollTo is optically pleasing, but the MotionEvent.ACTION_CANCEL kills its effect.
My question is, is there a more elegant way to do this? Ideal would be if I could simply instruct my ScrollView NOT to have momentum/velocity.
myView.setOnTouchListener(new HorizontalScrollView.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
event.setAction(MotionEvent.ACTION_CANCEL);
int x = myView.getScrollX();
if (x < 150)
myView.scrollTo(0,0);
else if (x<450)
myView.scrollTo(300,0);
else
myView.scrollTo(600,0);
}
return false;
}
});
If you want to scroll precisely to show specific view, this answer should help you. What you have to do is to call myView.scrollTo(0, view.getBottom()) or myView.smoothScrollTo(0, view.getBottom()) on UI thread. This way, view object will be displayed fully.
EDIT: It seems to me that what you're trying to achieve here is very close to what ViewPager does: your intention is to move between the views with a swipe/fling gesture, providing full visibility to the paged views contents.
If you were to use ViewPager, this is how your code may have looked:
viewPager.setAdapter(new PagerAdapter() {
#Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
#Override
public int getCount() {
return getViewCount();
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
View view = getViewAtPosition(position);
container.addView(view);
return view;
}
#Override
public void destroyItem(ViewGroup container, int position, Object view) {
container.removeView((View) view);
}
});
Where getViewCount() and getViewAtPosition() methods have to be implemented accordingly to how many displayed views you want and the way they are instantiated.
You should use an onScrollListener if you want to get the current position when the scrollView is scrolled.
scrollView.getViewTreeObserver().addOnScrollChangedListener(new OnScrollChangedListener() {
#Override
public void onScrollChanged() {
int scrollX = rootScrollView.getScrollX(); //for horizontalScrollView
int scrollY = rootScrollView.getScrollY(); //for verticalScrollView
//DO SOMETHING WITH THE SCROLL COORDINATES
}
});
I want to detect the Top of List view and i am using this method.
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (firstVisibleItem == 0)
swipeRefreshLayout.setEnabled(true);
else
swipeRefreshLayout.setEnabled(false);
}
This works fine, but the problem is I have attached the Header View to list as well. When I scrolled up, as soon as the first item is visible(not the Header view) it calls pull to refresh of list view. How can i detect that the List's Header is completely visible.
My List View Is
View imageSlider = inflater.inflate(R.layout.image_slider_layout, null, false);
findViewById(imageSlider);
mPullRefreshListView.addHeaderView(imageSlider);
private void findViewById(View view) {
mViewPager = (ViewPager) view.findViewById(R.id.view_pager);
mIndicator = (CirclePageIndicator) view.findViewById(R.id.indicator);
}
hmm, Interesting answer lies in onTouch listener rather then onScroll, see the implementation below, it exactly tells u when header is completely visible, you can refine the logic further.. its just a quick implementation form me.
// Set a on touch listener for your list
mList.setOnTouchListener(new OnTouchListener(){
#Override
public boolean onTouch(View v, MotionEvent event) {
// get the top of first child
View mView = mList.getChildAt(0);
int top = mView.getTop();
switch(event.getAction()){
case MotionEvent.ACTION_MOVE:
// see if it top is at Zero, and first visible position is at 0
if(top == 0 && mList.getFirstVisiblePosition() == 0){
Toast.makeText(MainActivity.this, "Header Item Visible",
Toast.LENGTH_SHORT).show();
}
}
// dont forget to retrun false here
return false;
}
});
You can simply identifies it with visibleitemCount in onScroll Listener also.
Firstly identify your listview's visible item count at the top of listview include the header. you can get the count by toasting or debugg the code.
in my case
my listview's normal visibleItemCount is 3 and at the place of top it is 2 (with headerview), then my code is work for me.
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if(firstVisibleItem==0&&visibleItemCount==2)
{
swp.setEnabled(true);
}
else{
swp.setEnabled(false);
}
}
There is a list view. I wrote this to stop the scroll when the user touches the screen while scrolling:
public class OnTouchListner implements OnTouchListener{
#Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction()==MotionEvent.ACTION_DOWN)
{
businessResultListView.smoothScrollBy(0, 0);
return true;
}
return false;
}
}
When i scroll the list down and when I touch the screen, the list view stops scrolling. But if I again try to scroll down / up, without lifting my finger from the scroll view, i am unable to scroll it.
If I take off my finger, then touch the list and then try to scroll, then I can do so.
How can I make my list scrollable after touch ?
Any help is greatly appreciated...
Give the Scroll id like scroll_home
ScrollView scroll_home;
scroll_home = (ScrollView) findViewById(R.id.scroll_event);
and on touch listview row add this function ...
this working well
v.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
scroll_home.requestDisallowInterceptTouchEvent(true);
return false;
}
});
I have an app that uses an ExpandableListView widget filled with items via a BaseExpandableListAdapter. The app was built for the Android Version 1.6, and when I test it using the Android Emulator (version 1.6 build) everything works fine. I can scroll the list up and down and when I tap on any items in the list I get a onChildClick() event.
However, when I try to run this same app on an real Android phone (running Gingerbread), I only get onChildClick() events if I don't scroll the ExpandableListView. If I scroll the list too much, I no longer get onChildClick events (nor itemClickEvents also).
So I'm baffled. Why do I not get any onChild or onItem click events for the listview items after I scroll it? Note, that if I scroll it just a small amount (say, 2 or three lines) I do get click events, but any more scrolling and then I no longer get click events for any item in the list.
Any suggestions or advice would be appreciated.
Thanks.
Ok, I'm answering my own question here for others who may have the same problem. The issue I'm experiencing seems to be related to the focus status of the ExpandableListView Widget. When I scroll the list, the ListView widget seems to lose focus and I can't select any of the listed items. I'm not sure what the best way is to correct this, but I did get this to work.
I added a scroll listener for the ListView widget as show:
getExpandableListView().setOnScrollListener(this);
I then added a method to my activity that would set the focus back to the ListView Widget once it is finished scrolling:
#Override
public void onScrollStateChanged(AbsListView view, int scrollState)
{
// - this method is called when there is a scroll event in the main ExpandableListView widget.
// - after the user stops scrolling the listview, make sure to set the focus to the widget
if ( scrollState == OnScrollListener.SCROLL_STATE_IDLE )
{
ExpandableListView elv = getExpandableListView();
elv.requestFocusFromTouch();
}
}
Now that seems to fix my issue. I'm sure there's a better way (and if you know of one, please post it here), otherwise my "hack" seems to work ok.
Hope it helps someone with a similar issue.
Thanks, this answer solved my problem on losing focus on while scrolling.
ListView mRecentSearchList;
mRecentSearchList.setOnScrollListener(new OnScrollListener(){
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
//adapter.notifyDataSetChanged();
}
public void onScrollStateChanged(AbsListView view, int scrollState) {
//adapter.notifyDataSetChanged();
if(scrollState == OnScrollListener.SCROLL_STATE_IDLE ||scrollState == SCROLL_STATE_TOUCH_SCROLL || scrollState == SCROLL_STATE_FLING)
{
mRecentSearchList.requestFocusFromTouch();
}
}
});
I have experienced exactly the same problem and I found that it was caused not by list itself but adapter(ResourceCursorTreeAdapter). To prevent groups to collapse I was doing a hack as follows in my adapter:
#Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
View view = super.getGroupView(groupPosition, isExpanded, convertView, parent);
ExpandableListView list = (ExpandableListView) parent;
list.expandGroup(groupPosition);
return view;
}
If you do the same, please try replacing this with different solution.
In my case I've used the same solution proposed by cohoman, however the requestFocus() method provided me a better user experience:
navList.setOnScrollListener(new OnScrollListener()
{
#Override
public void onScrollStateChanged(AbsListView view, int scrollState)
{
if(scrollState == OnScrollListener.SCROLL_STATE_IDLE)
{
navList.requestFocus();
}
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)
{
// TODO Auto-generated method stub
}
});
I have a problem;
I have a layout with scroll view over three list view A,B,C.
I want scroll hole layout as well as scroll each list view.
Problem:
List view are not scroll when layout is scroll if I remove scroll layout then list is scroll but layout is not scroll.
What is a possible solution?
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.
We cant scroll listview within scrollview, because listview itself contains scroll option.
Check this link:
http://code.google.com/p/android/issues/detail?id=6552
By that listview bug can do that list in scroll.
It depends on how you want the view and how you want the scrolling to be.
If you want all of them scrollable, then you should apply a fixed height on the list views. It will sometimes confuse which will scroll first.
Or you can populate the whole list with no scroll inside a scroll view, which will create a long list with all items from all of the lists.