Floating action button morph - android

I want to make this, but I didn't find any tuts or anything how to make it. (It's called Morph on google website) Can anybody tell me how or send some reference pls?
EDIT:
I want to set the layout from gone to visible... Don't you know when I should do shape.setVisibility(View.VISIBLE)? I tried but animation won't start until second click on button. (On first click layout is just set visible without animation)
Fragment layout:
<EditText
android:id="#+id/editText"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="true"
android:gravity="top"
android:padding="15dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="#+id/circle"
android:visibility="gone">
</LinearLayout>
<ImageButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:background="#color/transparent"
android:contentDescription="share"
android:padding="15dp"
android:src="#drawable/ic_share_55x55px" />
Fragment:
ImageButton fab = (ImageButton) view.findViewById(R.id.share);
fab.setOnClickListener(new View.OnClickListener() {
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
#Override
public void onClick(View view) {
LinearLayout shape = (LinearLayout) getActivity().findViewById(R.id.circle);
// Create a reveal {#link Animator} that starts clipping the view from
// the top left corner until the whole view is covered.
Animator animator = ViewAnimationUtils.createCircularReveal(
shape,
shape.getWidth() - 130,
shape.getHeight()- 130,
0,
(float) Math.hypot(shape.getWidth(), shape.getHeight()));
// Set a natural ease-in/ease-out interpolator.
animator.setInterpolator(new AccelerateDecelerateInterpolator());
animator.setDuration(400);
// Finally start the animation
animator.start();
}
});

Your would need to Animate a view (in this example a LinearLayout). Set the x and y values of the createCircularReveal to the fab button.
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
LinearLayout shape = (LinearLayout) rootView.findViewById(R.id.circle);
// Create a reveal {#link Animator} that starts clipping the view from
// the top left corner until the whole view is covered.
Animator animator = ViewAnimationUtils.createCircularReveal(
shape,
0,
0,
0,
(float) Math.hypot(shape.getWidth(), shape.getHeight()));
// Set a natural ease-in/ease-out interpolator.
animator.setInterpolator(new AccelerateDecelerateInterpolator());
// Finally start the animation
animator.start();
}
});
This is the information on the createCircleReveal
createCircularReveal(View view,
int centerX, int centerY, float startRadius, float endRadius);
Example Project:
https://github.com/googlesamples/android-RevealEffectBasic/
UPDATE
Instead of setting the view to GONE, set it to INVISIBLE. Also make the view setEnabled(false) to prevent it from being touched etc.
LinearLayout shape;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.reveal_effect_basic, container, false);
shape = (LinearLayout) view.findViewById(R.id.circle);
shape.setVisibility(View.INVISIBLE);
shape.setEnabled(false);
ImageButton fab = (ImageButton) view.findViewById(R.id.share);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Animator animator = ViewAnimationUtils.createCircularReveal(
shape,
shape.getWidth() - 130,
shape.getHeight() - 130,
0,
(float) Math.hypot(shape.getWidth(), shape.getHeight()));
shape.setVisibility(View.VISIBLE);
animator.setInterpolator(new AccelerateDecelerateInterpolator());
if (shape.getVisibility() == View.VISIBLE) {
animator.setDuration(400);
animator.start();
shape.setEnabled(true);
}
}
});

Related

Slide animation when guideline percent changes

