使位图越过 ImageView 边界
Make the bitmap get over ImageView borders
我正在 运行在 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 的解决方案后,仅当我在 MainActivity 的 onCreate() 中打开片段时,动画 运行 才正确。如果我在 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();
}
你几乎做到了,但忘记了两件事:
- 将 ImageView 宽度和高度设置为
match_layout
将仅匹配父级的边框。您必须设置自定义尺寸,这样当您将图像居中时,它将填满整个视图。
- 在图像旋转过程中,当图像达到 45 度时,我们可以注意到图像并没有填满整个视图。为什么?尝试将两个矩形放在自己身上,然后将其中一个旋转 45 度。这是结果。根据正方形的定义,it's diagonal value 大于正方形的一条边。所以我们必须覆盖这个。
这是解决方案。
- 我们根据屏幕的最长边为 ImageView 设置自定义尺寸
- 我们重写宽度以使用正方形的对角线宽度而不是单边
大部分代码与您的相同。我用片段来展示样本。
//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" />
结果如下:
我正在 运行在 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 的解决方案后,仅当我在 MainActivity 的 onCreate() 中打开片段时,动画 运行 才正确。如果我在 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();
}
你几乎做到了,但忘记了两件事:
- 将 ImageView 宽度和高度设置为
match_layout
将仅匹配父级的边框。您必须设置自定义尺寸,这样当您将图像居中时,它将填满整个视图。 - 在图像旋转过程中,当图像达到 45 度时,我们可以注意到图像并没有填满整个视图。为什么?尝试将两个矩形放在自己身上,然后将其中一个旋转 45 度。这是结果。根据正方形的定义,it's diagonal value 大于正方形的一条边。所以我们必须覆盖这个。
这是解决方案。
- 我们根据屏幕的最长边为 ImageView 设置自定义尺寸
- 我们重写宽度以使用正方形的对角线宽度而不是单边
大部分代码与您的相同。我用片段来展示样本。
//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" />
结果如下: