Pull down view (menu) from ActionBar - android

I need to implement a pull-down view that has a "handle" in right-most part of the ActionBar. It should be full width and open with an animation when the handle is clicked, and additionally the handle itself should be draggable. minSdkVersion is 8
Regarding the pull-down functionality itself, I found that SlidingDrawer isn't going to fit the bill, since it has been deprecated as of API v17, and it can only be opened from bottom to top. The control SlidingTray seems to overcome that issue. I haven't tested it thoroughly but but it seems to work as expected.
Now to the main issue. Is it even possible to display the view in such a manner? I have tried to set a custom view for the ActionBar, where the inflated XML looks something like this:
<?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="wrap_content" >
<my.package.drawer.SlidingTray
android:id="#+id/drawer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:content="#+id/content"
android:handle="#+id/handle" >
<ImageView
android:id="#+id/handle"
android:layout_width="88dp"
android:layout_height="44dp"
android:src="#drawable/ic_launcher" />
<Button
android:id="#+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</my.package.drawer.SlidingTray>
</RelativeLayout>
Now, the SlidingTray view itself is functioning as expected when I put it in the activity/fragment layout (can drag the handle and click it to open/close the tray), but when inflating the layout above inside the ActionBar, and upon pressing/dragging the handle, the Tray only moves a few pixels before stopping - it doesn't go beyond the ActionBar bounds. This is the main issue - can the view go beyond the ActionBar itself (over the activity displayed below), and if so - how?

Since no one answered, I'll post how I resolved the issue.
After some inspecting with hierarchyviewer, I saw that the ActionBar was in a LinearLayout and as such, it wouldn't be possible to extend a child of it outside of the ActionBar bounds. So I decided to get the root (decor) view and attach the modified version of SlidingDrawer there. Here is the excerpt:
ViewGroup decor = (ViewGroup) getWindow().getDecorView();
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View drawerContainer = inflater.inflate(R.layout.sliding_drawer, null);
drawer = (SlidingDrawer) drawerContainer.findViewById(R.id.drawer);
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
decor.addView(drawerContainer, params);
Since adding a view this way displays it behind the Status bar, I also added a container view with top padding of 25dp so that the handle and content are displayed beneath it.
Note: if you are using the SlidingMenu library, you need to do this in onPostCreate(), because the library also does this and will place your view behind all of the other content.

Related

Fixed element when using TileView in Android Studio