I have a view that looks like this:
https://i.stack.imgur.com/zKe01.png
When clicked, I want to animate the grey background color so that it slides from the right side to 50% of its initial width:
https://i.stack.imgur.com/s96BX.png
Here is the relevant portion of the layout xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/content_view"
android:layout_width="match_parent"
android:layout_height="44dp"
android:layout_marginBottom="4dp">
<androidx.constraintlayout.widget.Guideline
android:id="#+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="1.0"/>
<View
android:id="#+id/background"
android:layout_width="0dp"
android:layout_height="match_parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="#+id/guideline"
android:background="#drawable/background" />
</androidx.constraintlayout.widget.ConstraintLayout>
I've tried the following:
contentView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ConstraintSet constraintSet = new ConstraintSet();
constraintSet.clone(contentView);
constraintSet.setGuidelinePercent(guideline.getId(), 0.5f);
TransitionManager.beginDelayedTransition(contentView);
constraintSet.applyTo(contentView);
}
});
But instead of the background color sliding from the right to the left (100% to 50%), it sort of just cross-fades.
What am I doing wrong? How would I change my code so the animation SLIDES the background color when the guideline percent changes?
You can use android.animation.ValueAnimator to change the percentage value of your guideline inside your constraintLayout, the code would be like this:
contentView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// initialize your guideline
// Guideline guideline = findViewById ....
ValueAnimator valueAnimator = ValueAnimator.ofFloat(1.0f, 0.5f);
// set duration
valueAnimator.setDuration(1000);
// set interpolator and updateListener to get the animated value
valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
// update guideline percent value through LayoutParams
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
ConstraintLayout.LayoutParams lp = (ConstraintLayout.LayoutParams) guideline.getLayoutParams();
// get the float value
lp.guidePercent = (Float) animation.getAnimatedValue();
// update layout params
guideline.setLayoutParams(lp);
}
});
valueAnimator.start();
}
});

Circular Reveal Animation not working in the first call

I need to implement a circular reveal animation after the transition between 2 fragments is finished so that the ImageButton (android:id="#+id/update_profile_pic") will be revealed with a nice animation
The problem is that it doesn't work as it should:
setEnterSharedElementCallback(new SharedElementCallback() {
Handler handler = new Handler();
#Override
public void onSharedElementEnd(List<String> sharedElementNames,
List<View> sharedElements,
List<View> sharedElementSnapshots) {
handler.postDelayed(new Runnable() {
#Override
public void run() {
update_profile_pic.setVisibility(View.GONE);
// get the center for the clipping circle
int cx = update_profile_pic.getWidth() / 2;
int cy = update_profile_pic.getHeight() / 2;
// get the final radius for the clipping circle
float finalRadius = (float) Math.hypot(cx, cy);
// create the animator for this view (the start radius is zero)
Animator anim = ViewAnimationUtils.createCircularReveal(update_profile_pic, cx, cy, 0f, finalRadius);
// make the view visible and start the animation
update_profile_pic.setVisibility(View.VISIBLE);
anim.start();
}
}, 600);
}
});
When I try this animation in a button click listener, the button needs to be clicked twice to make the animation work
The layout is like this:
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_simple_two"
android:layout_gravity="center_horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:context=".FragmentB"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.mikhaellopez.circularimageview.CircularImageView
android:id="#+id/profile_picture"
android:clickable="false"
android:src="#drawable/roni"
app:civ_border_color="#color/fadedText"
app:civ_border_width="0.1dp"
android:layout_width="260dp"
android:layout_height="260dp"
android:layout_margin="18dp"
android:transitionName="#string/simple_fragment_transition"/>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="16dp"
android:scaleType="centerInside"
android:elevation="3dp"
android:layout_margin="26dp"
android:id="#+id/update_profile_pic"
android:src="#drawable/ic_menu_camera"
android:background="#drawable/round_button"
android:backgroundTint="#color/colorAccent"
app:layout_anchor="#id/profile_picture"
app:layout_anchorGravity="bottom|right|end"
android:visibility="gone"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Any help?
try to set visibility of your ImageButton to invisible instead of gone initially.

Push above view up while animating slide up another view

