Android 基于控件位置的缩放转场动画

    public static void startWithFragment(Context context, String fragmentName, Bundle args,
            Fragment resultTo, int resultRequestCode, String titleResPackageName, int titleResId,
            CharSequence title, boolean isShortcut) {
        Intent intent = onBuildStartFragmentIntent(context, fragmentName, args, titleResPackageName,
                titleResId, title, isShortcut);
        android.util.Log.e("SHUIYES","mOptsBundle: "+mOptsBundle);
        if (resultTo == null) {
            if(mOptsBundle != null) {
                context.startActivity(intent,mOptsBundle);
                mOptsBundle = null;
            }else{
                context.startActivity(intent);
            }
        } else {
            resultTo.startActivityForResult(intent, resultRequestCode);
        }
    }

    private static Bundle mOptsBundle = null;
    private static float[] mAnimationBounds = new float[4];
    public static void setSubSettingsOpenEnterAnimation(View v){
        int left = 0, top = 0;
        int width = v.getMeasuredWidth(), height = v.getMeasuredHeight();
        int[] location = new int[2];
        v.getLocationOnScreen(location);
        mAnimationBounds[0] = location[0];
        mAnimationBounds[1] = location[1];
        mAnimationBounds[2] = width;
        mAnimationBounds[3] = height;
        // or makeClipRevealAnimation (system api)
        ActivityOptions opts = ActivityOptions.makeScaleUpAnimation(v, left, top, width, height);
        mOptsBundle = opts != null ? opts.toBundle() : null;
    }

    // cp form Apptransition.java
    private static float computePivot(float startPos, float finalScale) {
        final float denom = finalScale-1f;
        if (Math.abs(denom) < .0001f) {
            return startPos;
        }
        return -startPos / denom;
    }

    public static AnimationSet getSubSettingsCloseExitAnimation(float screenW, float screenH){
        float startX = mAnimationBounds[0];
        float startY = mAnimationBounds[1];
        float startW = mAnimationBounds[2];
        float startH = mAnimationBounds[3];

        float scaleW = startW / screenW;
        float scaleH = startH / screenH;
        Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH,
                computePivot(startX,scaleW), computePivot(startY,scaleH));
        scale.setRepeatCount(0);
        scale.setFillAfter(true);
        scale.setDuration(500);

        Animation alpha = new AlphaAnimation(1, 0);
        alpha.setRepeatCount(0);
        alpha.setFillAfter(true);
        alpha.setDuration(500);

        AnimationSet set = new AnimationSet(false);
        set.addAnimation(scale);
        set.addAnimation(alpha);
        return set;
    }


/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.settings;

import android.util.Log;
import android.view.Display;
import android.view.KeyEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.Animation.AnimationListener;

/**
 * Stub class for showing sub-settings; we can't use the main Settings class
 * since for our app it is a special singleTask class.
 */
public class SubSettings extends SettingsActivity {

    @Override
    public boolean onNavigateUp() {
        finish();
        return true;
    }

