ListView into ScrollView (pull-to-refresh) - android

I have to add pull-to-refresh functionality to refresh info on main screen. Here`s a scheme of my screen UI (red area should handle pulling):
I use ready solution for pull-to-refresh. Due to documentation, my red layout should be one of these classes:
ListView
ExpandableListView
GridView
WebView
ScrollView
HorizontalScrollView
ViewPager
But I have ListView on my screen, so I am not able to use ScrollView as red layout. And I`m stuck with this problem. It is possible to use UITableView into UIScrollView in iOS, but in Android one I have no idea what to do in such cases.
Any help will be appreciated. Thanks!

Why not replace the listview by a LinearLayout and then you can use the ScrollView?
You just need to create a layout for the items in the linearlayout and then adding them using something like this:
LinearLayout layout = (LinearLayout)findViewById(R.id.MyListLayout);
for (int i=0; i<list.size(); i++) {
Item item = list.get(i);
View view = inflater.inflate(R.layout.MyRowLayout, null);
Textview myTextView = view.findViewById(R.id.MyTextView);
myTextView.setText(item.getString());
list.addView(vi);
}

Is the pull-to-refresh horizontal or vertical?
In case it's horizontal, use a HorizontalScrollView (a ViewPager would do, too), and then place a Table?Layout inside it.
In case it's horizontal, well, I don't think I like that design (the pull-to-refresh area should just be the ListView), but I believe there is some way to use the ListView without its internal scrolling so that you can rely on a parent ScrollView to do the scrolling, but I'd need to check the code of an old problem to "remember" how to do that.

I've solved this issue, but forgot to write about it :)
My layout.xml file looks like this:
<com.handmark.pulltorefresh.library.PullToRefreshScrollView
android:id="#+id/home_info_pulltorefresh"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true" >
<LinearLayout
android:id="#+id/home_info_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white_background"
android:baselineAligned="false"
android:orientation="horizontal" >
<LinearLayout
android:id="#+id/charts_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
android:orientation="vertical"
android:paddingRight="5dp" >
<FrameLayout
android:id="#+id/frame_container_chart_top"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<FrameLayout
android:id="#+id/frame_container_chart_bottom"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
<FrameLayout
android:id="#+id/frame_container_right"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
</LinearLayout>
</com.handmark.pulltorefresh.library.PullToRefreshScrollView>
android:fillViewport="true" is used to stretch its content to fill the viewport (make height of scroll match_parent)
I add Fragment containing ListView programmatically (R.layout.frame_container_right Fragment resource ID)
Everything worked fine, but when I tried to scroll ListView down, my ScrollView began to scroll. Scrolling ListView up worked fine. Also I noticed that if I tap ListView, move finger left or right and then try to scroll down, touch events are not transmitted from ListView to ScrollView and I get expected behavior. So I've decided to emulate this situation programmatically:
mListViewReviews.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
long startTime = SystemClock.uptimeMillis();
long duration = 1;
MotionEvent e = MotionEvent.obtain(startTime, startTime + duration, MotionEvent.ACTION_MOVE, event
.getX(), event.getY() + 10, 0);
MotionEvent ev = MotionEvent.obtain(startTime + duration, startTime + duration * 2,
MotionEvent.ACTION_MOVE, event.getX(), event.getY() + 20, 0);
v.dispatchTouchEvent(e);
v.dispatchTouchEvent(ev);
}
return false;
}
});
As a result, I've got working ListView with proper cell reuse and working pull-to-refresh logic. Thanks!

Related

How to set canvas (paint view) on top of listview and still have listview clickable?

I have a layout that contains a ListView and a few buttons in a RelativeLayout. I am trying to let the user draw on the page using a custom paint view layout. The good news is that I've got nearly everything working and looking how it should, however the last and most frustrating issue is that the ListView is no longer clickable at all. I would like to paint on top of the the ListView AND make it clickable.
The funny part is that the buttons on the page are still clickable, just the items in the ListView are not. I think what is happening is that the ListView is loaded by an adapter and gets loaded first (thus behind everything). What do I need to do in order to make the ListView clickable?
I've tried adding android:focusableInTouchMode="true" android:focusable="true" but it made no difference.
My layout is as follows:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/background"
android:orientation="vertical" >
<ListView android:id="#+id/lv"
android:layout_height="match_parent"
android:layout_width="match_parent"
></ListView>
<com.my.app.PaintView
android:id="#+id/paintView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<Button
Buttons Here.../>
</RelativeLayout>
The focusable attribute should be false for the element you do not want to receive touch events. To overlay your PaintView without having it intercept touch events, you can add a few XML attributes to it:
<com.my.app.PaintView
...
android:focusable="false"
android:clickable="false" />
As long as you don't set an OnClickListener or an OnTouchListener to your PaintView, touch events should simply pass through it to the Views behind it.
Managed to find a solution that works perfectly (at least for me). I imagine without the listview this would have been far easier, but I wanted the listview to work as well as drawing on the canvas. All I ended up having to do was set an onTouchListener in the main activity that had the ListView, then send it to the PaintView with the MotionEvent. Simple and it works perfectly:
listview.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
paintView.onTouchEvent(motionEvent);
return false;
}
});
In this example, the paintView.onTouchEvent could really be any method in the custom view, just kept it at "onTouchEvent" for simplicity.

