天天看點

android傳回功能實作,Android仿iOS實作側滑傳回功能(類似微信)

我們都知道側滑傳回操作是 iOS 裡面比較常見的功能,一般是手指在靠近手機螢幕左邊緣向右滑動就可以關閉目前的界面,iOS 系統提供了這樣的 API,但是 Android 怎麼實作呢?網上找了許多方法,比較了一下,個人覺得還是這個比較友善也容易了解,

先上個效果再說:

android傳回功能實作,Android仿iOS實作側滑傳回功能(類似微信)

原理

Activity 本身是不可以滑動的,但是我們可以制造一個正在滑動 Activity 的假象,使得看起來這個 Activity 正在被手指滑動。其原理其實很簡單,我們滑動的其實是 Activity 裡面的可見View元素,而我們将 Activity 設定為透明的,這樣當 View 滑過的時候,由于 Activity 的底部是透明的,我們就可以在滑動過程中看到下面的Activity,這樣看起來就是在滑動 Activity。是以 Activity 滑動效果分兩步:

設定 Activity 透明

滑動 View

實作

1、設定透明:

資源檔案 values -> styles.xml 添加如下代碼,搞一個透明的主題。

@android:color/transparent

true

然後在 AndroidManifest.xml 檔案裡面給相應的 Activity 設定透明的主題。比如 MainActivity :

android:name="com.example.test.MainActivity"

android:theme="@style/Transparent" >

2、滑動View:

先看看 Activity 的層次結構:我們用的 Activity 的 xml 的根 View 并不是 Activity 的根 View ,在它上面還有一個父 View, id 是 android.R.id.content,再向上一層,還有一個view,它是一個 LinearLayout,它除了放置我們建立的 View 之外,還放置我們的 xml 之外的一些東西比如放 ActionBar 或者标題欄什麼的。而再往上一級,就到了 Activity 的根 View —— DecorView,結構

如下圖所示:

android傳回功能實作,Android仿iOS實作側滑傳回功能(類似微信)

要做到像 iOS 那樣可以滑動整個 Activity ,隻滑動我們在xml裡面建立的 View 顯然是不對的,因為我們還有标題欄、ActionBar 什麼的,是以我們要滑動的應該是 DecorView 或者倒數第二層的那個 View。

而要滑動 View的話,我們要重寫其父視窗的 onInterceptTouchEvent 以及 onTouchEvent(當然使用 setOnTouchListener 不是不可能,但是如果子 View 裡面有一個消費了 onTouch 事件,那麼也就接收不到了),但是視窗的建立過程不是我們能控制的,DecorView 的建立都不是我們能幹預的。

解決辦法就是,我們自己建立一個 SwipeLayout,然後人為地插入頂層 View 中,放置在 DecorView 和其下面的 LinearLayout 中間,随着手指的滑動,不斷改變 SwipeLayout 的子 View ——曾經是 DecorView 的子 View——的位置,這樣我們就可以控制 Activity 的滑動啦。我們在 Activity 的 onPostCreate 方法中調用swipeLayout.replaceLayer 替換我們的 SwipeLayout,代碼如下:

public void replaceLayer(Activity activity) {

mActivity = activity;

screenWidth = getScreenWidth(activity);

setClickable(true);

//擷取 Activity 的 根 View

ViewGroup root = (ViewGroup) activity.getWindow().getDecorView();

//擷取 根 View 下面的第一個 View,并儲存到 content

content = root.getChildAt(0);

ViewGroup.LayoutParams params = content.getLayoutParams();

ViewGroup.LayoutParams params2 = new ViewGroup.LayoutParams(-1, -1);

//把根 View 下面原來的第一個 View 删除

root.removeView(content);

//把 content 添加到 SwipeLayout

this.addView(content, params2);

//再把 SwipeLayout 添加到根 View 裡面

root.addView(this, params);

sideWidth = (int) (sideWidthInDP * activity.getResources().getDisplayMetrics().density);

}

然後把這些寫成一個 SwipeActivity 要求實作側滑傳回的 Activity 繼承 SwipeActivity , SwipeActivity 繼承 FragmentActivity 或者 Activity 。比如 MainActivity:

public class SwipeActivity extends FragmentActivity {

...

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

}

...

}

public class MainActivity extends SwipeActivity {

...

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

}

...

}

總結

其實在工作中,開發一個項目基本都會封裝一個 BaseActivity,隻要 BaseActivity 繼承 SwipeActivity ,然後所有繼承 BaseActivity 的 Activity 就都可以實作側滑傳回了, 如果有不需要實作這個功能的隻需要調用 SwipeActivity 裡面的一個方法:

public void setSwipeEnabled(boolean swipeEnabled) 參數傳一個 false 就好了。是不是很友善!

其實另外還暴露出來一個方法:

public void setSwipeAnyWhere(boolean swipeAnyWhere) 設定是否螢幕任意位置右滑關閉,因為預設是隻能左邊緣右滑傳回。

最後

以上就是本文的全部内容,希望對大家的學習有所幫助,也希望大家多多支援我們。

時間: 2017-11-29