Android 進出activity的滑動動畫效果

騷劍客發表於2016-05-26

最近做了一個專案要求類似QQ中的SlidingMenu中選單的點選效果.

  1. 即點選之後跳到A activity,這時候就要求A activity有一個左滑的動畫效果
  2. 點選A activity上返回按鈕或則點選手機的返回鍵也要觸發一個返回動畫效果
  3. 在A activity上新增手勢返回滑動的動畫效果.

這裡我們先要在專案的res中新建一個anim檔案然後新增如下上個動畫效果的xml檔案:

base_slide_remain.xml 

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
    <translate
        android:duration="300"
        android:fromXDelta="0"
        android:interpolator="@android:anim/decelerate_interpolator"
        android:toXDelta="0" />

</set>
base_slide_right_in.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
    <translate
        android:duration="300"
        android:fromXDelta="100.0%"
        android:interpolator="@android:anim/decelerate_interpolator"
        android:toXDelta="0.0%" />

</set>

base_slide_right_out.xml


<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >

    <translate
        android:duration="300"
        android:fromXDelta="0.0%"
        android:interpolator="@android:anim/accelerate_interpolator"
        android:toXDelta="100.0%" />
</set>

以為這裡我們要對頁面做一個手勢的動畫效果事件的處理,我們可以自定義一個佈局

SlideFinishLayout.java
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.widget.LinearLayout;

/**
 * Created by shaolin on 5/26/16.
 */
public class SlideFinishLayout extends LinearLayout implements View.OnTouchListener {


    //手指向右滑動時的最小速度
    private static final int XSPEED_MIN = 200;

    //手指向右滑動時的最小距離
    private static final int XDISTANCE_MIN = 150;

    //記錄手指按下時的橫座標。
    private float xDown;

    //記錄手指移動時的橫座標。
    private float xMove;

    //用於計算手指滑動的速度。
    private VelocityTracker mVelocityTracker;

    public SlideFinishLayout(Context context) {
       this(context, null);
    }

    public SlideFinishLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        setOnTouchListener(this); //設定在本身上的滑動事件
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        createVelocityTracker(event);
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                xDown = event.getRawX();
                break;
            case MotionEvent.ACTION_MOVE:
                xMove = event.getRawX();
                //活動的距離
                int distanceX = (int) (xMove - xDown);
                //獲取順時速度
                int xSpeed = getScrollVelocity();
                //當滑動的距離大於我們設定的最小距離且滑動的瞬間速度大於我們設定的速度時,返回到上一個activity
                if (distanceX > XDISTANCE_MIN && xSpeed > XSPEED_MIN) {
                    if (mOnSlideFinishListener != null) {
                        mOnSlideFinishListener.onSlideFinish();
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                recycleVelocityTracker();
                break;
            default:
                break;
        }
        return true;
    }

    /**
     * 建立VelocityTracker物件,並將觸控content介面的滑動事件加入到VelocityTracker當中。
     *
     * @param event
     */
    private void createVelocityTracker(MotionEvent event) {
        if (mVelocityTracker == null) {
            mVelocityTracker = VelocityTracker.obtain();
        }
        mVelocityTracker.addMovement(event);
    }

    /**
     * 回收VelocityTracker物件。
     */
    private void recycleVelocityTracker() {
        mVelocityTracker.recycle();
        mVelocityTracker = null;
    }

    /**
     * 獲取手指在content介面滑動的速度。
     *
     * @return 滑動速度,以每秒鐘移動了多少畫素值為單位。
     */
    private int getScrollVelocity() {
        mVelocityTracker.computeCurrentVelocity(1000);
        int velocity = (int) mVelocityTracker.getXVelocity();
        return Math.abs(velocity);
    }

    private OnSlideFinishListener mOnSlideFinishListener;

    public void setOnSlideFinishListener(OnSlideFinishListener listener) {
        mOnSlideFinishListener = listener;
    }

    public interface OnSlideFinishListener {
        void onSlideFinish();
    }
}

上面的準備好了,現在我們就來說說怎麼實現對應的效果:

這裡我們可以先建一個AActivity然後我們在這個AActivity上進行進入/返回手勢/點選返回的效果展示
AActivity.java
import android.os.Bundle;
import android.view.View;

import com.hardware.mask.R;
import com.hardware.mask.app.base.BaseActivity;
import com.hardware.mask.widget.SlideFinishLayout;

import org.chiki.base.widget.TitleBar;

/**
 * Created by shaolin on 5/19/16.
 */
public class AActivity extends Activity {

    private SlideFinishLayout mSFL;

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

        initTitleBar();  
        initView();
    }

    @Override
    public void onBackPressed() {
    	//這裡是我們點選手機返回鍵的動畫
        super.onBackPressed();
        backTransition();
    }


    private void initTitleBar() {
    	//TitleBar這個是自己封裝的一個標題bar,大家只要知道這裡的點選事件那兩句就OK了
        TitleBar bar = (TitleBar) findViewById(R.id.title_bar);
        bar.setText("關於我們");
        bar.setLeftDrawableRes(R.mipmap.user_return);
        bar.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
            //這裡的兩句是返回的時候finish在加上動畫效果,還有就是overridePendingTransition必須放在finish後面才有效果
                finish();
                backTransition();  
            }
        });
    }

    private void initView() {
    	//獲取我們剛剛設定的那個佈局,然後通過介面實現手勢的事件處理
        mSFL = (SlideFinishLayout) findViewById(R.id.slideFinishLayout);
        mSFL.setOnSlideFinishListener(new SlideFinishLayout.OnSlideFinishListener() {
            @Override
            public void onSlideFinish() {
                finish();
                backTransition();
            }
        });
    }

    public void backTransition() {
        overridePendingTransition(0, R.anim.base_slide_right_out);
    }
}
aactivity.XML
<?xml version="1.0" encoding="utf-8"?>
<com.hardware.mask.widget.SlideFinishLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:hk="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    android:id="@+id/slideFinishLayout"
    android:orientation="vertical">

    <org.chiki.base.widget.TitleBar
        android:id="@+id/title_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        hk:center_textColor="@color/black" />

</com.hardware.mask.widget.SlideFinishLayout>

1.進入
startActivity(new Intent(this, AActivity.class));
overridePendingTransition(R.anim.base_slide_right_in, R.anim.base_slide_remain);

2.返回手勢
SlideFinishLayout mSFL = (SlideFinishLayout) findViewById(R.id.slideFinishLayout);
mSFL.setOnSlideFinishListener(new SlideFinishLayout.OnSlideFinishListener() {
    @Override
    public void onSlideFinish() {
        finish();
        backTransition();
    }
});

3.返回處理(這裡有兩個)

  • 手機返回鍵

 @Override
    public void onBackPressed() {
        super.onBackPressed();
        backTransition();
    }

  • 按鈕返回

finish();
backTransition();

相關文章