I have to implement slidable menu in my app. User should be able to show/hide it by tapping on it and move left/right.
To implement this, I`ve created custom SlidableFrameLayout that extends FrameLayout.
By overriding onTouchEvent method I calculate slide position and call
private void setLeftLayout(int left) {
layout(left, getTop(), getRight(), getBottom());
}
to change position for SlidableFrameLayout. Everything works fine, but when I keyboard shows (after focusing EditText), SlidableFrameLayout changes its left value to 0, so if menu was closed, it becomes opened. The same thing happens when I hide the keyboard (generally, it appears in all actions that prevents calling layout methods, I think).
I can not invent how to fix it. Could you help me? If any additional info is required, I`ll attach it. Thanks
I think your issue is related to calling layout directly. When the container view changes size as a result of the keyboard being shown/hidden onMeasure/onLayout will be called with the view's default bounds. In your case I'm guessing the left bound is 0, so layout is being called with 0 for left every time your window resizes.
Instead you probably want to use something like setTranslationX or scrollTo ..
Good luck!
As a result, I changed my logic:
private void setLeftLayout(int left) {
FrameLayout.LayoutParams params = getFrameLayoutParams();
params.leftMargin = left;
params.rightMargin = -left;
requestLayout();
}
In my case, view is a parent of FrameLayout, so I haven`t added any conditions in 1st line of the method. This method works pretty fine.
Related
I'm working on a simple sliding-drawer component. It's a similar to the deprecated SlidingDrawer component.
I'm extending LinearLayout (because that suits what I need to do). I'm not doing anything very fancy, just a handle that you click on to open and close the drawer.
My drawers are contained in a RelativeLayout, and for opening and closing it uses a TranslateAnimation to reposition the view mostly off-screen (with just the handle showing).
The problem I am having is that when the drawer is closed, the child components inside the drawer are responding to touch events at the same screen position as if the drawer was open - even though they are clearly not in that position.
For my right-hand drawer this is particularly bad because the area where you should be able to click the handle does not work, as the event is being handled instead by the component that would be in that position if the drawer were open.
It's really odd. I tried a requestLayout on the drawer in the onAnimationEnd event, but that did not help (in desperation I also tried invalidate and forceLayout - also did not work). I've also tried calling the requestLayout on the parent view.
Any thoughts on what else I could try?
It seems that the weird touch events occur because the view is translated, and for whatever reason this translation is not also applied to the touch region - go figure.
I resolved the problem by clearing the animation (which removes the translation), and then repositioning the view using layout params. Here's a snippet...
#Override
public void onAnimationEnd(Animation a) {
drawer.clearAnimation();
MarginLayoutParams lp = (MarginLayoutParams) drawer.getLayoutParams();
switch (drawer.mAlign) {
case ALIGN_LEFT:
lp.leftMargin = x2;
break;
case ALIGN_RIGHT:
lp.rightMargin = -x;
break;
case ALIGN_TOP:
lp.topMargin = y2;
break;
case ALIGN_BOTTOM:
lp.bottomMargin = -y2;
break;
}
drawer.setLayoutParams(lp);
}
x2 and y2 are the final x and y positions calculated earlier for use in the TranslateAnimation, and then reused here.
Note: On the animation I use setFillAfter(true). You can potentially leave this out, and then you also don't need the clearAnimation() later, but I found that doing this caused a flicker.
I hope this helps others. I'm a bit of a noob to Android, so very happy for any corrections or better ways of handling this!
The pre-3.0 animation system only updates the drawing for a given view, not its actual bounds including touchable areas.
You can use the newer animation properties (you'll need 9OldAndroids if you want to support pre honeycomb), or set the draw view to gone after the animation to slide it off has finished.
You could also try playing with offsetLeftAndRight
I am having great trouble to implement layout swiping UI. Here I show you how each layout works.
My first Layout
My second layout
My third Layout
How it works:
A user can move one page to another by touching the screen and the indicator will move as the layout or page move. But the Sign In and Sign Up button will be fixed in there position. How can I implement this type of UI.
This can be done using a viewFlipper but there is a trick using this whole as a layout.
Use a frameLayout
having your buttons settled down with the gravity set to bottom
Note framelayout works as a stack LIFO things(widgets/layouts) placed at last will superimpose the ones place above them in xml
like for example
//so here view shows s2 and below that s1.....
so in your layout s2 will be the buttons with gravity as bottom
s1 -should be a viewFlipper ...
SWIPPING
swipping can be acheived using the onTouch event
SWIPE LEFT
When the touch down gives a position(x1,y1) and onTouchUp (x2,y2)
check if(x2>x1)
so use viewFlipper.setInAnimation(Animation) viewFlipper.setOutAnimation(Animation)--for the ui that will be gone
SWIPE RIGHT
similarly if (x2<x1)
viewFlipper.setInAnimation(Animation) viewFlipper.setOutAnimation(Animation)
You have used three different layout and increment counter by touching the layout and match to set the layout.
Here is the complete example of ViewFlow please check out the source
https://github.com/pakerfeldt/android-viewflow
and here is another example
http://developer.android.com/shareables/training/Animations.zip
see implementation of screen slide, that is what you exactly want.
The bar moves something like this
Display d= getWindowManager().getDefaultDisplay();
int h=d.getHeight();
int w=d.getWidth();
after getting this h and w , now at every swipe move the bar
where w=screen width calculated with the above method
increments=w/3;
bar_initial_position+=increments;
so it moves..
I found this code to make a sliding menu like facebook app. He (who wrote this code) used a FrameLayout to contain 2 views and used TranslateAnimation to show/hide menu. He used setFillAfter(true) to keep position of view. In onAnimationEnd, he used view.layout(left, top, right, bottom) to ensure that views are in correct position.
I modified this code to use with 3 views: leftView, centerView and rightView (Each view in my case is a LinearLayout) like facebook and found a problem: when activity is show leftView (and a part of centerView), if I click an EditText in leftView and soft keyboard is shown, it return to centerView. Similarly, it happens when I click on an ExpandableListView and Childs is shown.
Can anyone help me please?. Here is [my code](https://dl.dropbox.com/u/38205395/TestErrorSlidingActivity.rar).
Thank you in advance and sorry for my poor English!
Your problem is that the keyboard retriggers the measurement/layout pass of your FrameLayout.
At this point the layout you manually called gets replaced from the FrameLayout original layout.
To avoid this you have 2 ways:
1) Do not use a FrameLayout (define your own extension of the viewgroup or extend FrameLayout overriding all the methods regarding the measurement/layout of the children)
2) Do not call layout after the animation but rather try using setMargin on your children (if possible)
Obviously the best way would be the first one.
Try using android:windowSoftInputMode="adjustNothing" for activity in manifest.
Worked for me :)
I have a ViewFlipper on my main Activity's View. At onCreate I instante Views which are added to ViewFlipper. After that I set displayed child to first one. And when a button is clicked I switch ViewFlipper's display child to second view. Right after calling viewFlipper.setDisplayedChild(1) I need to do some calculations and instantate some objects which are based on width and height of displayed child.
Main problem here is that at first time (second = 1) child is displayed measurement of view is not done yet. So my width and height are 0. If I go back (setDisplayedChild(0)) and than goes back to second child it is ok (width and height are correct).
I have done some research about that behavior of views and found out that there is a method [onMeasure](http://developer.android.com/reference/android/view/View.html#onMeasure(int, int)) which can be overrided and everything can be done here. OK that how it should be. Actually it is but problem is that onMeasure is called 4 times on each view switch. And my findings was that at first and third call width and height are full screen sized. The second and fourth call are proper width and height. Because I have to instantate new objects at that point it is unwise to do it in onMeasure.
Is there any other, proper way of doing it?
Is it possible to force measurement?
Do I really need to show view on screen for measurements?
Regards
Zmeda
Your init-action (based on width and height of displayed child) should be invoked after measuring of ViewFlipper's children, you can achieve that using method post, e.g.:
viewFlipper.setDisplayedChild(1);
viewFlipper.post(new Runnable() {
#Override
public void run() {
Log.d("test", "w: " + viewFlipper.getCurrentView().getWidth());// not 0
//do some calculations and instantate some objects
}
});
I´m having a problem with my Android Project.
I have a screen filling custom View, which displays a canvas. The canvas consists of a background picture and another picture layer, in which can be finger drawn. Additionally, the canvas view can be dragged and pinch-zoomed.
Now I implemented a detection for 'longClicks', i.e. finger down on same region for 1 second. As a result of this gesture, a small menu should pop up over the pointed region. The menu itself should consist of something like a TabHost/TabWidget, i.e. smaller icons on riders on top which reveal separate EditText, Buttons etc. at the lower part of the menu.
Now the question is: How can it technically be done?
1) I played around with TabHost etc., but I think it´s only possible to use when having a TabActivity. Is this correct?
2) Then I searched for a possibility to overlay my main activity with this TabActivity, resulting in that it´s possible, but I couldn´t really control where the overlay Activity was placed, it always started on top left. Is there a possibility to place an Activity somewhere on the screen?
3) Next I discarded my idea with the tabbed menu and searched for a possibility to only overlay my view with another view (and have the possibility to remove it later again). I read, that it´s possible with the ViewManager. But how do I access the ViewManager? Documentation says: http://developer.android.com/reference/android/view/ViewManager.html
call Context.getSystemService().
but via this function, I can only get the WindowManager and not the ViewManager. wtf?
I´m really stuck right now...can somebody give me a hand here?
edit:
I managed the view over view problem by programmatically instanciating a Layout and then handing it in as contentView.
rl = new RelativeLayout(getBaseContext());
rl.addView(cview);
cview.setId(1111);
View overlay = getLayoutInflater().inflate(R.layout.menuoverlay, rl, false);
LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
lp.addRule(RelativeLayout.ALIGN_LEFT, cview.getId());
lp.addRule(RelativeLayout.CENTER_VERTICAL, cview.getId());
rl.addView(overlay, lp);
Now when making the Layout static and by writing some getter/setter methods, I'm now able to control adding and removing of views.
private static rl;
//scroll scroll
public static void addView(View view){
rl.addView(view);
}
1) I played around with TabHost etc., but I think it´s only possible to use when having a TabActivity. Is this correct?
No. For an example of using TabHost without a TabActivity, take a look at Is it realizable on Android?
I finally used PopupWindow now.
http://developer.android.com/reference/android/widget/PopupWindow.html