I have a viewPager that I populate using a FragmentStatePagerAdapter. It works fine, can go through populated pages horizontally.
However the middle section of each page on the viewPager is made up of a listView. This listview will sometimes not fit into the designated area, I need to be able to scoll vertically. But I cannot scroll vertically on this section of the viewPager at the moment.
It looks like the viewPager is consuming all the scroll events (both horizontal and vertical).
I do not want a vertical viewPager; I have seen a few answers to that on StackOverflow.
I want only the section in the middle of the viewPager to scroll vertical, and this section is a listView
This is the mainlayout for the tab with a viewPager:
<LinearLayout
android:id="#+id/history"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="#color/fdi_gray">
<android.support.v4.view.ViewPager
android:id="#+id/historyFragment_container"
android:layout_weight="0.85"
android:layout_width="fill_parent"
android:layout_height="0dip"/>
<include layout="#layout/page_indicator_history"
android:layout_height="0dip"
android:layout_width="fill_parent"
android:layout_weight="0.05"
android:background="#color/darker_gray"
android:layout_marginTop="2dp"/>
</LinearLayout>
And the layout out that is used by the ViewPager adapter to populate above viewPager is this:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/spaceHolderLocations">
<TextView
android:id="#+id/locationName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginTop="10dp"
android:layout_centerHorizontal="true"
android:textStyle="bold"
android:textSize="17sp"/>
<TextView
android:id="#+id/latlon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_below="#+id/locationName"
android:layout_marginTop="2dp"
android:layout_marginBottom="3dp"
android:layout_centerHorizontal="true"/>
<View
android:id="#+id/listViewStart"
android:layout_width="match_parent"
android:layout_height="0.5dip"
android:layout_marginLeft="3dp"
android:layout_marginRight="3dp"
android:layout_below="#+id/latlon"
android:background="#color/white" />
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/fdi_gray"
android:layout_below="#+id/listViewStart"
android:layout_marginLeft="3dp"
android:layout_marginRight="3dp"
android:divider="#color/white"
android:dividerHeight="0.5dip"
android:padding="1dp">
</ListView>
<View
android:id="#+id/listViewEnd"
android:layout_width="match_parent"
android:layout_height="0.5dip"
android:layout_marginLeft="3dp"
android:layout_marginRight="3dp"
android:layout_below="#android:id/list"
android:background="#color/white" />
<TextView
android:id="#+id/curingLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/listViewEnd"
android:gravity="center"
android:text="#string/curingLabel"
android:layout_marginTop="10dp"
android:layout_marginLeft="30dp"
android:textSize="17sp"/>
<TextView
android:id="#+id/curingValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#+id/curingLabel"
android:layout_marginLeft="30dp"
android:layout_alignBottom="#+id/curingLabel"
android:textStyle="bold"
android:textSize="17sp"/>
Please note the listview in the above layout.
That's the section of the ViewPager that I want to be able to scroll on; but cannot, I can only scroll horizontally through the pages not vertically through the listView content if it doesn’t fit the page.
This question came close but it's not what I'm looking for: link
Thanks.
Implement the following functionality. I hope it helps you.
mList = (ListView) findViewById(R.id.list);
mList.setOnTouchListener(new View.OnTouchListener () {
#Override
public boolean onTouch(View v, MotionEvent event) {
mList.getParent().requestDisallowInterceptTouchEvent(true);
return false;
}
});
When a touch event occurs, parent always get to intercept the event. Here the parent is View Pager. What you are trying to do here is, when a touch on list view appears, request the parent not to intercept the touch event. This way, the touch event will be received by the Child, which here is ListView, and thus scrolls accordingly.
Basically you cannot set the height of your list view to be "wrap content". give a fixed height, or choose a different layout like linearlayout and set its weight to 1 will be another solution. if you set it to wrap content, it will just take all the space and go beyond the screen.
Related
I'm trying to make a layout in which a ViewPager fills vertically the available space.
Basically what I have here are a bunch of views stacked vertically.
Checkbox
ViewPager
LinearLayout (which will contain the indicator)
Button
I want the checkbox on top, and the button on the bottom, the LinearLayout above the button, and whatever space is left over in the middle to be used by the ViewPager, however I can't seem to be able to make it work.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:background="#color/white"
android:gravity="top|center_horizontal"
android:padding="#dimen/activity_horizontal_margin"
android:layout_width="match_parent"
android:layout_height="match_parent">
<CheckBox
android:background="#drawable/login_button"
android:id="#+id/checkbox_friend_notify"
android:visibility="invisible"
android:checked="false"
android:textColor="#color/black"
android:text="#string/friend_notify"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ViewPager
android:id="#+id/pager"
android:gravity="top"
android:layout_below="#+id/checkbox_friend_notify"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:id="#+id/pager_indicator"
android:layout_centerHorizontal="true"
android:orientation="horizontal"
android:layout_below="#+id/pager"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="#+id/start_btn"
android:visibility="invisible"
android:text="#string/start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/white"
android:background="#drawable/login_button"
android:layout_below="#+id/pager_indicator"
android:layout_alignParentBottom="true" />
</RelativeLayout>
Any pointers?
If you simply need a set of views stacked vertically, consider changing your RelativeLayout for a vertical LinearLayout. Then you can keep all your child views the same (getting rid of all the layout above/below attributes) except give the ViewPager android:layout_height="0dp" and android:layout_weight="1"
Explained:
layout_weight tells LinearLayout how to distribute leftover white space, and by giving the ViewPager a weight (and not giving any of the other children any weight values) you're telling LinearLayout that ViewPager wants all of the remaining white space to itself. This only works if you don't define a height (hence why layout_height=0dp).
You can read more about it on the LinearLayout guide.
I have a LinearLayout and I controlled the height of this layout using getLayoutParams previously and it was working beautifully. Now I want the layout to be scrollable so I placed it under a ScrollView. Now for some reason the getLayoutParams stopped working. I seem to have come to a dead end trying to resolve this. Please help.
Here is my code
if(subHistories.getLayoutParams().height==0)
(subHistories.getLayoutParams()).height=ViewGroup.LayoutParams.WRAP_CONTENT;
else
(subHistories.getLayoutParams()).height=0;
Here subHistories is the layout object I want to control the height for. I want it to switch it's height from zero to wrap_content on every onClick event
And here is the relevant xml code:
...<ScrollView
android:id="#+id/left"
android:layout_width="200dp"
android:layout_height="fill_parent"
android:orientation="vertical"
android:layout_below="#id/head"
android:animateLayoutChanges="true">
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<TextView
android:id="#+id/historyBut"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:background="#5261a5"
android:paddingBottom="5dp"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:paddingTop="5dp"
android:text="Historical Places"
android:textAllCaps="false"
android:textSize="20sp"
android:typeface="normal" />
<!-- historical places category -->
<LinearLayout
android:id="#+id/histories"
android:layout_marginLeft="10dp"
android:layout_width="match_parent"
android:layout_height="0dp"
android:orientation="vertical"
android:animateLayoutChanges="true" >...
After touching layout params, call requestLayout() for the changes to take effect.
For hiding/showing a layout, consider using setVisibility() with GONE and VISIBLE instead.
I have relative layout ("relative") with clickable layout ("clickable") on top, expandable list view ("lview") under "clickable", and "footer" text view with version of my app on bottom of "relative":
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/relative"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/menu_background" >
<com.reconti.app.widgets.Logo
android:id="#+id/reconti_menu_tv_logo"
android:layout_width="fill_parent"
android:layout_height="?android:attr/actionBarSize"
android:layout_alignParentTop="true"
android:gravity="center_vertical"
android:paddingLeft="#dimen/standart_side_margin"
android:textSize="30sp" />
<RelativeLayout
android:id="#+id/clickable"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="#id/menu_tv_logo"
android:layout_marginBottom="10dp"
android:layout_marginTop="10dp"
android:clickable="true"
android:paddingLeft="#dimen/standart_side_margin" >
<com.reconti.app.widgets.RoundedImageView
android:id="#+id/menu_profile_avatar"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:scaleType="fitCenter"
android:src="#drawable/com_facebook_profile_picture_blank_portrait" />
<TextView
android:id="#+id/menu_user_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="10dp"
android:layout_toRightOf="#id/menu_profile_avatar"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#color/white" />
</RelativeLayout>
<ExpandableListView
android:id="#+id/lview"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:childDivider="#color/menu_divider_color"
android:divider="#color/menu_divider_color"
android:dividerHeight="1dp"
android:footerDividersEnabled="false"
android:groupIndicator="#null"
android:headerDividersEnabled="false"
android:listSelector="#drawable/expandable_row_background" />
<TextView
android:id="#+id/footer"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_alignParentBottom="true"
android:layout_marginTop="10dp"
android:gravity="center"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="#color/white" />
</RelativeLayout>
Everything looks good as long as user hit some option in expandable list. Then "lview" overlaps "footer". I would like to achive effect, that "lview" remains on top of "footer" and "footer" remains on bottom of "relative" and only bottom of "lview" is visible to user (so top goes under "clickable"). I hope I explained it clearly:)
Usually I like to work with linearlayout when needs to keep views above views. I don't like how relative layout works sometimes. Well, you can try my idea, I know this works with list, but didnt try with expandable list (but guess will work).
LinearLayout vertical #relative
Logo #reconti_menu_tv_logo
RelativeLayout #clickable
ListView weight 1 #lview
TextView #footer
In this, only your ListView will scroll. I don't know if is this what you want. Your logo, clickable and footer will be fixed.
The weight 1 is to keep your listivew using all not used space, so your footer will be always on "footer". Don't forget about height 0dp when using weight.
Now, if you want all scrolling, you have to use addHeader(View) and addFooter(View) on your list before set the adapter. (this is the better way)
I have an activity where the bottom half of the page is a scrollable results view. At the top of the results view, is a relativelayout with some text and a button. This button will make new items appear in this relative layout to refine the search. This part is all working. However, below this relative layout, I need to add a list of search results. I had this working with a listview, but since I need the entire bottom of the portion of the page (including that header relative layout) scrollable and since you cant have a listview in a scrollview, this wont work.
So, I was hoping I could do something like make another view, populate it with the result data for each result item, and programatically add them below the relative layout. Perhaps just having a linearlayout beneath that header relative layout.
Am I on the right track with this thinking? What is the right way to do this?
If it matters, my app has a min sdk version of 8. I am using the support libraries.
EDIT: here is my current code:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".DealerFragment"
android:descendantFocusability="beforeDescendants"
android:focusableInTouchMode="true"
android:background="#drawable/background">
<ImageView
android:id="#+id/topBar"
android:background="#000000"
android:layout_width="match_parent"
android:layout_height="45dp"
/>
<ImageView
android:id="#+id/logoImageView"
android:layout_width="120dp"
android:layout_height="60dp"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:contentDescription="#string/CD_logo"
android:src="#drawable/logo" />
<fragment
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
class="com.google.android.gms.maps.SupportMapFragment" />
<ScrollView
android:id="#+id/scrollBox"
android:layout_width="match_parent"
android:layout_height="220dp"
android:layout_alignParentBottom="true"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:background="#00000000" >
<RelativeLayout
android:id="#+id/scrollViewRelativeLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#00000000">
<RelativeLayout
android:id="#+id/searchHeaderBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:background="#c0000000">
<TextView
android:id="#+id/near"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:text="#string/near"
android:textColor="#ffffff" />
<TextView
android:id="#+id/nearZip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#+id/near"
android:layout_marginLeft="4dp"
android:layout_centerVertical="true"
android:text="78749"
android:textColor="#ffffff" />
<ImageView
android:id="#+id/narrowSearchImage"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:src="#drawable/filter"
android:contentDescription="#string/CD_Narrow_Results"/>
<TextView
android:id="#+id/narrowSearchText"
android:layout_toLeftOf="#+id/narrowSearchImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:text="#string/narrow_results"
android:textColor="#ffffff"/>
</RelativeLayout>
<LinearLayout
android:id="#+id/resultsLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/searchHeaderBox"
android:layout_marginTop="1dp"
android:orientation="vertical"
android:background="#00000000">
</LinearLayout>
</RelativeLayout>
</ScrollView>
</RelativeLayout>
Basically, I want to know if I should just try to add my result items (which I currently have as a seperate .XML file) and if so how I do that. Or if there is some other device I should be using to accomplish this. My goal, is to have everything in that scrollview to scroll. I don't know how many result items I will have until the page is loaded.
How about, we actually put the ListView in a ScrollView!
I know people say you can't, but I found a way.
1. Wrap the layout that contains your ListView, with a ScrollView.
2. Add this to the class with the layout containing your ListView. Make sure to place it after you set your adapter. The only thing you need to change is dp to the height of your ListView row layout.
int listViewAdapterSize = yourListView.getAdapter().getCount();
LayoutParams listViewParams = yourListView.getLayoutParams();
final float scale = getContext().getResources().getDisplayMetrics().density;
int pixels = (int) ((listViewAdapterSize * dp) * scale + 0.5f);
params.height = pixels;
Let me know if you have any problems!
I've run into a very annoying problem regarding ScrollView resizing, and I'm running out of possible solutions.
I have a FragmentPager containing several different Fragments, one of which has a ScrollView.
The Fragment with the ScrollView is made up of a Spinner and the ScrollView containing a LinearLayout with several rows of other Views (such as SeekBars, Buttons, Edittexts) in it.
Depending on which option is select in the Spinner, the ScrollView shows different views. To do so, some Views have their visibility turned to Gone, while others are turned to Visible.
This works great, except for the fact that the ScrollView does not seem to resize itself properly upon choosing a different option using the Spinner.
When the ScrollView is full of Views, and therefore scrollable, if the user selects an option which shows less Viewsthan required to fill the ViewPort the ScrollView still scrolls.
When the user then chooses the old option again, the ScrollView is now unable to scroll since it took on the size required for the previous option.
When the user then chooses the SAME option again, the ScrollView suddenly is scrollable, since it is now resized to the actual size required.
What is going on here? And better yet, how can I fix this annoying problem?
My layout:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/control_scroll"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#99000000"
android:fillViewport="true" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#DD000000"
android:gravity="bottom"
android:orientation="vertical" >
<TextView
android:id="#+id/lamp_choose_tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:paddingLeft="5dp"
android:text="#string/choose_lamp_text"
android:textColor="#FFFFFF"
android:textSize="14sp" />
</LinearLayout>
<Spinner
android:id="#+id/lamp_select_spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:textColor="#FFFFFF" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#DD000000"
android:gravity="bottom"
android:orientation="vertical" >
<TextView
android:id="#+id/lamp_settings_tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:background="#44000000"
android:paddingLeft="5dp"
android:text="#string/lamp_settings_text"
android:textColor="#FFFFFF"
android:textSize="14sp" />
</LinearLayout>
<!-- Lamp name -->
<LinearLayout
android:id="#+id/naam_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="bottom"
android:paddingBottom="3dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="3dp" >
<TextView
android:id="#+id/bridge_naam"
style="#style/ConfigText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="#string/config_lightname"
android:textColor="#FFFFFF"
android:textSize="16sp" />
<EditText
android:id="#+id/lamp_naam_input"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:background="#drawable/tasstextfield"
android:inputType="textNoSuggestions"
android:textColor="#FFFFFF" >
</EditText>
</LinearLayout>
<View
android:id="#+id/separator"
android:layout_width="fill_parent"
android:layout_height="0.5dp"
android:background="#android:color/black"
android:visibility="visible" />
<!-- Rest of the views -->
Things I already tried:
ForceLayout/requestLayout on the parent ScrollView
Invalidate the ScrollView
ForceLayout/requestLayout on the containing LinearLayout
Invalidating the LinearLayout
Invalidating all children of the ScrollView
ForceLayout/requestLayout on all children of the ScrollView
This might not be the most enjoyable solution, but it might work.
Use a handler to post a delayed message to refresh the view a second time, as if the user would choose the same option twice after having click on the refresh button.
// The code when the user wants to update the views
myButton.setOnClickListener(new OnClickListener{
#Override
public void onClick(View view) {
updateView();
Message m = Message.obtain();
m.what = UPDATE_TAG;
mHandler.sendMessageDelayed(msg, 200);
}
})
...
final int UPDATE_TAG = 1;
public void updateView() {
// Code where View.GONE and View.VISIBLE + invalidate is used.
}
Handler mHandler = new Handler {
#Override
public void handleMessage(Message input_msg) {
if(msg.what == UPDATE_TAG) {
updateView();
}
}
}
Try with this changes
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/control_scroll"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#99000000"
android:fillViewport="true" >
Quit the android:layout_weight="1"
I suppose that LinearLayout uses some kind of caching mechanism to avoid measuring childs every time. Or maybe I'm wrong.
However, you can try to use RelativeLayout instead of bunch of LinearLayout. This will solve your problem and also this will be much more efficient, since nested ViewGroups isn't good for performance.
You can go ahead and set the ScrollView height to "wrap_content" so that even if the child views change the ScrollView can adjust to the new setting