Rotate ImageView and FrameLayout correctly - android

I have an Imageview inside a FrameLayout (both have Layout_margins),also i got my custom FrameLayout(same with Layout_margins).
So what i have now:
Source code(.axml):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ffff363c"
android:layout_weight="100"
android:clickable="true">
<FrameLayout
android:id="#+id/MainFrameLayout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="center"
android:layout_weight="80">
<FrameLayout
android:id="#+id/SourceFrame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_margin="10dp">
<ImageView
android:src="#android:drawable/ic_menu_camera"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/Img"
android:layout_margin="10dp" />
</FrameLayout>
<CustomFrameLayout
android:id="#+id/CustomView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible"
android:layout_margin="10dp" />
</FrameLayout>
</LinearLayout>
And what i want exactly(programmatically rotation left,right via button):
So my main goal is to rotate properly image(and CustomFrameLayout too),also i need to store my source Width/Height of image.How can i achieve this?
I tried to set scaleType.center / scaletype.centerInisde , but that is wrong idea.
Any suggestions? Thanks!

Don't know if i exactly understand your problem.
If u want programmatically rotate something u can try this:
ImageView image.animate().rotation(90).start();
or this
FrameLayout frame.animate().rotation(90).start();
or both.
To store Width/Height u can use
int image_h = image.getHeight();
int image_w = image.getWidth();

Better late than never.
I was facing the exactly same problem.
After some trying, I came with this solution:
private void rotateImageBy90(){
imageView.animate()
.rotation(90)
.setInterpolator(new AccelerateDecelerateInterpolator())
.setDuration(250)
.setListener(rotateListener)
.start();
Log.d("chatImage", "Rotating image by "+90+" degrees clockwise");
}
Declare an AnimatorListener, the one that solves the problem:
Animator.AnimatorListener rotateListener = new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animator) {
}
#Override
public void onAnimationEnd(Animator animator) {
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) imageView.getLayoutParams();
params.height = FrameLayout.LayoutParams.MATCH_PARENT;
params.width = FrameLayout.LayoutParams.MATCH_PARENT;
imageView.setLayoutParams(params);
imageView.requestLayout();
//This is the trick: I get the current bitmap, rotate it
Bitmap newBitmap = rotateImage(((BitmapDrawable)imageView.getDrawable()).getBitmap(),90);
//Then, rotate the imageview back to it's original position, without animation
imageView.setRotation(0);
//As I set the new, rotate bitmap, to it.
imageView.setImageBitmap(newBitmap);
}
#Override
public void onAnimationCancel(Animator animator) {
}
#Override
public void onAnimationRepeat(Animator animator) {
}
};
The rotateImage method:
public static Bitmap rotateImage(Bitmap source, float angle) {
Matrix matrix = new Matrix();
matrix.postRotate(angle);
return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix,
true);
}

Related

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.

How to animate an imageview up to the another view and again back to original position

