Block layout pass programmatically? - android

This is my View Hierarchy:
-RelativeLayout [rootView] (root)
LinearLayout [menu_holder] (menu fragment layout)
RelativeLayout [app_holder] (app content layout)
Action Bar (custom view to implement ActionBar < 2.1
FrameLayout [content_fragment] (layout to load content fragment)
FloatingMenu (custom LinearLayout to show a floating widget)
<com.example.app.views.widgets.RootLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drag_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#color/white" >
<LinearLayout
android:id="#+id/menu_holder"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#color/red"
android:orientation="vertical" />
<com.example.app.views.widgets.AppHolder
android:id="#+id/app_holder"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#color/gray" >
<com.example.app.widgets.ActionBar
android:id="#+id/action_bar"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<FrameLayout
android:id="#+id/content_holder"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_below="#+id/action_bar"
android:background="#drawable/backrepeat" >
</FrameLayout>
<com.example.app.widgets.FloatingMenu
android:id="#+id/floating_menu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:padding="15dp"
android:visibility="gone" />
</com.example.app.views.widgets.AppHolder>
</com.example.app.views.widgets.RootLayout>
Now I load both menu_holder & app_holder into the rootView, such that app_holder stays on top. Now when the user presses MENU button, app_holder slides towards right to show the underlying menu fragment on the left, like in the picture below:
I have used a scroller inside a runnable to slide app_holder towards right. I also call invalidate() every 16ms on the rootView after offsetting my app_holder.
Its working fine, but problem comes when any content gets loaded in the content_fragment (visibility set or loaded from web), when the menu fragment is visible. The invalidated view (out of bounds) calls requestLayout() and the following layout call resets the app_holder to its initial position. I have implemented lazy loading listviews on my content_fragment, so any update on the listview (notifyDataSetChanged etc.) initiates a relayout call.
How to stop this from occurring ?
Overriding and commenting requestLayout() on all dynamically loaded views on the right will fix the issue, but is there any other proper way ?

Related

Custom Drawer Layout - Click transparency

I use the Drawer Layout in my project. I want to customize the Drawer like the Google+ Android App. Over the "main" ListView I've added a ImageView. That's work fine. The code is:
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<RelativeLayout
android:id="#+id/drawer_layout_relative"
android:layout_width="240dp"
android:layout_height="wrap_content"
android:layout_gravity="start" >
<ImageView
android:id="#+id/drawer_header_image"
android:layout_width="wrap_content"
android:layout_height="85dp"
android:src="#drawable/ic_logo_blue" />
<ProgressBar
android:id="#+id/drawer_progress"
style="?android:attr/progressBarStyleLarge"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/drawer_header_image"
android:background="#ffffffff" />
<ListView
android:id="#+id/drawer_listview"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_below="#id/drawer_progress"
android:background="#ffffffff"
android:choiceMode="singleChoice" />
</RelativeLayout>
When you click on one of the ListView-Items a fragment load into the FrameLayout. Thats work perfectly, too.
But there is one problem. The ImageView is "clickable" too. So that, when the Drawer is open, an one will click on the ImageView the ListView (on the fragment) behind is clicked!! I don't want that. So I have try it with clickable:false on ImageView. Don't work...
For a little demo here is a video: http://www.vidup.de/v/Ao71r/
How can i make the imageview don't clickable?!
In order to keep clicks from being passed through the drawer to the view behind it, you have to setClickable to true for the view in the drawer, specifically the parent view of all the other views you have in your drawer, so that it consumes all the touch events if none of its children consume them.
Change your RelativeLayout code for drawer_layout_relative to the following (NOTE: I added android:clickable="true" to the relative layout):
<RelativeLayout
android:id="#+id/drawer_layout_relative"
android:layout_width="240dp"
android:clickable="true"
android:layout_height="wrap_content"
android:layout_gravity="start" >
By default, if a view does not handle any clicks, it lets the clicks go to the view behind it. You have an ImageView, a ProgressBar, and a ListView: The ListView handles click events, so it consumes any touches on it. The ProgressBar and ImageViews by default just display stuff and don't handle clicks to them, so the system just passes the click to the list that you have behind the drawer. Those three views are all inside a RelativeLayout. If we set that RelativeLayout to be clickable, it collects the click events that aren't handled by the ImageView and ProgressBar and it doesn't let the click events go to the view underneath it.
Think of android:clickable="true" as a way to block interaction with any view underneath the view you set this on.
For further explanation, please see this question

Receiving click/swipe events on a view behind a transparent item of a listview

I have a layout similar to Foursquare (image), where a View (in their case, a map) is behind a ListView, but is visible because the first element is transparent.
I need the View behind the ListView to take touch and swipe events. Is there a way to make only that first invisible item of the ListView ignore these events and allow the events to propagate to the View behind it, but have the rest of the ListView items take the events as usual?
I'm just hoping I won't have to completely abandon the ListView and use a ScrollView instead, because I've already implemented a lot of ListView specific features.
ScrollView on the back will work normaly unless you click the button:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:id="#+id/bottom"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/text"
android:text="asdfasdfa Put more text for testing sdfasdfasdfasdfasdfff
afdasdfasdfasdfasdfasdf
asdfasdfa"/>
</ScrollView>
<LinearLayout
android:id="#+id/top"
android:layout_height="match_parent"
android:layout_width="match_parent">
<Button
android:id="#+id/butt"
android:layout_height="100dp"
android:layout_width="200dp"
android:text="Test"/>
</LinearLayout>
</FrameLayout>
Both of the layers/frames have height and width set to match_parent (full screen in this case). And you can basicaly put anything you want into both of this layers as you need it.

Android: Hidden buttonbar like in Hotmail app

Consider the Hotmail app for Android. When you check an e-mail item, three buttons appear at the bottom: [Mark Read] [Mark Unread] [Delete]
When you uncheck it, the buttons go away again.
What's the layout for this? I've tried this, but it yields scrolling problems at the bottom (can't see last item):
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="#+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/black" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#android:color/darker_gray"
android:orientation="horizontal"
android:paddingLeft="5dip"
android:paddingRight="5dip"
android:paddingTop="5dip" >
<Button
android:id="#+id/bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:enabled="false"
android:text="#string/mark_read" />
</LinearLayout>
Then, I also need to show/hide this stuff?
Changing the visibility of bottom linearlayout will show/hide it. You'll need to give it an id and then
LinearLayout bottomLayout = (LinearLayout)findViewById(R.id.someId);
bottomLayout.setVisibility(View.GONE)// or View.VISIBLE
As for the scrolling problem, that occurs because the RelativeLayout overlays view components, so you can either show/hide the button overlaying the bottom of the ListView or change the Relativelayout to a LinearLayout so that the ListView ends before the button and change the visibility.
Though I'm not sure this will look very good when you suddenly show the button and the ListView has to resize itself.
Note on visibility
setVisibility(View.GONE);
will remove the view from the layout and other component may resize due to this. However using
setVisibility(View.INVISIBLE);
keeps the space the view took up in the layout and simply makes the view invisible and no resizing will occur.

Pass touch event down through Views and ViewGroup

I have a FrameLayout wiht a ScrollView and a LinearLayout inside.
Both ScrollView and LinearLayout have the same dimensions, so they are overlaid and the LinearLayout covers and hides the ScrollView.
The ScrollView has TextView and a Button inside itself.
This is the situation:
+FrameLayout
+ScrollView
+ LinearLayout 1
+ TextView
+ Button
+LinearLayout 2
Sometimes the LinearLayout2, which is on the top, is animated and goes out of the screen. For layout reasons I can't set it to GONE and this is the problem.
After the animation ends, the ScrollView is shown and I need to interact with the ScrollView, for example clicking the button and obviously scrolling, but all the events are always caught by the LinearLayout 2, because it always has the Visibility set to VISIBLE even if is actually hide out of the screen.
So, how can I pass the touch event down to the scrollview and its children?``
** EDIT **
This my XML. So you can understand better.
Which is the idea?
This layout is composed by 4 sliding drawer. When the user clicks on one of them, the drawer clicked goes up with animation and becomes a kind of header, the others go down out of the screen and they hide and the scrollview is visible ready to interact with the user.
For example: I click the second drawer, the third goes down, the disclaimer, the first goes up out of the screen and the second, which has been clicked goes at the top of the scree as an header. If I click again the second drawer, which is on the top now, I restore the initial layout as at the beginning, always with animation. To do that I add a Trasparent Layout, which has the same dimension of a drawer on the top, to handle click event, so I avoid to set a new layout whenever I animate the drawers.
What I want is to interact with the scrollview when it becomes visible and with all the stuff inside it.
PROBLEM: I can't set the drawers to GONE because the wieght parameter influences their height, but only to INVISIBLE. So, how can interact with the scrollview below?
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/programma_layout_root"
android:layout_width="fill_parent" android:layout_height="fill_parent">
<!-- SCROLLVIEW HIDDEN FIRST LAYER -->
<ScrollView android:id="#+id/programma_content_scroll" android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="top">
<LinearLayout android:id="#+id/programma_layout_disclaimer_content"
android:layout_height="fill_parent" android:layout_width="fill_parent"
android:orientation="vertical" android:visibility="invisible">
<TextView android:id="#+id/programma_layout_disclaimer_content_text"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:text="some text..." />
<Button android:id="#+id/programma_layout_disclaimer_content_button"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center|bottom" android:text="CLICK" />
</LinearLayout>
</ScrollView>
<!-- LAYOUT FOREGROUND SECOND LAYER -->
<LinearLayout android:id="#+id/programma_layout_container"
android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"
android:weightSum="19">
<include android:id="#+id/header_placeholder" layout="#layout/header" />
<!-- DISCLAIMER DRAWER -->
<RelativeLayout android:id="#+id/programma_layout_disclaimer"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:layout_weight="4" >
</RelativeLayout>
<!-- FIRST DRAWER -->
<RelativeLayout android:id="#+id/programma_layout_first"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:layout_weight="5" android:visibility="visible"
>
<!-- some stuff here (text, image...) -->
</RelativeLayout>
<!-- SECOND DRAWER -->
<RelativeLayout android:id="#+id/programma_layout_second"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:layout_weight="5"
>
<!-- some stuff here (text, image...) -->
</RelativeLayout>
<!-- THIRD DRAWER -->
<RelativeLayout android:id="#+id/programma_layout_third"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:layout_weight="5" >
<!-- some stuff here (text, image...) -->
</RelativeLayout>
</LinearLayout>
<include android:id="#+id/header" layout="#layout/header"
android:layout_gravity="top" />
</FrameLayout>

Hiding Android "loading" view to show another view

In my XML layout for an activity, I've got two views which are essentially the "loading" view and the "results" view. The loading view is visible and the results are invisible until an asynchronous/threaded call completes, at which point the visibilities are intended to reverse.
Here is an excerpt of the relevant XML:
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center">
<TextView
android:id="#+id/loading"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:text="#string/loading" />
<LinearLayout
android:id="#+id/results"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:visibility="invisible">
<!-- result contents -->
</LinearLayout>
</LinearLayout>
Here is the code I'm using to swap visibilities:
findViewById(R.id.results).setVisibility(View.VISIBLE);
findViewById(R.id.loading).setVisibility(View.INVISIBLE);
Unfortunately, the result of these calls appears to hide the loading view, but not show the results.
I'm thinking that even though the loading view is invisible, its area is still consuming the portion of the screen needed for the results layout to be displayed, but that's just a guess. Any help would be appreciated!
Please use
findViewById(R.id.results).setVisibility(View.VISIBLE);
findViewById(R.id.loading).setVisibility(View.GONE);

Categories

Resources