I am building an activity within Android Studio which uses the TileView library by moagrius to build a layout that can be panned and zoomed, which is all working just fine. I am trying to add an element to the activity which stays fixed at the bottom of the screen and not be affected by the scrolling and zooming of the TileView.
Points to Note:
The TileView and content inside of it are all generated and placed programmatically. It does not use an XML layout.
The element I'm trying to place is an Image. It needs to be in the bottom center of the viewport, and can preferably be reused easily in other activities.
Things I've Tried:
I've tried placing the menu button in its own XML file and tried to use the include attribute on the main XML layout file and inflate that via Java. No luck. The bottom menu is still affected.
I've tried programatically generating the menu button, adding it to a new Relative (tried Linear too) layout, and adding it with parameters to make it sit at the bottom. This got it to appear and stay at the bottom, but it was still affected by zooming and panning.
I've tried using a FrameLayout to add the tileview on top (tried bottom too) of the Relative or Linear layout containing the button, and it was still affected.
I've tried a few other concepts but they didn't work either.
layout.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/res"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
app:theme="#style/Theme.AppCompat">
<include layout="#layout/menu"/>
</RelativeLayout>
menu.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:id="#+id/bottompanel">
<RelativeLayout android:layout_height="match_parent"
android:layout_width="match_parent">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true">
<ImageView
android:id="#+id/imageView3"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#drawable/bottombarclosed"
app:srcCompat="#drawable/bottombarclosed" />
</LinearLayout>
</RelativeLayout>
</FrameLayout>
activity.java
// Initialize TileView, set it's size, and add the detail level (background)
TileView tileView = new TileView(this);
tileView.setSize(5600, 5000);
tileView.addDetailLevel(.15f, "tile-1-1.png", 200, 100);
/*
Generate content for the TileView here.
*/
RelativeLayout rl = new RelativeLayout(this);
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
lp.addRule(RelativeLayout.CENTER_IN_PARENT);
/*
Add the generated content to the Relative Layout for the TileView here.
*/
// Make a new instance of the layout inflator.
LayoutInflater inflater = (LayoutInflater) this.getSystemService(LAYOUT_INFLATER_SERVICE);
// Inflate the bottom menu FrameLayout and save for later.
FrameLayout bm = (FrameLayout) inflater.inflate(R.layout.menu, (ViewGroup) findViewById(R.id.bottompanel));
// Adds the TileView content to the ViewGroup (scaleable, so it can be affected by zooming and panning.)
tileView.addScalingViewGroup(rl);
// Remove the parent from the bottom panel so it can be reassigned. (It crashes without this)
((ViewGroup)bm.getParent()).removeView(bm);
// Add the bottom menu to the tileView without scaling (so it SHOULDN'T be affected by zoom and panning)
tileView.addView(bm);
// Set the content view to display
setContentView(tileView);
Update
I got it to stay in the right position by switching
FrameLayout bm = (FrameLayout) inflater.inflate(R.layout.menu, (ViewGroup) findViewById(R.id.bottompanel));
to
RelativeLayout bm = (RelativeLayout) inflater.inflate(R.layout.menu, (ViewGroup) findViewById(R.id.menulrel)); // menurel is an immediate child of the beforementioned FrameLayout
and by adding the TileView to the RelativeLayout instead of the other way around, and setting the content view to the RelativeLayout (bm). Now the issue is, the menu shows for a second, then is hidden when the TileView updates... Hmmm....
I finally found the answer! I'm just posting it here just in case somebody else stumbles across this issue.
I changed the inflator back to the FrameLayout as it was in the original post.
FrameLayout bm = (FrameLayout) inflater.inflate(R.layout.menu, (ViewGroup) findViewById(R.id.bottompanel));
Then added the tileView to the FrameLayout.
bm.addView(tileView);
Used the full view to locate the Relative Layout container of the menu (parent of the ImageView), then called bringToFront on it.
bm.findViewById(R.id.menurel).bringToFront();
This next step is the MOST IMPORTANT part. You MUST invalidate the RelatieLayout for it to stay present on the screen. Otherwise it fades as the TileView updates and re-renders.
bm.findViewById(R.id.menurel).invalidate();
Then lastly, add set your content view to the new FrameLayout with the other views included.
setContentView(bm);
I hope this helps somebody out in the future!

Android - Padding/Margin Exists but is not set