ImageView larger than the screen as a background

Hello I have a ImageView(background) which's height should correspond to the screen height, the width on the other hand should be left intact.
Before this was done like this
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="match_parent">
<HorizontalScrollView
android:layout_width="wrap_content"
android:layout_height="match_parent">
<ImageView
android:id="#+id/songDetails_songImage"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:adjustViewBounds="true"
android:contentDescription="#string/songDetails_cd_songCover"
app:srcCompat="#drawable/default_song_cover" />
</HorizontalScrollView>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
...
This worked fine - the image view occupies whole background and the user can scroll right or left to see the whole image.
My goal is to animate the scroll, to do that I need to get rid of the horizontal view(to prevent user from scrolling) but whenever I change the HorizontalScrollView to Frame/Relative layouts(with the width set to wrap_content) the image view is scaled down to fit the screen.
Is there a way to keep the imageView width intact(with height matching that of the screen) so that it would remain bigger than the device screen?(without cropping)
I could then use custom animation to scroll right.
I have looked at similar questions but I wasn't able to find anything that would work in this case.
What you could do is to try to override the onTouchListener for the HorizontalScrollView.
For example, something like this:
scrollView.setOnTouchListener(new OnTouch());
private class OnTouch implements OnTouchListener
{
#Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
}
This would disable the user from scrolling the HorizontalScrollView while you could probably still scroll it programmatically.

Android ListView scrolls the entire screen

I have created a layout containing many linear layouts, and I have, in one of the linear layouts, 3 ListViews set side by side. I want to make each one of them scrollable, but singularily. For example, I want to be able to scroll one of them without anything else being affected.
Right now, if I set "android:nestedScrollingEnabled="true"" for any one of the lists, the entire screen scrolls. I want the scrolling of the list to be confined to the layout the list is in (so I can scroll the list and the rest of the screen stays in place).
How can I do that? So far, it's either no scrolling at all, or scrolling the entire screen. I just want the list to scroll.
Thanks!
PS: Here's how the relevant part of the XML looks like (nothing special about it):
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:layout_marginBottom="#dimen/list_vertical_margin">
<ListView
android:id="#+id/realtime_vehicle_list"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<ListView
android:id="#+id/realtime_errors_list"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<ListView
android:id="#+id/realtime_depot_list"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
</LinearLayout>
One of your LinearLayouts is in a ScrollView, I guess. So remove the ScrollView.
Try to add the next following code in the activity that contains those Listviews:
ListView mylistview = (ListView) findViewById(R.id.mylistview);
mylistview.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
v.getParent().requestDisallowInterceptTouchEvent(true);
return false;
}
I've figured it out. Apparently, the layout "continues" beyond the screen. I only put a few more elements to test if it scrolls, but in reality, the reason why only the 3rd list was scrolling and the other two weren't is because the 3rd list had more elements, and it went beyond its limits. That's why it was scrolling.
I was equating the "going out of the screen" with the idea that the list should scroll, but it's just a design problem - the operating system didn't think that the list was going off the screen.
As soon as I put more elements into the other two lists, they are now all scrolling.

Android: Passing touch event to overlapped view