I want to animate an ImageView in such a way that it starts moving from its initial position to a button (move ImageView upside) and again back to its initial position and this repeats infinitely. I am totally new to animating things so please guide me how to do it?
my layout.xml is as follows:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".fragment.Scratch1Fragment">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="#+id/btn_scratch_now"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="#style/buttonStyle"
android:text="#string/str_scratch_now"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintVertical_bias="0.2"/>
<View
android:id="#+id/upper_bound"
android:layout_width="match_parent"
android:layout_height="2dp"
android:background="#color/primary"
android:layout_marginEnd="10dp"
android:layout_marginStart="10dp"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintVertical_bias="0.5"/>
<TextView
android:id="#+id/text_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/str_scratch"
style="#style/tvDarkLargeStyle"
android:gravity="center"
android:textAlignment="center"
app:layout_constraintTop_toBottomOf="#+id/upper_bound"
/>
<View
android:id="#+id/lower_bound"
android:layout_width="match_parent"
android:layout_height="2dp"
android:background="#color/primary"
android:layout_marginEnd="10dp"
android:layout_marginStart="10dp"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="#+id/text_view"
/>
<TextView
android:id="#+id/tv_tap_here"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="#id/lower_bound"
android:layout_margin="20dp"
android:padding="10dp"
android:gravity="center"
style="#style/tvLightLargeStyle"
android:textAlignment="center"
android:text="Tap here"/>
<ImageView
android:id="#+id/img_hand"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/clicker_hand_64"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="#+id/upper_bound"/>
</android.support.constraint.ConstraintLayout>
</FrameLayout>
Please feel free to ask for more code or more details if my question sounds unclear.
Update
After getting some resources to begin with I tried it and I found below code. but somehow I can not get the position of button's float (It is always returning 0.)
My code is as below:
private void animate() {
Log.e("button top", String.valueOf(btnScratch.getTop()));
int location[] = new int[2];
btnScratch.getLocationOnScreen(location);
Log.e("button location x and y",location[0]+" "+location[1]);
int location2[] = new int[2];
imgHand.getLocationOnScreen(location2);
Log.e("image location x and y",location2[0]+" "+location2[1]);
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f, btnScratch.getTop());
valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator()); // increase the speed first and then decrease
valueAnimator.setDuration(1000);
valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
float progress = (float) animation.getAnimatedValue();
imgHand.setTranslationY(progress);
// no need to use invalidate() as it is already present in //the text view.
}
});
valueAnimator.start();
}
I have also tried same with ObjectAnimatior instead of ValueAnimator. But did not work.
Finally, I found my answer with the help of all the comments and links provided in that. I don't know whether it is the ideal solution or not but it is working. If anyone has a better solution please provide that.
What I did for getting the position of the button (which was 0 before the solution).
btnScratch.post(new Runnable() {
#Override
public void run() {
float center = (btnScratch.getTop() + btnScratch.getBottom()) / 2;
Log.e("center point", String.valueOf(center));
animateUpToButton(center - imgHand.getTop());
}
});
for getting center of the button I used following line:
float center = (btnScratch.getTop() + btnScratch.getBottom()) / 2;
and for animation :
private void animateUpToButton(final float distance) {
ObjectAnimator imageAnimator = ObjectAnimator.ofFloat(imgHand, "translationY", 0f, distance);
imageAnimator.setDuration(ANIM_DURATION);
imageAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
imageAnimator.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animator) {
}
#Override
public void onAnimationEnd(Animator animator) {
animateBackToOrigin(distance);
}
#Override
public void onAnimationCancel(Animator animator) {
}
#Override
public void onAnimationRepeat(Animator animator) {
}
});
imageAnimator.start();
}
And, onAnimationEnd(), I added another animation to get the image back to the initial position.
private void animateBackToOrigin(final float distance) {
ObjectAnimator imageAnimator = ObjectAnimator.ofFloat(imgHand, "translationY", distance, 0f);
imageAnimator.setDuration(ANIM_DURATION);
imageAnimator.setInterpolator(new LinearInterpolator());
imageAnimator.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animator) {
}
#Override
public void onAnimationEnd(Animator animator) {
animateUpToButton(distance);
}
#Override
public void onAnimationCancel(Animator animator) {
}
#Override
public void onAnimationRepeat(Animator animator) {
}
});
imageAnimator.start();
}
and again onAnimationEnd(), I added animation to move image towards the button. this way, the animation will continue one after another.
Try This:
ObjectAnimator slideUp = ObjectAnimator.ofFloat(mImageView,"translationY",-btn_scratch_now.getTop());
slideUp.setRepeatMode(ObjectAnimator.RESTART);
slideUp.setRepeatCount(ObjectAnimator.INFINITE);
slideUp.start();

Translation Animation not working