    @Override
    protected boolean isValidFragment(String fragmentName) {
        Log.d("SubSettings", "Launching fragment " + fragmentName);
        return true;
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {

        if (keyCode == KeyEvent.KEYCODE_BACK){
            finishWithAnimation();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    public void finishWithAnimation(){
        final View root  = this.findViewById(R.id.first_layer);
        if(root == null){
            finish();
            return;
        }
        Display display = this.getWindowManager().getDefaultDisplay();
        final AnimationSet set = Utils.getSubSettingsCloseExitAnimation(display.getWidth(),display.getHeight());
        set.setAnimationListener(new AnimationListener() {

            @Override
            public void onAnimationStart(Animation animation) {
                //ignore
            }

            @Override
            public void onAnimationRepeat(Animation animation) {
                //ignore
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                finish();
            }
        });

        root.clearAnimation();
        root.setAnimation(set);
        set.startNow();
    }

    @Override
    public void finish() {
        super.finish();
        // disable Activity default animation
        overridePendingTransition(0, 0);
    }
}


其中要对Subettings设置透明Style,

        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:windowAnimationStyle">@null</item>
        <item name="android:windowIsTranslucent">true</item>

还有就是如果系统主题是 @android:style/Theme.Material , 则要对 Subettings 设置 Theme.Translucent ,不然上面设置无效

<activity android:name=".SubSettings"
                android:theme="@android:style/Theme.Translucent.NoTitleBar"



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android实现控件缩放移动功能,可以通过自定义控件并重写其onTouchEvent()方法来实现。具体步骤如下: 1. 在自定义控件类中,实现GestureDetector.OnGestureListener接口和ScaleGestureDetector.OnScaleGestureListener接口,用于监听手势事件。 2. 在onTouchEvent()方法中,将MotionEvent对象传递给GestureDetector和ScaleGestureDetector对象,分别监听手势事件。 3. 在GestureDetector的onScroll()方法中,处理手指拖动事件,计算控件移动的距离,并将其应用到控件上。 4. 在ScaleGestureDetector的onScale()方法中,处理缩放手势事件,计算控件缩放比例,并将其应用到控件上。 5. 需要注意的是,缩放功能需要在控件的父布局中开启clipChildren属性,以保证控件可以在缩放时不会超出父布局的边界。 示例代码如下: ```java public class ZoomView extends View implements GestureDetector.OnGestureListener, ScaleGestureDetector.OnScaleGestureListener { private GestureDetector mGestureDetector; private ScaleGestureDetector mScaleGestureDetector; private float mScaleFactor = 1.0f; private float mLastTouchX; private float mLastTouchY; private float mPosX; private float mPosY; public ZoomView(Context context) { super(context); mGestureDetector = new GestureDetector(context, this); mScaleGestureDetector = new ScaleGestureDetector(context, this); } @Override public boolean onTouchEvent(MotionEvent motionEvent) { mGestureDetector.onTouchEvent(motionEvent); mScaleGestureDetector.onTouchEvent(motionEvent); final int action = motionEvent.getAction(); switch (action & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: { final float x = motionEvent.getX(); final float y = motionEvent.getY(); mLastTouchX = x; mLastTouchY = y; break; } case MotionEvent.ACTION_MOVE: { final float x = motionEvent.getX(); final float y = motionEvent.getY(); final float dx = x - mLastTouchX; final float dy = y - mLastTouchY; mPosX += dx; mPosY += dy; invalidate(); mLastTouchX = x; mLastTouchY = y; break; } } return true; } @Override public boolean onScale(ScaleGestureDetector scaleGestureDetector) { mScaleFactor *= scaleGestureDetector.getScaleFactor(); mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f)); invalidate(); return true; } @Override public boolean onScaleBegin(ScaleGestureDetector scaleGestureDetector) { return true; } @Override public void onScaleEnd(ScaleGestureDetector scaleGestureDetector) { } @Override public boolean onDown(MotionEvent motionEvent) { return true; } @Override public void onShowPress(MotionEvent motionEvent) { } @Override public boolean onSingleTapUp(MotionEvent motionEvent) { return true; } @Override public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent1, float distanceX, float distanceY) { mPosX -= distanceX; mPosY -= distanceY; invalidate(); return true; } @Override public void onLongPress(MotionEvent motionEvent) { } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.save(); canvas.scale(mScaleFactor, mScaleFactor); canvas.translate(mPosX / mScaleFactor, mPosY / mScaleFactor); // 绘制控件内容 canvas.restore(); } } ``` 在该示例中,我们重写了onTouchEvent()方法,使用GestureDetector和ScaleGestureDetector对象分别监听拖动事件和缩放事件。在onScale()方法中,我们计算了控件缩放比例,并在onScroll()方法中计算了控件的移动距离。最后,在onDraw()方法中,我们将缩放和移动的变换应用到画布上,然后在画布上绘制控件的内容。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值