I have following view inside my layout
<RelativeLayout
android:id="#+id/wrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<LinearLayout
android:id="#+id/header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true">
<!-- some child views here -->
</LinearLayout>
<LinearLayout
android:id="#+id/footer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/header"
android:visibility="gone">
<!-- some other child views here -->
</LinearLayout>
</RelativeLayout>
The wrapper RelativeLayout is aligned to bottom of its parent. And initialy footer view is not displayed (View.GONE). When header view is tapped, then footer should be shown to user with slide up animation from bottom of screen and when user taps again footer should be slide down to bottom. When i start an slide up animation on footer view, it does not push header view simultaneously with animation. If i first set footer view visibility to View.INVISIBLE first and then start animation, header view is pushed up immediately (not together with animation or footer view), and footer view comes with animation.
Here is the code to call animation
footer.setVisibility(View.INVISIBLE);
Animation animation = AnimationUtils.loadAnimation(activity, R.anim.slide_up_from_bottom);
animation.setDuration(animDuration);
footer.startAnimation(animation);
footer.postDelayed(new Runnable() {
#Override
public void run()
{
footer.setVisibility(View.VISIBLE);
}
}, animDuration);
and this is the animation file content:
How can i make this animation to push header view, while footer view sliding up?
Hope i made myself clear. All i want is both views moves up/down together.
If i apply animation to wrapper view then it slides up from bottom (not from current location).
If you want your header to push along with footer animation, you can do it manually as follows
public class MainActivity extends Activity {
private LinearLayout header,footer;
private RelativeLayout wrapper;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
header = (LinearLayout) findViewById(R.id.header);
footer = (LinearLayout) findViewById(R.id.footer);
wrapper = (RelativeLayout) findViewById(R.id.wrapper);
header.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(footer.getVisibility() == View.VISIBLE){
int footerHeight = footer.getMeasuredHeight();
float initialWrapperY = wrapper.getY();
ObjectAnimator oa=ObjectAnimator.ofFloat(wrapper, "y", initialWrapperY,initialWrapperY+footerHeight);
oa.setDuration(400);
oa.start();
oa.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(android.animation.Animator animation) {
footer.setVisibility(View.INVISIBLE);
};
});
}
else{
final float initialWrapperY = wrapper.getY();
footer.setVisibility(View.VISIBLE);
wrapper.setY(initialWrapperY);
ViewTreeObserver vto=wrapper.getViewTreeObserver();
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
#Override
public boolean onPreDraw() {
wrapper.getViewTreeObserver().removeOnPreDrawListener(this);
final int footerHeight = footer.getMeasuredHeight();
ObjectAnimator oa=ObjectAnimator.ofFloat(wrapper, "y", initialWrapperY,(initialWrapperY-footerHeight));
oa.setDuration(400);
oa.start();
return true;
}
});
}
}
});
}
}

Updating view position after animation

I'm working on getting a animation to work. I'm moving a search bar from the middle of the screen to the top of the screen. The animation works fine, but once it's moved I can't interact with anything. I've updated the position but can't interact with it regardless. Here's what I've got so far:
private void moveSearchToTop()
{
FrameLayout root = (FrameLayout) findViewById( R.id.rootLayout );
DisplayMetrics dm = new DisplayMetrics();
this.getWindowManager().getDefaultDisplay().getMetrics( dm );
statusBarOffset = dm.heightPixels - root.getMeasuredHeight();
int originalPos[] = new int[2];
mSearchBar.getLocationOnScreen( originalPos );
search_top = statusBarOffset - originalPos[1];
TranslateAnimation anim = new TranslateAnimation( 0, 0, 0, search_top);
anim.setDuration(500);
anim.setFillAfter(true);
anim.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
mSearchBar.layout(0, search_top, 0, mSearchBar.getHeight() + search_top);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
mSearchBar.startAnimation(anim);
}
and here's what the view looks like in xml:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:id="#+id/search_bar"
android:background="#android:drawable/dialog_holo_light_frame">
<ImageView
android:id="#+id/search_icon"
android:layout_width="wrap_content"
android:onClick="onSearchClick"
android:layout_height="25dp"
android:layout_gravity="center_vertical"
android:src="#drawable/search"/>
<EditText
android:id="#+id/search_field"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:singleLine="true"
android:hint="Search"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="25dp"
android:layout_gravity="center_vertical"
android:src="#drawable/camera"/>
</LinearLayout>
Do I need to update the position of all of the child elements too? Thanks for a push in the right position.
No, you won't need to modify the child views. They will go where the search bar goes.
It looks to me like you are using your search_top variable both as a delta (for the TranslateAnimation constructor) and as a position within its parent (in the call to layout). It's really a delta, so the call to layout is incorrect.
Is the parent of your searchBar the "root" FrameLayout? If so, then you just want to use 0 as the new y coordinate in the call to layout. Also, you are using 0 as the right coordinate, which means that it has no width after the animation. This call would position your search bar at the upper-left edge of its parent, and maintain its current width and height:
mSearchBar.layout(0, 0, mSearchBar.getWidth(), mSearchBar.getHeight());
I also would recommend that you do not use screen position. It's safer to just set the position of views within parent views. For example, if the search bar's parent really is root, then you could get the delta with:
search_top = - mSearchBar.getTop();