I tried to do a simple animation from bottom left corner to right center and then to center of the screen
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
screenWidthPx = size.x;
screenHeightPx = size.y;
final TranslateAnimation slideFromRight = new TranslateAnimation(screenWidthPx, screenWidthPx/2, screenHeightPx, screenHeightPx);
slideFromRight.setInterpolator(new AccelerateDecelerateInterpolator());
slideFromRight.setStartOffset(300);
slideFromRight.setDuration(600);
slideFromRight.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
TranslateAnimation titleIconSlideUp = new TranslateAnimation(0, screenWidthPx/2, screenHeightPx, screenHeightPx/2);
titleIconSlideUp.setInterpolator(new AccelerateDecelerateInterpolator());
titleIconSlideUp.setStartOffset(500);
titleIconSlideUp.setFillAfter(true);
titleIconSlideUp.setDuration(1000);
tvAnimView.startAnimation(titleIconSlideUp);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
tvAnimView.startAnimation(slideFromRight);
the second animation inside onAnimationEnd is working fine. But don't know why first animation is not working fine. where my layout is simple
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/rl_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
android:clipToPadding="false"
tools:context="broadpeak.animationlearning.AnimTestActivity">
<TextView
android:id="#+id/tv_anim_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World"
android:textColor="#color/colorPrimaryDark"
android:textSize="24sp" />
</RelativeLayout>
You should start your animation using this line:
tvAnimView.startAnimation(slideFromRight);
Just put this piece of code in click listener or onCreate(), onResume() methods, according to your needs.

View width is zero when set to MATCH_PARENT

I have an ImageView inside of a LinearLayout which is an item of a RecyclerView. I have all these views' width as MATCH_PARENT.
Now, I'm trying to calculate the heigth using the aspect ratio before the image is loaded so there's no resizing.
But, what I've seen is that before the image is loaded, its width is zero.
The thing is that I'm doing similar things in other parts of the app and it's working fine, I don't really know what I'm missing here.
RecyclerView item:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/white">
<LinearLayout
...
</LinearLayout>
<!-- This is the image -->
<ImageView
android:id="#+id/descubre_shop_banner"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="16dp"
android:adjustViewBounds="true"
android:scaleType="centerCrop"/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#color/colorLightText"
android:layout_marginRight="16dp"
android:layout_marginLeft="16dp"
android:layout_marginBottom="8dp"/>
</LinearLayout>
ViewHolder
mBannerTarget = new Target()
{
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from)
{
mShopBannerImageView.setImageBitmap(bitmap);
// Wrap content when the images is loaded.
mShopBannerImageView.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT;
mShopBannerImageView.setBackgroundColor(-1);
mShopBannerImageView.setAlpha(1.0f);
Animation fadeOut = new AlphaAnimation(0, 1);
fadeOut.setInterpolator(new AccelerateInterpolator());
fadeOut.setDuration(250);
mShopBannerImageView.startAnimation(fadeOut);
LOADED = true;
}
#Override
public void onBitmapFailed(Drawable errorDrawable)
{
mShopBannerImageView.setBackgroundColor(
mContext.getResources().getColor(android.R.color.holo_red_dark));
mShopBannerImageView.setAlpha(0.2f);
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable)
{
// This is 0
Log.d(Properties.TAG, "" + mShopBannerImageView.getWidth());
// Remove the old bitmap
mShopBannerImageView.setImageBitmap(null);
// Set the height using the width and the aspect ratio.
mShopBannerImageView.getLayoutParams().height =
(int) (mShopBannerImageView.getWidth() * shop.getAspectRatio());
// Set a color while loading.
mShopBannerImageView.setBackgroundColor(
mContext.getResources().getColor(R.color.colorAccent));
mShopBannerImageView.setAlpha(0.25f);
}
};
I tried to set the width of the ImageView and its parent as MATCH_PARENT in code but no luck. Any clue of what's going on?
Regards,
The views dimensions is always 0 before being fully created, if you wanted to know the actual width, you have to use the method: post():
view.post(new Runnable() {
#Override
public void run() {
// This is where width would be different than 0
}
});
That being said, you should actually use an other method to keep the ratio than actually calculating it yourself!
See this thread for further information How to scale an Image in ImageView to keep the aspect ratio

