Hai Hack
Hai Hack

Reputation: 1018

Make the bitmap get over ImageView borders

I'm running a rotation animation on a ImageView. The thing is the bitmap has been cut to fit exactly the ImageView. So when it rotate, it doesn't cover completely the ImageView as well as the screen.

This is what I want

enter image description here

And this is what happened

enter image description here

xml

<?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"
    tools:context=".fragments.LevelCompletedFragment">

    <RelativeLayout
        android:id="@+id/vgBackground"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#3f5d68"
        android:alpha="1">
    </RelativeLayout>

    <ImageView
        android:id="@+id/ivStarburst"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:adjustViewBounds="true"
        android:scaleType="centerCrop"
        android:src="@drawable/star" />

</FrameLayout>

Run animation

Animation shake = AnimationUtils.loadAnimation(mContext, R.anim.clockwise_rotation);
        **ivStarburst.startAnimation(shake);

Edit: After following the solution by @deadfish the animation run correctly only when I open the fragment in onCreate() in MainActivity. If I trigger the fragment in onClick() method, it doesn't work.

MainActivity.java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    btn.setOnClickListener(this);
}

@Override
public void onClick(View v) {
    MainFragment frgm = new MainFragment ();
                getSupportFragmentManager().beginTransaction()
                        .replace(R.id.fragment_container, frgm).commit();
}

Upvotes: 0

Views: 122

Answers (1)

deadfish
deadfish

Reputation: 12304

You almost did it but forget two things:

  1. setting ImageView width and height as match_layout will match only to the parent's border. You must set custom dimenstion so when You center image, it will fill the whole view.
  2. during image's rotation when the image reaches degree 45 we can notice the image doesn't fill the whole view. Why? Try put two rectangles on themself and then rotate one of them by 45 degree. Here is the result. According to definition of square, it's diagonal value is bigger than one of the sides of a square. So we must cover this.

enter image description here

Here is the solution.

  1. we set custom dimension for ImageView basing on the longest side of the screen
  2. we rewrite width to use diagonal width of square instead of single side

Most of the code is the same as Yours. I used fragment to show the sample.

//MainActivity part

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_activity);

        this.<Button>findViewById(R.id.btn).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        getSupportFragmentManager()
                .beginTransaction()
                .replace(R.id.container, MainFragment.newInstance())
                .commit();
    }
}

// Fragment part

public class MainFragment extends Fragment {

    public static MainFragment newInstance() {
        return new MainFragment();
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.main_fragment, container, false);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        ImageView imageView = Objects.requireNonNull(view).findViewById(R.id.imageView);

        // Manually set image for ImageView
        setImageForView(imageView, R.drawable.star);

        // Turn ImageView to square where a = Max(Screen.width, Screen.height)
        changeDimensionToSquareForView(imageView);

        // Start rotations
        animateRotation(imageView);
    }

    private void changeDimensionToSquareForView(ImageView imageView) {
        DisplayMetrics displayMetrics = Resources.getSystem().getDisplayMetrics();
        double maxWidth = Math.max(displayMetrics.widthPixels, displayMetrics.heightPixels);

        //calc diagonal line, x = a * sqrt(2)
        maxWidth = (maxWidth * (Math.sqrt(2)));

        imageView.setLayoutParams(new FrameLayout.LayoutParams((int) maxWidth, (int) maxWidth, Gravity.CENTER));
    }

    private void setImageForView(ImageView imageView, @DrawableRes int imageRes) {
        Context context = imageView.getContext();
        imageView.setImageDrawable(context.getResources().getDrawable(imageRes, context.getTheme()));
    }

    // Call this method in onClick method
    public void animateRotation(ImageView imageView) {
        Context context = imageView.getContext();
        Animation shake = AnimationUtils.loadAnimation(context, R.anim.clockwise_rotation);
        imageView.startAnimation(shake);
    }

}

Here is the layout of fragment:

<?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:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ui.main.MainFragment">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:src="@drawable/star" />

</FrameLayout>

Here is the animation xml:

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="15000"
    android:fromDegrees="0"
    android:interpolator="@android:anim/linear_interpolator"
    android:pivotX="50%"
    android:pivotY="50%"
    android:startOffset="0"
    android:toDegrees="360" />

Here is the result:

enter image description here

Upvotes: 3

Related Questions