我正在尝试使用来自 der android 开发人员网站的以下示例缩放 FrameLayout:http: //developer.android.com/training/animation/zoom.html
我的具体问题,第一次动画是正确的,是从 thumbView 扩展,第二次动画来自“某处”(中间/顶部到中心)。
我几乎相同,不同之处在于,我有一个 Framelayout 而不是一个 ImageView 并且我提取了函数以在一个额外的方法中最小化视图。现在看起来像这样:
private void zoomImageFromThumb(final View thumbView) {
if (mCurrentAnimator != null) {
mCurrentAnimator.cancel();
}
// here i building my custome layout
startBounds = new Rect();
final Rect finalBounds = new Rect();
final Point globalOffset = new Point();
thumbView.getGlobalVisibleRect(startBounds);
findViewById(R.id.container)
.getGlobalVisibleRect(finalBounds, globalOffset);
startBounds.offset(-globalOffset.x, -globalOffset.y);
finalBounds.offset(-globalOffset.x + 15, -globalOffset.y + 60);
float startScale;
if ((float) finalBounds.width() / finalBounds.height()
> (float) startBounds.width() / startBounds.height()) {
startScale = (float) startBounds.height() / finalBounds.height();
float startWidth = startScale * finalBounds.width();
float deltaWidth = (startWidth - startBounds.width()) / 2;
startBounds.left -= deltaWidth;
startBounds.right += deltaWidth;
} else {
startScale = (float) startBounds.width() / finalBounds.width();
float startHeight = startScale * finalBounds.height();
float deltaHeight = (startHeight - startBounds.height()) / 2;
startBounds.top -= deltaHeight;
startBounds.bottom += deltaHeight;
}
thumbView.setAlpha(0f);
expandedImageView.setVisibility(View.VISIBLE);
expandedImageView.setPivotX(0f);
expandedImageView.setPivotY(0f);
AnimatorSet set = new AnimatorSet();
set
.play(ObjectAnimator.ofFloat(expandedImageView, View.X,
startBounds.left, finalBounds.left))
.with(ObjectAnimator.ofFloat(expandedImageView, View.Y,
startBounds.top, finalBounds.top))
.with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_X,
startScale, 1f)).with(ObjectAnimator.ofFloat(expandedImageView,
View.SCALE_Y, startScale, 1f));
set.setDuration(mShortAnimationDuration);
set.setInterpolator(new DecelerateInterpolator());
set.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mCurrentAnimator = null;
}
@Override
public void onAnimationCancel(Animator animation) {
mCurrentAnimator = null;
}
});
set.start();
mCurrentAnimator = set;
}
startBounds 变量是全局的,因为我需要它来知道最小化过程的位置。这里是最小化方法:
private void minimizeViewFromThumb(final View thumbView) {
if (mCurrentAnimator != null) {
mCurrentAnimator.cancel();
}
AnimatorSet set = new AnimatorSet();
set.play(ObjectAnimator
.ofFloat(expandedImageView, View.X, startBounds.left))
.with(ObjectAnimator
.ofFloat(expandedImageView,
View.Y,startBounds.top))
.with(ObjectAnimator
.ofFloat(expandedImageView,
View.SCALE_X, startScaleFinal))
.with(ObjectAnimator
.ofFloat(expandedImageView,
View.SCALE_Y, startScaleFinal));
set.setDuration(mShortAnimationDuration);
set.setInterpolator(new DecelerateInterpolator());
set.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
thumbView.setAlpha(1f);
expandedImageView.setVisibility(View.GONE);
mCurrentAnimator = null;
}
@Override
public void onAnimationCancel(Animator animation) {
thumbView.setAlpha(1f);
expandedImageView.setVisibility(View.GONE);
mCurrentAnimator = null;
}
});
set.start();
mCurrentAnimator = set;
}
如果我调试整个过程,我可以看到方法 zoomViewFromThumb 中的 getGlobalVisibleRect 方法给了我另一个值。
如果我调试线路
finalBounds.offset(-globalOffset.x, -globalOffset.y);
第一次这两个参数是 0 和 -60,第二次(最小化和重新创建后有 15 和 360。
我不知道为什么会这样。
我尝试从给定的 thumbView 设置 View.X 和 View.Y 参数追加,我尝试在 ObjectAnimator 中使用 View.X、View.Y 参数的常量值,但没有解决我的问题。
现在请帮助我。
问候马努
1. 编辑:失败出现在 Android 4.1.2 上
2.编辑:这里是xml文件,第一个是代表我的主要活动的xml文件(带有动画),第二个代表我在主要xml的FrameLayout中推送的TableLayout。(请注意,目前我正在工作,我无法访问原始文件,现在这些 xml 文件在我记忆中都很好)
首先
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/relZoom"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<FrameLayout
android:id="@+id/frameZoomOne"
android:layout_width="160dp"
android:layout_height="215dp"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_marginBottom="10dp"
android:layout_marginLeft="10dp" >
</FrameLayout>
<FrameLayout
android:id="@+id/frameZoomTwo"
android:layout_width="160dp"
android:layout_height="215dp"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginRight="10dp"
android:layout_marginTop="10dp" >
</FrameLayout>
<FrameLayout
android:id="@+id/container"
android:layout_width="300dp"
android:layout_height="408dp"
android:visibility="invisible" >
</FrameLayout>
<FrameLayout
android:id="@+id/containerTwo"
android:layout_width="300dp"
android:layout_height="408dp"
android:visibility="invisible" >
</FrameLayout>
</RelativeLayout>
第二
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/tableLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TableRow
android:id="@+id/tableRow1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dip" >
<TextView
android:id="@+id/textView1"
android:text="Column 1"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="@+id/textView2"
android:text="Column 2"
android:textAppearance="?android:attr/textAppearanceLarge" />
</TableRow>
<TableRow
android:id="@+id/tableRow2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dip" >
<ImageView
android:id="@+id/imgView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/android" />
</TableRow>
<TableRow
android:id="@+id/tableRow3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dip" >
<TextView
android:id="@+id/textView3"
android:text="Column 3"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="@+id/textView4"
android:text="Column 4"
android:textAppearance="?android:attr/textAppearanceLarge" />
</TableRow>
</TableLayout>
3.编辑:更正xml文件,现在添加活动:
public class SinglePlayerSp extends Activity implements OnClickListener
{
private final Context mContext = this;
private boolean mBackZoomOne = false;
private FrameLayout frameZoomOne;
private FrameLayout frameZoomTwo;
private static Animator mCurrentAnimatorOne;
private int mShortAnimationDuration;
private float startScaleOne;
private static Animator mCurrentAnimatorTwo;
private float startScaleTwo;
private Rect startBoundsOne;
private Rect startBoundsTwo;
private static View lastViewOne;
private static View lastViewTwo;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_zoom);
frameZoomOne = (FrameLayout) findViewById(R.id.frameZoomOne);
frameZoomTwo = (FrameLayout) findViewById(R.id.frameZoomTwo);
frameZoomOne.setOnClickListener(this);
frameZoomTwo.setOnClickListener(this);
mShortAnimationDuration = getResources().getInteger(android.R.integer.config_mediumAnimTime);
cardItems = getIntent().getParcelableArrayListExtra(CARD_ITEMS);
java.util.Collections.shuffle(cardItems);
}
private void flipCard(boolean playerOneDeck, final int selectionFromPlayer, final boolean result)
{
Card cardItemOne = null;
if (oneCards.get(0) != null)
{
cardItemOne = oneCards.get(0);
}
if (!mBackZoomOne)
{
getFragmentManager().beginTransaction().setCustomAnimations(R.animator.card_flip_right_in,
R.animator.card_flip_right_out, R.animator.card_flip_left_in, R.animator.card_flip_left_out).replace(
R.id.frameZoomOne, new CardBackFragment()).commit();
mBackZoomOne = true;
}
else
{
getFragmentManager().beginTransaction().setCustomAnimations(R.animator.card_flip_right_in,
R.animator.card_flip_right_out, R.animator.card_flip_left_in, R.animator.card_flip_left_out).replace(
R.id.frameZoomOne,
CardFrontFragment.newInstance(cardItemPlayerOne, selectionFromPlayer, playerOneDeck)).commit();
mBackZoomOne = false;
zoomViewOneFromThumb(frameZoomOne, cardItemOne);
}
}
private void zoomViewOneFromThumb(final View thumbView, final Card cardItem)
{
if (mCurrentAnimatorOne != null)
{
mCurrentAnimatorOne.cancel();
}
lastViewOne = thumbView;
View.getDefaultSize(0, 0);
final FrameLayout expandFrameLayout = (FrameLayout) findViewById(R.id.container);
LayoutInflater inflater =
(LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.fragment_card_front_clickable, null);
TableRow rowOne = (TableRow) layout.findViewById(R.id.tableRow1);
rowOne.setOnClickListener(this);
TextView cardone = (TextView) layout.findViewById(R.id.textView1);
TextView cardtwo = (TextView) layout.findViewById(R.id.textView2);
TextView cardthree = (TextView) layout.findViewById(R.id.textView3);
TextView cardfour = (TextView) layout.findViewById(R.id.textView4);
Locale locale = getApplicationContext().getResources().getConfiguration().locale;
cardone.setText(cardItem.TextOne());
cardtwo.setText(cardItem.getTextTwo());
cardthree.setText(cardItem.getTextThree());
cardfour.setText(cardItem.TextFour());
expandFrameLayout.addView(layout);
startBoundsOne = new Rect();
final Rect finalBounds = new Rect();
final Point globalOffset = new Point();
thumbView.getGlobalVisibleRect(startBoundsOne);
findViewById(R.id.containerSp).getGlobalVisibleRect(finalBounds, globalOffset);
startBoundsOne.offset(-globalOffset.x, -globalOffset.y);
finalBounds.offset(-globalOffset.x + 15, -globalOffset.y + 50);
if ((float) finalBounds.width() / finalBounds.height() > (float) startBoundsOne.width()
/ startBoundsOne.height())
{
startScaleOne = (float) startBoundsOne.height() / finalBounds.height();
float startWidth = startScaleOne * finalBounds.width();
float deltaWidth = (startWidth - startBoundsOne.width()) / 2;
startBoundsOne.left -= deltaWidth;
startBoundsOne.right += deltaWidth;
}
else
{
startScaleOne = (float) startBoundsOne.width() / finalBounds.width();
float startHeight = startScaleOne * finalBounds.height();
float deltaHeight = (startHeight - startBoundsOne.height()) / 2;
startBoundsOne.top -= deltaHeight;
startBoundsOne.bottom += deltaHeight;
}
thumbView.setAlpha(0f);
expandFrameLayout.setVisibility(View.VISIBLE);
expandFrameLayout.setPivotX(0f);
expandFrameLayout.setPivotY(0f);
AnimatorSet set = new AnimatorSet();
set.play(ObjectAnimator.ofFloat(expandFrameLayout, View.X, startBoundsOne.left, finalBounds.left)).with(
ObjectAnimator.ofFloat(expandFrameLayout, View.Y, startBoundsOne.top, finalBounds.top)).with(
ObjectAnimator.ofFloat(expandFrameLayout, View.SCALE_X, startScaleOne, 1f)).with(
ObjectAnimator.ofFloat(expandFrameLayout, View.SCALE_Y, startScaleOne, 1f));
set.setDuration(mShortAnimationDuration);
set.setInterpolator(new DecelerateInterpolator());
set.addListener(new AnimatorListenerAdapter()
{
@Override
public void onAnimationEnd(Animator animation)
{
mCurrentAnimatorOne = null;
}
@Override
public void onAnimationCancel(Animator animation)
{
mCurrentAnimatorOne = null;
}
});
set.start();
mCurrentAnimatorOne = set;
startScaleFinal = startScaleOne; // with this or without this, i have the same problem
}
private void minimizeViewOne(final View expandFrameLayout)
{
AnimatorSet set = new AnimatorSet();
set.play(ObjectAnimator.ofFloat(expandFrameLayout, View.X, startBoundsOne.left)).with(
ObjectAnimator.ofFloat(expandFrameLayout, View.Y, startBoundsOne.top)).with(
ObjectAnimator.ofFloat(expandFrameLayout, View.SCALE_X, startScaleFinal)).with(
ObjectAnimator.ofFloat(expandFrameLayout, View.SCALE_Y, startScaleFinal));
set.setDuration(mShortAnimationDuration);
set.setInterpolator(new DecelerateInterpolator());
set.addListener(new AnimatorListenerAdapter()
{
@Override
public void onAnimationEnd(Animator animation)
{
lastViewOne.setAlpha(1f);
expandFrameLayout.setVisibility(View.GONE);
mCurrentAnimatorOne = null;
}
@Override
public void onAnimationCancel(Animator animation)
{
lastViewOne.setAlpha(1f);
expandFrameLayout.setVisibility(View.GONE);
mCurrentAnimatorOne = null;
}
});
set.start();
mCurrentAnimatorOne = set;
}
}
好的,这就是完整的代码。最后是一个 onClick 方法,在那里我收到用户操作。从那里我调用minimizeView 方法,然后进行一些检查,然后我调用flipCard。就这样。