Android: setting leftMargin property to a button automatically resizes it

I have a simple button in my layout. Setting leftMargin to the view actually showing different results.
my_layout.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="#+id/left_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="hello pandora"/>
</RelativeLayout>
In my activity, I'm setting the leftMargin property to the Button.
Button leftBtn = (Button) findViewById(R.id.left_btn);
LayoutParams params = (LayoutParams) leftBtn.getLayoutParams();
params.leftMargin = 550;
If I set leftMargin as negative value or 0, its working fine, but If I set the value greater than the width of screen, it just resizing/compressing the button. I am expecting the button to go out of bounds like negative value.
I am expecting the button in the 3rd image to go out of bounds like the button in 1st image.
Please don't say to set the button layout_alignParentRight="true" in layout and rightMargin = -50in activity(this works) because I want to move the button from left to right.
I assume assigning a specific width larger than the screen size (eg. 1000 dp) to the parent RelativeLayout should solve your problem.
Also why do you want to make out-of-screen UI elements? What is the desired behaviour? Perhaps a transition animation would be better?
EDIT
I've tried the animation + storing the measured width of the Button. It seems to work.
Can you try this on GB?
MainActivity.java
public class MainActivity extends Activity {
final Context context = this;
Button mButton;
int mButtonWidth; // Measured width of Button
int amountToMove; // Amount to move the button in the x direction
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
amountToMove = 600;
mButton = (Button) findViewById(R.id.button);
// Measure Button's width
mButton.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
mButtonWidth = mButton.getMeasuredWidth();
// Simple onClick listener showing a Toast
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(context,"Hello Pandora clicked!",Toast.LENGTH_SHORT).show();
}
});
// Onclick listener for the other button
Button toggle = (Button) findViewById(R.id.toggle);
toggle.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Animate the other button
TranslateAnimation a = new TranslateAnimation(0, amountToMove, 0, 0);
a.setDuration(1000);
// Finalize movement when animation ends
a.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationEnd(Animation animation) {
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)mButton.getLayoutParams();
// Restore measured width and change left margin
lp.width = mButtonWidth;
lp.leftMargin = lp.leftMargin + amountToMove;
mButton.setLayoutParams(lp);
amountToMove = -amountToMove;
}
#Override
public void onAnimationStart(Animation animation) { /* Do nothing */ }
#Override
public void onAnimationRepeat(Animation animation) { /* Do nothing */ }
});
mButton.startAnimation(a);
}
});
}
}
activity_main.xml
<LinearLayout 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"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello Pandora"
android:id="#+id/button" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Move the other button"
android:id="#+id/toggle"/>
</LinearLayout>
EDIT 2
It works on a GB Emulator too (the Button gets clipped, is clickable).
u can use max line=1 to show complete text in one line on button when you use leftMargin = 550;
try this
<Button
android:id="#+id/left_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:maxLines="1"
android:text="hello pandora"/>
Hello Edit your button property like this,
android:layout_gravity="center_horizontal"
android:singleLine="true"
and change parent layout to frameLayout

Categories

Resources