There is a left horizontal padding that exists in my app that i did not set and can't find out how to remove it, for the image i added a sample image to illustrate the issue. This is what is happening:
And here is the layout for that piece:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="fill_horizontal" >
<ImageView
android:id="#+id/actionBarLogo"
android:layout_width="match_parent"
android:layout_height="20dp"
android:layout_gravity="center"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_centerInParent="true"
android:scaleType="fitXY"
android:src="#drawable/th2" />
</RelativeLayout>
It also happened on my main activity but only by about 5dp which was fine because i added 5dp on the right. But for my action bar It seems like 15dp or so and thats too much off each side. Where would it be coming from?
EDIT
This is how i initialize the actionable
android.support.v7.app.ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayShowTitleEnabled(false);
actionBar.setDisplayUseLogoEnabled(false);
actionBar.setDisplayHomeAsUpEnabled(false);
LayoutInflater mInflater = LayoutInflater.from(this);
View myActionBar = mInflater.inflate(R.layout.menu_custom, null);
android.support.v7.app.ActionBar.LayoutParams layout = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
actionBar.setDisplayShowHomeEnabled(false);
actionBar.setDisplayOptions(actionBar.DISPLAY_SHOW_CUSTOM);
actionBar.setCustomView(myActionBar, layout);
actionBar.setDisplayShowCustomEnabled(true);
EDIT
When I try to add padding/margin to the right, the left padding/margin grows
EDIT
I'm not sure the difference between margin and padding but I think it could be margin instead if that makes a difference
First of all, remove the android:orientation="vertical" (not used in a relative layout), android:layout_gravity="fill_horizontal" (not needed when you have match_parent width),
android:layout_gravity="center" (not used inside a relative layout), android:layout_centerHorizontal and android:layout_centerHorizontal ( android:layout_centerInParent="true" is enough).
Secondly, is this an activity layout? Do you use it directly in 'setContentView()'? Or is it inside a Fragment or inside a custom view? Any level in the view hierarchy could be causing this. You can use the layout editor in Android Studio to find what's causing it (click on the 'Design' tab when looking at the xml file, and then click on the empty padding to see where it belongs). If you can't figure it out from there, you can use the Hierarchy Viewer (http://developer.android.com/tools/debugging/debugging-ui.html) on an emulator and see what's wrong.

ActionBar with custom layout does not occupy full screen width on Android 4.4.2 (KitKat)

I want to display an Action Bar with a custom layout. The custom layout has three ImageViews, one in the centre and the other two on the left & right ends of the action bar. There must be no back button or action items.
Here is what I've used:
android.support.v7.app.ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayShowTitleEnabled(false);
actionBar.setDisplayShowCustomEnabled(true);
actionBar.setDisplayUseLogoEnabled(false);
actionBar.setDisplayShowHomeEnabled(false);
ActionBar.LayoutParams lp = new ActionBar.LayoutParams(ActionBar.LayoutParams.MATCH_PARENT, ActionBar.LayoutParams.MATCH_PARENT);
View actionBarView = LayoutInflater.from(this).inflate(resource, null);
actionBar.setCustomView(actionBarView, lp);
The custom layout is inflated correctly, but does not occupy the full width of the screen. This happens on Android 4.4.2 (KitKat). On Gingerbread, the above arrangement works properly.
I've tried the recommended solutions in the following discussions:
ActionBar - custom view with centered ImageView, Action Items on sides
RelativeLayout/customview doesn't fill tab's width
However the problem remains. There has to be a way to force the layout to occupy the complete screen width.
I am using the Action Bar from the V7 AppCompat library. Does anyone know a way around this ??
EDIT 1:
Here is the XML layout file:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="fill_horizontal"
android:orientation="horizontal">
<ImageView
android:id="#+id/left_icon"
android:background="#drawable/leftbutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:adjustViewBounds="true"
android:scaleType="centerInside"
android:clickable="true"
android:onClick="leftButtonPressed"
android:hapticFeedbackEnabled="true"
/>
<ImageView
android:id="#+id/center_icon"
android:background="#drawable/centertitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:adjustViewBounds="true"
android:scaleType="centerInside"
/>
<ImageView
android:id="#+id/right_icon"
android:background="#drawable/rightbutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:adjustViewBounds="true"
android:scaleType="centerInside"
android:clickable="true"
android:onClick="rightButtonPressed"
android:hapticFeedbackEnabled="true"
/>
</RelativeLayout>
Here is what it looks like on Gingerbread (2.3.5):
As you can see, its inflating correctly. And here's how it looks on Kitkat (4.4.2):
You can see that there's a slight gap on the right and the layout is not occupying the complete width.
I dont believe there's a problem with the layout (its inflating correctly on Android 2.3.5), but I could be wrong. Tell me if I'm crazy.
EDIT 2:
Thanks to Doctoror Drive and this post, I was able to get the result I wanted. I know its a bit strange: why use an Action Bar if you are not going to have any navigation or action items, but this is what I need for my particular problem. I have a TabHost with a stack of sliding Fragments in each tab, and the top LinearLayout (i.e. the Action Bar) needs to change its appearance when different Fragments are displayed.
EDIT 3:
Here are some more links for understanding this further:
https://groups.google.com/forum/#!msg/actionbarsherlock/i8JRUkBJjqk/ZzQV9xaM-lkJ
https://groups.google.com/forum/#!topic/android-developers/FGEi72thLzE
In my case I have solved the issue bypassing the invocation of the LayoutInflater.
So one should simply replace this code:
View actionBarView = LayoutInflater.from(this).inflate(R.layout.custom_actionbar, null);
actionBar.setCustomView(actionBarView, lp);
with this code:
actionBar.setCustomView(R.layout.custom_actionbar);
It's not a gap, it's a menu overflow button to the right. If you look closely you can see three dots button.
You've chosen the wrong theme because you can hardly see it.
Use Theme.Compat.Light.DarkActionBar if your ActionBar is dark and you need the light theme.
On devices that don't have physical menu button (mostly new ones) the menu overflow button is shown.
You can't remove it unless you disable menus.
You can use splitActionBarWhenNarrow uiOptions which will split the ActionBar so that the menu part will be at the bottom one, but that will be only for vertical orientation of medium screens and probably not what you need.
Take a look at the ActionBar Patterns doc and Menus UI doc

Android - Pop up a View on top of another View

Suppose I have a Button like what is in the following:
I want once this button is clicked a ImageView(popup message) appears in the top of this button, something like this:
But I do not know how put a View as an overlay on top of another View, Just I know this can be achieved by FrameLayout . Please suppose I want to embed this capability into the Button (in the other phrases I want to create a custom button with a method called showPopup(...) like Textview's setError(...))
Can any one please help me? Thanks
How about taking a look at the Quick Action Dialog?
It is an old article (We're talking Android 2.2 territory), but should still work for the latest devices and OS.
The example uses a contextual popup with buttons, but should be easily modifiable to just show text or whatever you want. There is an example further in that shows use alongside a button.
You can also use RelativeLayout. you can define as on top of other views that way.
Notice that if you define two views, the last one is stacked on the first
http://developer.android.com/reference/android/widget/RelativeLayout.LayoutParams.html
You can use a popupWindow
PopupWindow popupWindow = new PopupWindow(context);
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View popupView = layoutInflater.inflate(R.layout.popup_view_layout, null);
Imageview popupImage = popupView.findViewById(R.id.imageView);
popupWindow.setContentView(popupView);
popupWindow.setBackgroundDrawable(null);
int popupY = button.getTop() - button.getHeight();
int popupX = button.getLeft();
popupWindow.showAtLocation(keyView, Gravity.NO_GRAVITY, popupX, popupY);
The popup_view_layout can look like this
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/imageView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_weight="1"
android:minWidth="20dp"
android:visibility="gone"
app:srcCompat="#drawable/yourImage" />
</FrameLayout>
For more information click here or check this question's answers.

How to disable any event on a View in Android?

My question is simple: How to disable any event on a View in Android? (including removing its focussability, like I just want it to be there visually but be inexistant on everything else)
And does it work on a whole view tree? (like if I disable events on the root, all the events will be disabled for its children?).
Now, before you say anything I have tried all the following:
setEnabled
setFocusable
setSelected
setClickable
setActivated
And none of these methods appear to work, seriously.
I have tried them directly on a WebView, as well as on the parent layout on everything but I am still able to interact with it.
Any idea?
Thanks!
EDIT#1
The solution that consists in adding a view on top of the view that needs to be disabled doesn't work. Actually, it's still possible to click on the inner view, I have tried with a simple example:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#ff0000">
<Button
android:id="#+id/button"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Click Me!"
/>
</LinearLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00000000"
/>
</FrameLayout>
Here it's still possible to click on the button.
EDIT#2
The reason why I want to do this is related to the following question that I asked weeks ago.
What I have is a ListViewacting as a navigation bar which is underneath a View that holds the content of my app. The problem with this implementation is that when I try to scroll through the ListView when there is a focusable view in the layer on top of it, well the ListView doesn't scroll and instead it's the top view that takes focus (That's the case when there is a
Webview or an EditText etc.).
So yes as mentioned in one of the answers, I can disable any click events on a WebView by overriding setOnTouchListener but the view remains focussed and I think this is the reason why I am still having the same issue with my navigation bar.
Simply put a view on top of your view. You can toggle it on off by setting view.visibility = gone/visible.
<FrameLayout>
<WebView/>
<FrameLayout This view will be on top/>
</FrameLayout>
Edit: Just stumpled upon this link: https://stackoverflow.com/a/3856199/969325
Basically disables all touch event for the webview. Tryed that?
Edit 2 reedit: Try to set the visibility to gone for the the top view below your listview.

Categories

Resources