android pop out (zoom) view on focus - android

I have a group of views, which I want to 'pop-out' of the screen when focused; the sort of thing you might see in a menu on a video game, for example.
To achieve this I am adding an onfocusChaned listener to these views which runs a zoomIn animation on focus, and a zoomOut animation on losing focus:
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
ViewGroup base = (ViewGroup) this.getLayoutInflater().inflate(R.layout.gridtest, null);
ViewGroup container = (ViewGroup) base.getChildAt(0);
this.animZoomIn = AnimationUtils.loadAnimation(this, R.anim.zoomin);
this.animZoomOut = AnimationUtils.loadAnimation(this, R.anim.zoomout);
int x=0;
for(View child:this.getViews(container))
{
ImageView i = (ImageView) child;
i.setPadding(10,10,10,10);
if(x==0) { i.setBackgroundColor(Color.RED); x++; }
else if(x==1) {i.setBackgroundColor(Color.GREEN); x++; }
else if(x==2) {i.setBackgroundColor(Color.BLUE); x=0; }
i.setTag(GridActivity.TAG_EMPTY);
i.setOnFocusChangeListener(new View.OnFocusChangeListener()
{
#Override
public void onFocusChange(View v, boolean hasFocus)
{
if (hasFocus)
{
v.startAnimation(GridActivity.this.animZoomIn);
}
else
{
v.startAnimation(GridActivity.this.animZoomOut);
}
}
});
}
setContentView(base);
}
zoomin.xml:
<scale
xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:anim/accelerate_decelerate_interpolator"
android:zAdjustment="top"
android:fillEnabled="true"
android:fillAfter="true"
android:fromXScale="1.0"
android:toXScale="1.2"
android:fromYScale="1.0"
android:toYScale="1.1"
android:pivotX="50%"
android:pivotY="50%"
android:duration="200" />
zoomout.xml:
<scale
xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:anim/accelerate_decelerate_interpolator"
android:zAdjustment="bottom"
android:fromXScale="1.2"
android:toXScale="1.0"
android:fromYScale="1.1"
android:toYScale="1.0"
android:duration="50" />
This works in so far as the views zoom in and out correctly, however the z-ordering of the views doesn't change... so the 'popped out' view is overlapped by the (smaller) view immediately to its right.
I have tried using v.bringToFront() but that appears to move the focused view to the end of the parent layout, rather than actually re-order it z-wise.
(edit)
This is the effect I'm trying to duplicate

Related

Applying shake animation while retaining the scale animation

I am applying a scale animation on RecyclerView. I am applying this animation on OnFocusChangeListener event. After this animation is applied, I also want to apply a shake animation to the same item while it retains the previous scale.
but in my case the item is scaled back to normal size before applying the shake animation.
Here is the problem I face.
scale animation zoom_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true"
android:fillEnabled="true"
android:interpolator="#android:anim/linear_interpolator"
android:zAdjustment="top">
<scale
android:duration="200"
android:fromXScale="1"
android:fromYScale="1"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1.2"
android:toYScale="1.2" />
</set>
Shake animation shake.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="100"
android:fromXDelta="-5%"
android:repeatCount="3"
android:repeatMode="reverse"
android:toXDelta="5%" />
</set>
OnFocusChangeListener - This is where I scale the object
holder.channelCardView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View view, boolean hasFocus) {
if (hasFocus) {
Animation animZoomIn = AnimationUtils.loadAnimation(mContext, R.anim.zoom_in);
view.startAnimation(animZoomIn);
} else {
Animation animZoomOut = AnimationUtils.loadAnimation(mContext, R.anim.zoom_out);
view.startAnimation(animZoomOut);
}
}
});
OnKeyListener - This is where I apply shake animation.
holder.channelCardView.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_DPAD_RIGHT && getItemCount() == position + 1) {
if(getItemCount() == position + 1 && count[0] >= 2) {
Animation animShake = AnimationUtils.loadAnimation(mContext, R.anim.shake);
holder.channelCardView.startAnimation(animShake);
}
else {
count[0]++;
}
}
else {
count[0] = 0;
}
return false;
}
});
I want to apply the shake animation while the item is zoomed and I want to keep it zoomed until focus is changed.
Appreciate your help
After lot of reading I found the solution myself. by changing the shake.xml as below the problem is solved.
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:anim/linear_interpolator"
android:fillEnabled="true"
android:fillAfter="true">
<scale
android:duration="200"
android:fromXScale="1.2"
android:fromYScale="1.2"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1.2"
android:toYScale="1.2" />
<translate
android:duration="100"
android:fromXDelta="-3%"
android:repeatCount="3"
android:repeatMode="restart"
android:toXDelta="3%" />
</set>

Why image rotation animation only works correctly for the first time