Scale a layout to match parent with animation

In my sample project i have a linear layout, its height is set to wrap content in xml and there is also a fragment below it which takes all the remaining space. The fragment contains a button which when clicked will remove the fragment and the height of the linear layout is set to match parent. I tried adding android:animateLayoutChanges="true" but the transition from wrap_content to match_parent is not smooth. How can i animate from android:layout_height="wrap_content" to android:layout_height="match_parent"
Here is the layout
<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:background="#drawable/bg"
android:orientation="vertical"
android:id="#+id/layoutRoot"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:id="#+id/cloudHolder"
android:orientation="vertical"
android:animateLayoutChanges="true"
android:gravity="center"
android:layout_height="wrap_content">
<ImageButton
android:layout_width="100dp"
android:layout_gravity="center"
android:layout_height="100dp"
android:background="#drawable/play"/>
</LinearLayout>
#tdjprog Answer with some edit
1 - Stritch
private void animateViewTostritch_height(final View target) {
int fromValue = 0;
// int fromValue = target.getHeight();
// int toValue = ((View) target.getParent()).getHeight();// matchparent
int toValue = (int) getResources().getDimension(R.dimen.dialog_header_height);//spesific hight
// int toValue = (int) (getResources().getDimension(R.dimen.dialog_header_height) / getResources().getDisplayMetrics().density);
ValueAnimator animator = ValueAnimator.ofInt(fromValue, toValue);
animator.setDuration(2000);
animator.setInterpolator(new DecelerateInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
target.getLayoutParams().height = (int) animation.getAnimatedValue();
target.requestLayout();
}
});
animator.start();
}
Call animateViewTostritch_height(your_View);
2 - Scale %
public void scaleView(View v, float startScale, float endScale) {
Animation anim = new ScaleAnimation(
1f, 1f, // Start and end values for the X axis scaling
startScale, endScale, // Start and end values for the Y axis scaling
Animation.RELATIVE_TO_SELF, 0f, // Pivot point of X scaling
Animation.RELATIVE_TO_SELF, 1f); // Pivot point of Y scaling
anim.setFillAfter(true); // Needed to keep the result of the animation
anim.setDuration(1000);
v.startAnimation(anim);
}
Call scaleView(your_View,0f,10f); // 10f match parent
You may need to try adding android:animateLayoutChanges="true" in the parent layout itself like for example:
<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:background="#drawable/bg"
android:orientation="vertical"
android:animateLayoutChanges="true"
android:id="#+id/layoutRoot"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:id="#+id/cloudHolder"
android:orientation="vertical"
android:gravity="center"
android:layout_height="wrap_content">
<ImageButton
android:layout_width="100dp"
android:layout_gravity="center"
android:layout_height="100dp"
android:background="#drawable/play"/>
</LinearLayout>
</LinearLayout>
If the above code doesn't work, you might need to take a look at:
Animation of height of LinearLayout container with ValueAnimator
Or
Animation in changing LayoutParams in LinearLayout
I think relying on animateLayoutChanges isn't a good idea. Try below code instead.
import android.view.ViewPropertyAnimator;
// In your activity
private int parentHeight;
private int childHeight;
private float childScaleFactor;
//In onCreate()
mChildView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
parentHeight = mParentView.getMeasuredHeight();
childHeight = mChildView.getMeasuredHeight();
childScaleFactor = parentHeight/childHeight;
}
});
mChildView.animate()
.scaleY(childScaleFactor)
.setDuration(500)
.start();
If this doesn't work, refer to this answer on another post
try this:
private void animateViewToMatchParent(final View target) {
int fromValue = target.getHeight();
int toValue = ((View) target.getParent()).getHeight();
ValueAnimator animator = ValueAnimator.ofInt(fromValue, toValue);
animator.setDuration(250);
animator.setInterpolator(new DecelerateInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
target.getLayoutParams().height = (int) animation.getAnimatedValue();
target.requestLayout();
}
});
animator.start();
}

Categories

Resources