I have a Relative layout which has two child layouts. First child is linear layout which is container of a fragment. The fragment has few buttons. The second child is a linear layout which has a View which is blank and transparent. The second child overlaps the first child.The first child is smaller than second child. I want to send touch events from second child to first child so that those buttons on the fragment which first child contains receives click.
I read few posts on internet for solving my problem but could not solve it.
So far i have overriden dispatchTouchEvent of Activity and have tried to detect whether touch is in bounds of first child and if so i do firstChild.onTouch(ev). Actually i just dont know what to do and just trying get it working. So please, help me.
#Override
public boolean dispatchTouchEvent(MotionEvent ev)
{
float x,y,backViewX,backViewY,frontViewX,frontViewY;
x = ev.getX();
y = ev.getY();
frontViewX = frontView.getX();
frontViewY = frontView.getY();
backViewX = backView.getX();
backViewY = backView.getY();
if(y >= backViewY && y <= (backViewY+backViewHeight))
{
if(x >= backViewX && x<=(backViewX+backViewWidth))
{
return backView.onTouchEvent(ev);
}
}
return super.dispatchTouchEvent(ev);
}
Orignal Layout is not the exact as i described but it is little more complex but the concept is same as i described....i am shortning the layout for simplifying things.The frontLayout here overlaps layoutBackFragmentArea.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/back_view_background">
<LinearLayout
android:id="#+id/layoutBackFragmentArea"
android:layout_width="match_parent"
android:layout_height="#dimen/back_view_height"
android:orientation="vertical"
android:gravity="center_vertical"
android:background="#android:color/transparent">
</LinearLayout>
<LinearLayout
android:id="#+id/layoutFrontArea"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_vertical"
android:background="#android:color/transparent">
<View
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</RelativeLayout>
layoutBackFragmentArea will contain a fragment which has UI which should receive click events.

Detcting horizontal swipe on relative layout and also properly handle scroll event on the relative layout without any interception

I am new to android development and I am stuck upon following problem. I have been working hard for days and not able to find a solution. In this question I am explaining what steps that I have exactly taken to implement. Please have a look at my procedure and either suggest a solution or an improvisation or an alternative way through which this can be handled.
I want to design a screen which is divided into three parts. The structure of my screen is as follows :
The parent layout of the whole screen is a Scroll-View. The rough structure of the layout file is :
<ScrollView>
<!-- Other Views (Part: 1) -->
<RelativeLayout>
<!-- Part 2 -->
<LinearLayout android:orientation = "vertical">
<LinearLayout android:orientation = "horizontal">
<Button1 /> <Button1 /> </Button3>
</LinearLayout>
<LinearLayout android:orientation = "horizontal">
<Button4 /> <Button5 /> </Button6>
</LinearLayout>
</LinearLayout>
<ImageView>
</RelativeLayout>
<!--Other Views (Part 3) -->
</ScrollView>
The part of interest is the middle part that is the Relative layout. The Things that I want to
Implement is that :
I want to detect a swipe on this RelativeLayout. So with every swipe to either Left or
Right I update the the images and the text that is there on these buttons.
I want to be able to scroll the screen from anywhere on the screen.
To be able to click on the buttons.
Now let me tell you what I have done and the problems that I am facing. To detect the swipe on the relative layout I have set an onTouchListener on the relative layout. The overridden onTouch method is :
public boolean onTouch(View v, MotionEvent event) {
scrollview.requestDisallowInterceptTouchEvent(true);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
downX = event.getX();
downY = event.getY();
return true;
}
case MotionEvent.ACTION_UP: {
if(v instanceof Button){
v.performClick();
}
upX = event.getX();
upY = event.getY();
float deltaX = downX - upX;
float deltaY = downY - upY;
// swipe horizontal?
if (Math.abs(deltaX) > MIN_DISTANCE) {
// left or right
if (deltaX < 0) {
this.onLeftToRightSwipe();
return true;
}
if (deltaX > 0) {
this.onRightToLeftSwipe();
return true;
}
}
}
}
return false;
}
Since , the buttons occupy all the space on the relative layout , I had to set this Listener on
all the inner Linear Layouts and Buttons. To detect the button click and disallow the scroll view to intercept I had to include scrollview.requestDisallowInterceptTouchEvent(true) .
But the problem is that now I am not able to scroll on this Relative layout.
The Swipe and Button clicks are working exactly as they should but , now it is not detecting the scroll.
If I remove the scrollview.requestDisallowInterceptTouchEvent(true) , the scroll is detected but the swipe is not . This is giving a very bad user experience and overall a negative feedback from all of those to who I have shown the application.
So what i want is that , user should be able to scroll from any point of the screen plus he should be able to swipe on the relative layout and also be able to click on the buttons.
Please Help! Could the possible solutions be like :
1) implementing a simpleOnGesture Listener or Detector? override fling event? Please provide valuable and useful pointers.
I suggest you to use ViewPager to accomplish this. You can learn more about ViewPagers from this link: http://developer.android.com/training/animation/screen-slide.html
And there is also a sample code in the website that you can see how it works. It allows you to swipe through pages and also scroll down in each page.
So the main.xml file looks like this:
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
And the fragment.xml file looks like this:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView android:id="#android:id/text1"
style="?android:textAppearanceLarge"
android:textStyle="bold"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp" />
<TextView style="?android:textAppearanceMedium"
android:lineSpacingMultiplier="1.2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/lorem_ipsum" />
</LinearLayout>
</ScrollView>

Categories

Resources