I have this simple arrow image rotation animation which works as intended only for the first time. from second time onward It's still do the rotation but without slow animation.
Here's the code in anim xml files
Rotate 180
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1500"
android:fromDegrees="0"
android:toDegrees="180"
android:interpolator="#android:anim/linear_interpolator"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="0"
android:fillAfter="true"
android:fillEnabled="true"/>
Rotate Revere
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1500"
android:fromDegrees="180"
android:toDegrees="0"
android:interpolator="#android:anim/linear_interpolator"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="0"
android:fillAfter="true"
android:fillEnabled="true"
/>
The image view inside card view.
<ImageView
android:id="#+id/creadit_card_next_image"
android:layout_width="#dimen/next_image_size"
android:layout_height="#dimen/next_image_size"
android:layout_marginEnd="#dimen/static_menu_primary_margin"
android:layout_marginTop="16dp"
android:rotation="-90"
android:src="#drawable/ic_navigate_next"
android:tint="#color/colorPrimary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
Java code to trigger Animation.
private Animation rotatePlus180;
private Animation rotateMinus180;
private boolean creditDebitCardViewExpanded = true;
rotatePlus180 = AnimationUtils.loadAnimation(this, R.anim.rotate_plus_180);
rotateMinus180 = AnimationUtils.loadAnimation(this, R.anim.rotate_minus_180);
private void onClickCreditDebitCardView() {
creditDebitCardPaymentMethod.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (creditDebitCardViewExpanded) {
expandAnimation(paymentRecyclerView);
creditDebitCardViewExpanded = false;
creditCardNextImage.setAnimation(rotatePlus180);
} else {
collapseAnimation(paymentRecyclerView);
creditDebitCardViewExpanded = true;
creditCardNextImage.setAnimation(rotateMinus180);
CreditDebitLayoutContainer.setPadding(0, 0, 0, padding);
}
}
});
}
Instead of setAnimation use startAnimation
creditCardNextImage.startAnimation(rotatePlus180);
creditCardNextImage.startAnimation(rotateMinus180);
setAnimation seems to be called once you attach the animation to the view/ or when the view is added.
StartAnimation will be called all the time even if the view has already been added.

How do I reverse a running animation?

When the Button is touched, it starts a zoom animation.
Animation zoomIn = AnimationUtils.loadAnimation(context, R.anim.zoomin);
view.startAnimation(zoomIn);
The zoomin.xml code:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillEnabled="true"
android:fillAfter="true">
<scale
android:fromXScale="1.0"
android:toXScale="1.3"
android:fromYScale="1.0"
android:toYScale="1.3"
android:pivotX="50%"
android:pivotY="50%"
android:duration="200"
android:interpolator="#android:anim/accelerate_interpolator"/>
</set>
But if the Button is released during this still running animation, it should reverse the animation from this point in time.
How can i achieve that?
You could use ViewPropertyAnimator to achieve something like this.
For example:
Button button = (Button) findViewById(R.id.yourButton);
button.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// adjust the scale and duration values according to your needs
if (event.getAction() == MotionEvent.ACTION_DOWN) {
v.animate().scaleX(2).scaleY(2).setDuration(2000);
} else if (event.getAction() == MotionEvent.ACTION_UP) {
v.animate().scaleX(1).scaleY(1).setDuration(2000);
}
return false;
}
});

Animation of a Custom Dialog Fragment in Android

