I want to make a drop down menu, like a status menu, that is hidden when the activity starts, and when it's pressed or slid it opens like the image below..
http://i.stack.imgur.com/jeq5z.png
My layout currently has a RelativeLayout for the top bar and a ScrollView for the text.. between those, i'd like to put the menu..
I'm not doing this app on phonegap or anything like that, just java and xml..
Thanks in advance
Edit:
Thank you all for your help! I end up doing a FrameLayout that was set off the screen with the translationY and then, when clicked, just slide up and down.. Here's the snipped.. I'll just leave it here in case someone else needs it.
on layout.xml
<FrameLayout
android:id="#+id/layout_FrameLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#00ffffff" >
<!-- stuf -->
</FrameLayout>
on activity.java
private FrameLayout statusDrawer = null;
private int statusDrawerHeight; // height of the FrameLayout (generated automatically)
private int statusDrawerDragButtonHeight = 30 + 5; //height of the DragButton + height of the border
private boolean statusDrawerOpened = false;
private int statusDrawerDuration = 750; //time in milliseconds
private TimeInterpolator interpolator = null; //type of animation see#developer.android.com/reference/android/animation/TimeInterpolator.html
#Override
protected void onCreated(Bundle savedInstanceState){
statusDrawer = (FrameLayout) findViewById(R.id.layout_FrameLayout);
interpolator = new AccelerateDecelerateInterpolator();
statusDrawer.post(new Runnable() {
#Override
public void run() {
statusDrawerHeight = statusDrawer.getHeight();
statusDrawer.setTranslationY(-statusDrawerHeight+statusDrawerDragButtonHeight);
}
});
statusDrawer.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v){
if(statusDrawerOpened) {
statusDrawer.animate()
.translationY(-statusDrawerHeight+statusDrawerDragButtonHeight)
.setDuration(statusDrawerDuration)
.setInterpolator(interpolator)
.start();
} else {
statusDrawer.animate()
.translationY(0)
.setDuration(statusDrawerDuration)
.setInterpolator(interpolator)
.start();
}
statusDrawerOpened = !statusDrawerOpened;
}
});
}
Use a FrameLayout as the root layout. Add the drop menu layout as in the right side of your picture. Call
menuView.setTranslationY(-view.getHeight);
on this view to initially hide the drop down menu when the activity is started. Make sure menuView only refers to the drop down view part without the small tab button. When the user touches the tab animate translationY to 0 so that the layout will slide down
ObjectAnimator.ofFloat(dropDownView, "translationY", -view.getHeight, 0).setDuration(200).start();
whereby dropDownView refers to the complete drop down menu.
Using ObjectAnimator requires API level 11. If you need to support older API levels, use http://developer.android.com/reference/android/view/animation/TranslateAnimation.html (which has some down sides).
If you instead want add a sliding effect, e.g. the sliding menu is moving with together with the finger, install a OnTouchListener:
dropDownTab.setOnTouchListener(new OnTouchListener() {
public void onTouch(View v, MotionEvent e) {
// Make the drop down menu finger follow the finger position.
// Use again dropDownView.setTranslationY(...) to move the view.
// If the drop down menu has been dragged a certain distance, make it move out by itself using the animation as above.
}
});
Related
I am using a Github library (https://github.com/oguzbilgener/CircularFloatingActionMenu) to create a circular floating action menu programmatically. Using drawables I have added a menu and an exit icon to the floating action menu and I want to remove the square border around the menu and exit icons that appear when the menu is clicked. I have tried things like programmatically setting the background of the button to be null or changing it's 'alpha' value, neither of which has the desired effect.
There are other questions posted asking this but they are all creating the menu/button using XML while I'm doing it programmatically using Java. Is there any way to remove the border (and if possible fill the whole menu button with the icons rather than have it enclosed inside)? Below I have inserted the code I'm using from the library for convenience:
// Create our Floating Action Button
final ImageView fabIconNew = new ImageView(getActivity());
/* Set the icon in the center of the Floating Action Button
Old Deprecated way to get drawable -> getResources().getDrawable(R.drawable.ic_action_new_light)
Instead, use -> getApplicationContext(), R.drawable.ic_action_new_light)
*/
fabIconNew.setImageDrawable(ContextCompat.getDrawable(getActivity().getApplicationContext(), R.drawable.menu_icon));
final FloatingActionButton rightLowerButton = new FloatingActionButton.Builder(getActivity())
.setContentView(fabIconNew)
.setPosition(FloatingActionButton.POSITION_BOTTOM_RIGHT)
.build();
// Create your menu items which are also Floating Action Buttons
SubActionButton.Builder rLSubBuilder = new SubActionButton.Builder(getActivity());
// Create an image view for each menu item
ImageView menuOption1 = new ImageView(getActivity());
ImageView menuOption2 = new ImageView(getActivity());
// Set the ico/*rea*/n for each menu item
menuOption1.setImageDrawable(ContextCompat.getDrawable(getActivity().getApplicationContext(), R.drawable.button_sub_action));
menuOption2.setImageDrawable(ContextCompat.getDrawable(getActivity().getApplicationContext(), R.drawable.button_sub_action_selector));
// Build the menu with default options: 90 degrees, 72dp radius.
// Set 4 default SubActionButtons
final FloatingActionMenu rightLowerMenu = new FloatingActionMenu.Builder(getActivity())
.addSubActionView(rLSubBuilder.setContentView(menuOption1).build())
.addSubActionView(rLSubBuilder.setContentView(menuOption2).build())
.attachTo(rightLowerButton)
//.setStartAngle(360)
.build();
// Listen for menu open and close events to animate the button content view
rightLowerMenu.setStateChangeListener(new FloatingActionMenu.MenuStateChangeListener() {
#Override
public void onMenuOpened(FloatingActionMenu menu) {
// Rotate the icon of rightLowerButton 45 degrees clockwise
// fabIconNew.setRotation(0);
fabIconNew.setImageDrawable(ContextCompat.getDrawable(getActivity().getApplicationContext(), R.drawable.exit_icon));
PropertyValuesHolder pvhR = PropertyValuesHolder.ofFloat(View.ROTATION, 0);
ObjectAnimator animation = ObjectAnimator.ofPropertyValuesHolder(fabIconNew, pvhR);
animation.start();
}
#Override
public void onMenuClosed(FloatingActionMenu menu) {
// Rotate the icon of rightLowerButton 45 degrees counter-clockwise
// fabIconNew.setRotation(45);
fabIconNew.setImageDrawable(ContextCompat.getDrawable(getActivity().getApplicationContext(), R.drawable.menu_icon));
PropertyValuesHolder pvhR = PropertyValuesHolder.ofFloat(View.ROTATION, 0);
ObjectAnimator animation = ObjectAnimator.ofPropertyValuesHolder(fabIconNew, pvhR);
animation.start();
}
});
// OnClickListeners for each menu item
menuOption1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getActivity().getApplicationContext(), "Option 1", Toast.LENGTH_SHORT).show();
/*
Could also go to an Intent or perform whatever action you want.
To go to another Activity, you would use something like:
Intent goToActivity = new Intent(getApplicationContext(), Name_Of_Activity.class)
startActivity(goToActivity);
*/
}
});
menuOption2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getActivity().getApplicationContext(), "Option 2", Toast.LENGTH_SHORT).show();
NavHostFragment.findNavController(FirstFragment.this)
.navigate(R.id.action_FirstFragment_to_SecondFragment);
rightLowerMenu.close(true);
rightLowerButton.setVisibility(View.GONE);
}
});
Can you create different actions for clicking on the same ImageView but different parts? Say I have an ImageView and I want for it to act differently if I click on the top of the ImageView and differently if I click on the middle part of the ImageView . Can I achieve this in android
The best way is to add an OnTouchListener to the view and handle click event by yourself related to the touch coordinate.
But if you need an easy way which I don't suggest because it can lead to performance issue you can add transparent views on top of your ImageView and add different OnClickListener for them.
if you have fixed sections in your imageview you can use a frame layout and add 3(for example) transparent views on your imageview and then set click listeners on those views.
but if you have dynamic sections you can handle it by combining onTouchListener and onClickListener, for example :
// just store the touch X,Y coordinates
View.OnTouchListener touchListener = new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// save the X,Y coordinates
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
lastTouchDownXY[0] = event.getX();
lastTouchDownXY[1] = event.getY();
}
// let the touch event pass on to whoever needs it
return false;
}
};
View.OnClickListener clickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
// retrieve the stored coordinates
float x = lastTouchDownXY[0];
float y = lastTouchDownXY[1];
// use the coordinates for whatever or check the clickable areas
Log.i("TAG", "onLongClick: x = " + x + ", y = " + y);
}
};
I think the best way for this is that you declare a frameLayout as parent view then you can declare views on your imageView then clicking each view will perform what you want.
I referenced the other questions but couldn't find a solution, also I am fairly new to programming.
So I implemented a TranslateAnimation on my ImageView but once the animation ends it returns to its original position. I used Override onAnimationEnd but that doesn't seem to work. Can someone figure out what should I be doing?
public class PackAnimation extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pack_animation);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
String s = getIntent().getStringExtra("CHOICE");
final ImageView pandya = (ImageView) findViewById(R.id.pandya);
final int amountToMoveRight = 600;
final int amountToMoveDown = 0;
TranslateAnimation anim = new TranslateAnimation(0, amountToMoveRight, 0, amountToMoveDown);
anim.setDuration(100);
anim.setAnimationListener(new TranslateAnimation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) { }
#Override
public void onAnimationRepeat(Animation animation) { }
#Override
public void onAnimationEnd(Animation animation)
{
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams)pandya.getLayoutParams();
params.topMargin += amountToMoveDown;
params.leftMargin += amountToMoveRight;
pandya.setLayoutParams(params);
}
});
pandya.startAnimation(anim);
}
}
You can use anim.setFillAfter(true) to the TranslateAnimation and get the button stay at the new position, but the button clicks will not work at the new position.
So use ViewPropertyAnimator or ObjectAnimator. These are property animation and will change the position of the View, whereas the TranslateAnimation is View animation and will not change the actual property of the View.
For example, using ViewPropertyAnimator:
pandya.animate()
.translationX(amountToMoveRight)
.translationY(amountToMoveDown);
Refer the blog for more info:
Finally, the previous animations changed the visual appearance of the
target objects... but they didn't actually change the objects
themselves. You may have run into this problem. Let's say you want to
move a Button from one side of the screen to the other. You can use a
TranslateAnimation to do so, and the button will happily glide along
to the other side of the screen. And when the animation is done, it
will gladly snap back into its original location. So you find the
setFillAfter(true) method on Animation and try it again. This time the
button stays in place at the location to which it was animated. And
you can verify that by clicking on it - Hey! How come the button isn't
clicking? The problem is that the animation changes where the button
is drawn, but not where the button physically exists within the
container. If you want to click on the button, you'll have to click
the location that it used to live in. Or, as a more effective solution
(and one just a tad more useful to your users), you'll have to write
your code to actually change the location of the button in the layout
when the animation finishes.
Use anim.setFillAfter(true); and it will remain on the final position after the end of animation.
I am developing an app in Android. I am using a flow to take information form the user. To build the flow I am using few fragments. There are five steps and I am using five fragments. I am using another fragment to show the previous records he saved using list view. In my activity I am using a button named Expand. The button Expand is used to show the previous records using fragment. When the user clicks on the button Expand the fragment will take place and the Expand button text will be set to Hide. When the button text is Hide, if the user clicks on the button again the fragment will be removed from the stack and the previous fragment added to the back stack will be shown.
For example let us assume that I have five fragments named FragmentA, FragmentB, FragmentC, FragmentD, FragmentE and another fragment named ProjectRowsFragment which will be used to show the records previously saved in a ListView on the click event of the button named Expand.
Let us assume that the user is in FragmentC and he clicked on the Expand button. What will happen is that FragmentC will be replaced and ProjectRowsFragment will be added. If the user clicks on the button again the ProjectRowsFragment will be replaced and the FragmentC will come in from back stack. If it was FragmentD then it will be replaced and ProjectRowsFragment will be added and if user clicks on the button again ProjectRowsFragment will be replaced and FragmentD will come in from back stack.
I have done with the transactions.
What I want is that I want animation to be added while the ProjectRowsFragment (The fragment I am using to show the records) is shown and replaced. When it is shown it will slide down from the top and then when it is removed from the back stack it will slide up.
After trying a lot I accomplished the slide down effect, but how can I get the slide up animation.
Here is my codes.
fragmentManager = getFragmentManager();
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.setCustomAnimations(R.animator.slide_in_from_top, 0, R.animator.slide_in_from_bottom, 0);
fragmentTransaction.replace(R.id.fragment_container, ProjectRowsFragment.newInstance(this.projectId));
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
projectRowsExpanded = true;
slide_in_from_top.xml file is
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true" >
<objectAnimator
android:duration="600"
android:propertyName="y"
android:valueFrom="-1280"
android:valueTo="0"
android:valueType="floatType" />
</set>
Here i have three images to visualize
Initial Step
If the user clicks on the button indicated a list will be placed.
If the user clicks again in the indicated button.
Instead of applying custom animations to fragment, you can add animation to your FrameLayout, by passing your fragment container view to following functions to expand and collapse:
FrameLayout v = (FrameLayout) findViewById(R.id.fragment_container);
expand(v); //To Expand
collapse(v); //To Collapse
public static void expand(final View v) {
v.measure(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
final int targetHeight = v.getMeasuredHeight();
v.getLayoutParams().height = 1;
v.setVisibility(View.VISIBLE);
Animation a = new Animation() {
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
v.getLayoutParams().height = interpolatedTime == 1
? ViewGroup.LayoutParams.WRAP_CONTENT
: (int) (targetHeight * interpolatedTime);
v.requestLayout();
}
#Override
public boolean willChangeBounds() {
return true;
}
};
a.setDuration((int) (targetHeight / v.getContext().getResources().getDisplayMetrics().density));
v.startAnimation(a);
}
public static void collapse(final View v) {
final int initialHeight = v.getMeasuredHeight();
Animation a = new Animation() {
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
if (interpolatedTime == 1) {
v.setVisibility(View.GONE);
} else {
v.getLayoutParams().height = initialHeight - (int) (initialHeight * interpolatedTime);
v.requestLayout();
}
}
#Override
public boolean willChangeBounds() {
return true;
}
};
a.setDuration((int) (initialHeight / v.getContext().getResources().getDisplayMetrics().density));
v.startAnimation(a);
}
I'm trying to do an animation that goes like this:
The context:
I have two EditText's I need that when you click over one, the another one come out from behind the first one. Here you have some pictures to get a image of what I want.
To do this obviously I need a TranslateAnimation in order to move the second EditText from behind the first one.
My approach:
The first thing that I could thought was in use a FrameLayout put the EditText one over another, and then in the onTouch event of the first one do a TranslateAnimation on the second one. The problem with this is that if I have the FrameLayout height in wrap_content then the animation will be invisible to the user. And if I change on runtime the height of the FrameLayout I will leave a void below the first EditText as you can see in this picture:
The second solution that I thought was add one AnimationListener to the TranslateAnimation and in the onAnimationStart method change the height of the FrameLayout. But the problem with this is that the height of the FrameLayout changes too abruptly. I want keep the animation smooth.
My question:
How can I get a smooth animation of the second EditText from behind the first one, changing the height of the FrameLayout as the second EditText moves down?
Thanks!
Update:
I changed the FrameLayout by a RelativeLayout I searched and there's no difference for this case. I tried scale this RelativeLayout that contains both of the EditText with an AnimationScale in order to display the animation smoothly, but didn't work. Here is my code:
protected void expanse() {
Log.d("Accordion", "expandAccordion");
//Translate the top of the second EditText to its bottom
TranslateAnimation translateSecond = new TranslateAnimation(second.getLeft(), second.getLeft(),
second.getTop(), second.getBottom());
translateSecond.setDuration(1000);
//Scale the relative layout to show the both of them
ScaleAnimation scaleContainer = new ScaleAnimation(container.getLeft(), container.getLeft(),
container.getTop(), second.getBottom());
scaleContainer.setDuration(1000);
//At the end of the scaling, change the height of the relative layout
scaleContainer.setAnimationListener(new AnimationListenerAdapter() {
#Override
public void onAnimationEnd(Animation animation) {
RelativeLayout.LayoutParams params = (LayoutParams) container.getLayoutParams();
params.height = second.getBottom();
container.setLayoutParams(params);
super.onAnimationEnd(animation);
}
});
container.startAnimation(scaleContainer);
second.startAnimation(translateSecond);
}
BTW I can guarantee that if I hardcode some large height like 350dp, the animation is displayed correctly.
UPDATE:
I tried moving both, the second EditText and the layout below. This is the code. BTW for another reasons I changed the ListView by a custom ViewPager, this doesn't change anything.
public class MainActivity extends FragmentActivity {
private EditText first;
private EditText second;
private HoboViewPager pager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pager = (HoboViewPager) findViewById(R.id.pager);
pager.setPageTransformer(true, new RotationPageTransformer());
pager.setAdapter(new SampleAdapter(this, getSupportFragmentManager()));
first = (EditText) findViewById(R.id.location_search_field);
second = (EditText) findViewById(R.id.term_search_field);
first.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
expanseSecondField();
return true;
}
});
}
protected void expanseSecondField() {
TranslateAnimation translateSecondField = new TranslateAnimation(second.getLeft(), second.getLeft(),
second.getTop(), second.getBottom());
translateSecondField.setFillAfter(true);
translateSecondField.setDuration(1000);
TranslateAnimation translateContainer = new TranslateAnimation(pager.getLeft(), pager.getLeft(),
pager.getTop(), pager.getTop() + second.getBottom());
translateContainer.setFillAfter(true);
translateContainer.setDuration(1000);
pager.startAnimation(translateContainer);
second.startAnimation(translateSecondField);
}
}
This didn't work because the TranslateAnimation of the container is executed immediately. The result is the same that when I was trying to change the size of the container at the end of the animation.
How use the 2nd option & try performing two translate animations in tandem: 1 on the EditText, then one on the FrameLayout? Give them both the same exact deltas and duration. This way, the FrameLayout will move down smoothly, then at the end of the animation, change the height of the FrameLayout.
Hope this helps :)