Заставить растровое изображение преодолеть границы ImageView

Я запускаю анимацию вращения в ImageView. Дело в том, что растровое изображение было обрезано, чтобы соответствовать точно ImageView. Поэтому, когда он вращается, он не покрывает полностью ImageView, а также экран.

Это то что я хочу

И это то, что случилось

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>

Запустить анимацию

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

Редактировать: после выполнения решения @deadfish анимация запускается правильно, только когда я открываю фрагмент в onCreate() в MainActivity. Если я запускаю фрагмент в методе onClick(), он не работает.

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();
}

1 ответ

Решение

Вы почти сделали это, но забыли две вещи:

  1. установка ширины и высоты ImageView как match_layout будет соответствовать только границе родителя. Вы должны установить пользовательские размеры, чтобы, когда Вы центрируете изображение, оно заполняло весь вид.
  2. во время поворота изображения, когда изображение достигает 45-й степени, мы можем заметить, что изображение не заполняет весь вид. Зачем? Попробуйте наложить два прямоугольника на себя, а затем поверните один из них на 45 градусов. Вот результат. Согласно определению квадрата, его диагональное значение больше, чем одна из сторон квадрата. Поэтому мы должны это охватить.

Вот решение.

  1. мы устанавливаем пользовательское измерение для ImageView, основываясь на самой длинной стороне экрана
  2. мы переписываем ширину, чтобы использовать диагональную ширину квадрата вместо одной стороны

Большая часть кода такая же, как ваша. Я использовал фрагмент, чтобы показать образец.

// MainActivity

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();
    }
}

// Фрагмент

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);
    }

}

Вот расположение фрагмента:

<?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>

Вот анимация 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" />

Вот результат:

Другие вопросы по тегам