To achieve a animated pop up, I have used a custom DialogFragment extending the DialogFragment class. Then, I designed the overlay layout in xml and added that during loading of the pop up. As, I needed to do the animation, I designed 2 animation xml files and added that in styles.xml and added the animation during the loading of the overlay.
I am showing the overlay animation in 3 places. It shows perfectly i.e. grows from the Bee icon and disappears in the bee icon when I use it as a component in a list item and when I use it along with a image view. But when I use it along with a VideoView or Exoplayer View the starting point of the animation shifts to the left for the x axis and goes up for the Y axis.
Also, the the pop up along with the animation works perfectly using the below code for Samsung Note Edge but causes the above problem for Samsung Galaxy S5 and Nexus 4.
It also works fine i.e. the overlay is at the exact position where the bee is for all 3 screens when I do not use the animation. So, I guess the error is in the animation.
I am giving sample code, I wrote.
Custom Dialog Fragment:
public class ConfirmBox extends DialogFragment {
private View source;
private RelativeLayout relLayout;
public ConfirmBox() {
}
public ConfirmBox(View source) {
this.source = source;
}
public ConfirmBox(View source,RelativeLayout relLayout) {
this.source = source;
this.relLayout =relLayout;
}
public static ConfirmBox newInstance(View source) {
return new ConfirmBox(source);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(STYLE_NO_TITLE, 0);
}
#Override
public void onStart() {
super.onStart();
// Less dimmed background; see http://stackoverflow.com/q/13822842/56285
Window window = getDialog().getWindow();
WindowManager.LayoutParams params = window.getAttributes();
params.dimAmount = 0.2f; // dim only a little bit
window.setAttributes(params);
// Transparent background; see http://stackoverflow.com/q/15007272/56285
// (Needed to make dialog's alpha shadow look good)
window.setBackgroundDrawableResource(android.R.color.transparent);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Put your dialog layout in R.layout.view_confirm_box
final View view = inflater.inflate(R.layout.overlay_view, container, false);
RelativeLayout layout = (RelativeLayout) view.findViewById(R.id.overlayLayout);
layout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
getDialog().dismiss();
}
});
setDialogPosition();
return view;
}
/**
* Try to position this dialog next to "source" view
*/
private void setDialogPosition() {
if (source == null) {
return; // Leave the dialog in default position
}
// Find out location of source component on screen
// see http://stackoverflow.com/a/6798093/56285
int[] location = new int[2];
source.getLocationOnScreen(location);
int sourceX = location[0];
int sourceY = location[1];
Log.d("CONFIRM BOX:", "X: " + sourceX + "Y: " + sourceY);
Window window = getDialog().getWindow();
window.getAttributes().windowAnimations = R.style.PauseDialogAnimation;
// set "origin" to top left corner
window.setGravity(Gravity.TOP| Gravity.LEFT);
WindowManager.LayoutParams params = window.getAttributes();
params.x = sourceX;
params.y = sourceY - dpToPx(25);
Log.d("CONFIRM BOX:","X: "+ sourceX + "Y: "+ sourceY);
Log.d("CONFIRM BOX:","-----------------------------------------------------------");
window.setAttributes(params);
// Show the animation of the DialogueFragment
window.getAttributes().windowAnimations = R.style.PauseDialogAnimation;
}
public int dpToPx(float valueInDp) {
DisplayMetrics metrics = getActivity().getResources().getDisplayMetrics();
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, valueInDp, metrics);
}
}
anim_in.xml:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:interpolator="#android:anim/linear_interpolator"
android:fromXScale="0.0"
android:toXScale="1.0"
android:fromYScale="0.0"
android:toYScale="1.0"
android:fillAfter="false"
android:startOffset="100"
android:duration="200"
android:pivotX = "5%"
android:pivotY = "-40%"
/>
<translate
android:fromYDelta="50%"
android:toYDelta="0"
android:startOffset="100"
android:duration="200"
/>
</set>
anim_out.xml:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:interpolator="#android:anim/linear_interpolator"
android:fromXScale="1.0"
android:toXScale="0.0"
android:fromYScale="1.0"
android:toYScale="0.0"
android:fillAfter="false"
android:duration="200"
android:pivotX = "5%"
android:pivotY = "-40%"
/>
<translate
android:fromYDelta="0"
android:toYDelta="50%"
android:duration="200"
/>
</set>
styles.xml:
<style name="PauseDialogAnimation">
<item name="android:windowEnterAnimation">#anim/anim_in</item>
<item name="android:windowExitAnimation">#anim/anim_out</item>
</style>
Can someone kindly help me on zeroing in on the problem here?
Thanks.

how to manage OnClickListener on animated image?

I have an animated image of a bee.
I set an onClick Listener to the imageView, and it's working, but only in native position of the imageView, but not when its animating.
i also tried to use onTouchListener, but the result is the same.
How can i make onClick or onTouchListener work while the ImageView is animating?
animation:
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:anim/accelerate_decelerate_interpolator"
android:shareInterpolator="true">
<scale
android:repeatCount="infinite"
android:repeatMode="reverse"
android:duration="8000"
android:fromXScale="0.2"
android:toXScale="1.5"
android:fromYScale="0.2"
android:toYScale="1.5"
android:pivotY="0%"
android:pivotX="50%"/>
<translate
android:interpolator="#android:anim/bounce_interpolator"
android:fillBefore="true"
android:repeatCount="infinite"
android:repeatMode="reverse"
android:duration="2000"
android:toXDelta="35"
android:toYDelta="85"/>
<rotate
android:pivotX="50%"
android:pivotY="0%"
android:fromDegrees="360"
android:toDegrees="0"
android:duration="6000"
android:repeatMode="reverse"
android:repeatCount="infinite"/>
onClick:
public static void onBTNClick_RidBee(Activity activity){
bee_icon = (ImageView)activity.findViewById(R.id.bee_icon);
bee_icon.clearAnimation();
}
}
onTouchListener:
bee_icon.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.d("myLogs", "clear anim bee");
bee_icon.clearAnimation();
}
return true;
}
});
Use android:fillAter="true". fillAfter controls whether the animation's ending value persists after it ends. By default, the state of the view after animation will be same as the state before the animation. for eg:suppose, before animation view's x position is 10, and you are translating x to 100, after animation the position will be still 10 not 100. But if you set fillAfter="true", after animation x will be 100

Categories

Resources