Quellcode durchsuchen

添加右划退出操作

316044749 vor 7 Jahren
Ursprung
Commit
a0cff3996e
23 geänderte Dateien mit 2833 neuen und 16 gelöschten Zeilen
  1. 4 0
      app/src/main/AndroidManifest.xml
  2. 39 8
      app/src/main/java/com/ynstkz/shitu/android/activity/HomeActivity.java
  3. 7 0
      app/src/main/java/com/ynstkz/shitu/android/activity/LoginActivity.java
  4. 31 0
      app/src/main/java/com/ynstkz/shitu/android/activity/LoginPhoneCodeActivity.java
  5. 1 1
      app/src/main/java/com/ynstkz/shitu/android/base/TitleBarActivity.java
  6. 5 0
      app/src/main/res/anim/slide_in_left.xml
  7. 7 0
      app/src/main/res/anim/slide_in_right.xml
  8. 7 0
      app/src/main/res/anim/slide_out_left.xml
  9. 7 0
      app/src/main/res/anim/slide_out_right.xml
  10. 195 0
      app/src/main/res/layout/activity_login_phonecode.xml
  11. 4 2
      app/src/main/res/layout/view_main_bottom.xml
  12. 1 0
      app/src/main/res/values/colors.xml
  13. 7 0
      app/src/main/res/values/styles.xml
  14. 42 4
      library/src/main/java/com/common/library/base/LibBaseActivity.java
  15. 1 1
      library/src/main/java/com/common/library/view/MaterialDialog.java
  16. 605 0
      library/src/main/java/com/common/library/view/swipeback/SwipeBackLayout.java
  17. 103 0
      library/src/main/java/com/common/library/view/swipeback/Utils.java
  18. 1580 0
      library/src/main/java/com/common/library/view/swipeback/ViewDragHelper.java
  19. 50 0
      library/src/main/java/com/common/library/view/swipeback/app/SwipeBackActivity.java
  20. 21 0
      library/src/main/java/com/common/library/view/swipeback/app/SwipeBackActivityBase.java
  21. 62 0
      library/src/main/java/com/common/library/view/swipeback/app/SwipeBackActivityHelper.java
  22. 48 0
      library/src/main/java/com/common/library/view/swipeback/app/SwipeBackPreferenceActivity.java
  23. 6 0
      library/src/main/res/layout/swipeback_layout.xml

+ 4 - 0
app/src/main/AndroidManifest.xml

@@ -51,6 +51,10 @@
         <activity android:name=".activity.RegisterSubmitActivity"
             android:screenOrientation="portrait"/>
 
+        <!--验证码登陆-->
+        <activity android:name=".activity.LoginPhoneCodeActivity"
+            android:screenOrientation="portrait"/>
+
         <!--定位服务-->
         <meta-data android:name="com.ynstkz.shitu.android.demo" android:value="a78b553a67f68d1d980f908eb1f034a8"/>
         <service android:name="com.amap.api.location.APSService"/>

+ 39 - 8
app/src/main/java/com/ynstkz/shitu/android/activity/HomeActivity.java

@@ -9,8 +9,10 @@ import android.support.v4.app.Fragment;
 import android.support.v4.content.ContextCompat;
 import android.util.Log;
 import android.view.View;
+import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.RelativeLayout;
+import android.widget.TextView;
 
 import com.amap.api.location.AMapLocation;
 import com.amap.api.location.AMapLocationClient;
@@ -39,6 +41,18 @@ public class HomeActivity extends TitleBarActivity implements AMapLocationListen
     RelativeLayout rlLabUsercenter;
     @Bind(R.id.ll_bottom_lab)
     LinearLayout llBottomLab;
+    @Bind(R.id.iv_lab_home)
+    ImageView ivLabHome;
+    @Bind(R.id.tv_lab_home)
+    TextView tvLabHome;
+    @Bind(R.id.iv_lab_nearby)
+    ImageView ivLabNearby;
+    @Bind(R.id.tv_lab_nearby)
+    TextView tvLabNearby;
+    @Bind(R.id.iv_lab_usercenter)
+    ImageView ivLabUsercenter;
+    @Bind(R.id.tv_lab_usercenter)
+    TextView tvLabUsercenter;
 
     private Fragment[] mFragments;
     private int tabIndex;
@@ -51,6 +65,7 @@ public class HomeActivity extends TitleBarActivity implements AMapLocationListen
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+        setSwipeBackEnable(false);
         ButterKnife.bind(this);
         initView();
         initData();
@@ -62,7 +77,7 @@ public class HomeActivity extends TitleBarActivity implements AMapLocationListen
         return R.layout.activity_home;
     }
 
-    private void initView(){
+    private void initView() {
         mFragments = new Fragment[3];
         mFragments[0] = getSupportFragmentManager().findFragmentById(R.id.fm_home);
         mFragments[1] = getSupportFragmentManager().findFragmentById(R.id.fm_nearby);
@@ -70,7 +85,7 @@ public class HomeActivity extends TitleBarActivity implements AMapLocationListen
         changleLayout(0);
     }
 
-    private void initData(){
+    private void initData() {
         mlocationClient = new AMapLocationClient(getApplicationContext());
         //初始化定位参数
         mLocationOption = new AMapLocationClientOption();
@@ -86,7 +101,7 @@ public class HomeActivity extends TitleBarActivity implements AMapLocationListen
         mlocationClient.setLocationOption(mLocationOption);
     }
 
-    private void setListener(){
+    private void setListener() {
         //首页
         rlLabHome.setOnClickListener(new View.OnClickListener() {
             @Override
@@ -105,7 +120,7 @@ public class HomeActivity extends TitleBarActivity implements AMapLocationListen
         rlLabUsercenter.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View view) {
-                if(isLogin()){
+                if (isLogin()) {
                     changleLayout(2);
                 } else {
                     startActivityForResult(new Intent(HomeActivity.this, LoginActivity.class), 10);
@@ -123,12 +138,28 @@ public class HomeActivity extends TitleBarActivity implements AMapLocationListen
         this.tabIndex = tabIndex;
         getSupportFragmentManager().beginTransaction().hide(mFragments[0]).hide(mFragments[1])
                 .hide(mFragments[2]).show(mFragments[tabIndex]).commitAllowingStateLoss();
+        ivLabHome.setImageResource(R.drawable.lab_home_icon);
+        ivLabNearby.setImageResource(R.drawable.lab_neayby_icon);
+        ivLabUsercenter.setImageResource(R.drawable.lab_usercenter_icon);
+        tvLabHome.setTextColor(getResources().getColor(R.color.color_999));
+        tvLabNearby.setTextColor(getResources().getColor(R.color.color_999));
+        tvLabUsercenter.setTextColor(getResources().getColor(R.color.color_999));
         switch (tabIndex) {
-
+            case 0:
+                ivLabHome.setImageResource(R.drawable.lab_home_icon_press);
+                tvLabHome.setTextColor(getResources().getColor(R.color.main_color));
+                break;
+            case 1:
+                ivLabNearby.setImageResource(R.drawable.lab_neayby_icon_press);
+                tvLabNearby.setTextColor(getResources().getColor(R.color.main_color));
+                break;
+            case 2:
+                ivLabUsercenter.setImageResource(R.drawable.lab_usercenter_icon_press);
+                tvLabUsercenter.setTextColor(getResources().getColor(R.color.main_color));
+                break;
         }
     }
 
-
     @Override
     public void onLocationChanged(AMapLocation amapLocation) {
         if (amapLocation != null) {
@@ -158,7 +189,7 @@ public class HomeActivity extends TitleBarActivity implements AMapLocationListen
             //启动定位
             mlocationClient.startLocation();
         } else if (ActivityCompat.shouldShowRequestPermissionRationale(this,
-                Manifest.permission.ACCESS_COARSE_LOCATION)){
+                Manifest.permission.ACCESS_COARSE_LOCATION)) {
             ConfirmationDialogFragment
                     .newInstance(R.string.app_name,
                             new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
@@ -175,7 +206,7 @@ public class HomeActivity extends TitleBarActivity implements AMapLocationListen
     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
         switch (requestCode) {
             case 10:
-                if(resultCode == RESULT_OK) { //登陆成功
+                if (resultCode == RESULT_OK) { //登陆成功
                     changleLayout(2);
                 }
                 break;

+ 7 - 0
app/src/main/java/com/ynstkz/shitu/android/activity/LoginActivity.java

@@ -80,5 +80,12 @@ public class LoginActivity extends TitleBarActivity {
                 startActivity(new Intent(LoginActivity.this, RegisterActivity.class));
             }
         });
+        //验证码登陆
+        tvPhoneCodeLogin.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                startActivity(new Intent(LoginActivity.this, LoginPhoneCodeActivity.class));
+            }
+        });
     }
 }

+ 31 - 0
app/src/main/java/com/ynstkz/shitu/android/activity/LoginPhoneCodeActivity.java

@@ -0,0 +1,31 @@
+package com.ynstkz.shitu.android.activity;
+
+import android.os.Build;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.view.View;
+
+import com.ynstkz.shitu.android.R;
+import com.ynstkz.shitu.android.base.TitleBarActivity;
+import com.ynstkz.shitu.android.utils.StatusBarUtil;
+
+/**
+ * 作者:fuchangle on 2018/2/7 15:02
+ */
+
+public class LoginPhoneCodeActivity extends TitleBarActivity{
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        StatusBarUtil.setTransparent(this);
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            setStatusBarColor(this, View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
+        }
+    }
+
+    @Override
+    protected int getLayoutId() {
+        return R.layout.activity_login_phonecode;
+    }
+}

+ 1 - 1
app/src/main/java/com/ynstkz/shitu/android/base/TitleBarActivity.java

@@ -22,7 +22,7 @@ public abstract class TitleBarActivity extends BaseActivity{
         super.onCreate(savedInstanceState);
         setContentView(getLayoutId());
         StatusBarUtil.setColorNoTranslucent(this, getResources().getColor(R.color.colorPrimary));
-        mToolbarTitle = findViewById(R.id.tv_title);
+        mToolbarTitle = (TextView)findViewById(R.id.tv_title);
         if (mToolbarTitle != null) {
             //getTitle()的值是activity的android:lable属性值
             mToolbarTitle.setText(getTitle());

+ 5 - 0
app/src/main/res/anim/slide_in_left.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+    <translate android:fromXDelta="-100%p" android:toXDelta="0"
+        android:duration="300"/>
+</set>

+ 7 - 0
app/src/main/res/anim/slide_in_right.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+    <translate android:fromXDelta="100%p" android:toXDelta="0"
+        android:duration="300"/>
+    <alpha android:fromAlpha="1.0" android:toAlpha="1.0"
+        android:duration="300" />
+</set>

+ 7 - 0
app/src/main/res/anim/slide_out_left.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+    <translate android:fromXDelta="0" android:toXDelta="-100%p"
+        android:duration="300"/>
+    <alpha android:fromAlpha="1.0" android:toAlpha="1.0"
+        android:duration="300" />
+</set>

+ 7 - 0
app/src/main/res/anim/slide_out_right.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+    <translate android:fromXDelta="0" android:toXDelta="100%p"
+        android:duration="300"/>
+    <alpha android:fromAlpha="1.0" android:toAlpha="1.0"
+        android:duration="300" />
+</set>

+ 195 - 0
app/src/main/res/layout/activity_login_phonecode.xml

@@ -0,0 +1,195 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:background="@color/white">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        android:paddingLeft="@dimen/default_content_margin"
+        android:paddingTop="@dimen/default_content_margin"
+        android:paddingRight="@dimen/default_content_margin">
+
+        <RelativeLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content">
+
+            <ImageView
+                android:id="@+id/iv_cancel"
+                android:layout_width="@dimen/company_20dp"
+                android:layout_height="@dimen/company_20dp"
+                android:src="@drawable/login_cancel_icon" />
+
+            <TextView
+                android:id="@+id/tv_register"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_alignParentRight="true"
+                android:text="注册"
+                android:textColor="@color/main_color"
+                android:textSize="@dimen/company_18sp" />
+
+        </RelativeLayout>
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="@dimen/company_30dp"
+            android:gravity="center_horizontal"
+            android:orientation="vertical">
+
+            <ImageView
+                android:layout_width="62dp"
+                android:layout_height="62dp"
+                android:src="@drawable/logo" />
+
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="@dimen/company_6dp"
+                android:text="仕  途  网"
+                android:textColor="@color/main_color"
+                android:textSize="@dimen/company_18sp"
+                android:textStyle="bold" />
+
+        </LinearLayout>
+
+        <TextView
+            android:id="@+id/tv_login"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="@dimen/company_20dp"
+            android:gravity="right"
+            android:text="普通方式登录"
+            android:textColor="@color/main_color"
+            android:textSize="@dimen/company_14sp" />
+
+        <EditText
+            android:id="@+id/edit_username"
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/company_50dp"
+            android:layout_marginTop="@dimen/company_10dp"
+            android:background="@drawable/shapre_default_edit_bg"
+            android:hint="请输入用户名称/手机号/邮箱"
+            android:maxLines="1"
+            android:textCursorDrawable="@null"
+            android:textSize="@dimen/company_14sp" />
+
+        <EditText
+            android:id="@+id/edit_verification_code"
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/company_50dp"
+            android:layout_marginTop="@dimen/company_20dp"
+            android:background="@drawable/shapre_default_edit_bg"
+            android:hint="请输入验证码"
+            android:inputType="textPassword"
+            android:maxLines="1"
+            android:textCursorDrawable="@null"
+            android:textSize="@dimen/company_14sp" />
+
+        <TextView
+            android:id="@+id/tv_forget_pw"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="@dimen/company_10dp"
+            android:gravity="right"
+            android:text="忘记密码"
+            android:textColor="@color/main_color"
+            android:textSize="@dimen/company_14sp" />
+
+        <Button
+            android:id="@+id/btn_login"
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/company_50dp"
+            android:layout_marginTop="@dimen/company_20dp"
+            android:background="@drawable/shape_default_btn_bg"
+            android:text="登录"
+            android:textColor="@color/white"
+            android:textSize="@dimen/company_16sp" />
+
+    </LinearLayout>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="true"
+        android:orientation="vertical">
+
+        <FrameLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="@dimen/company_20dp"
+            android:layout_marginRight="@dimen/company_20dp">
+
+            <TextView
+                android:layout_width="match_parent"
+                android:layout_height="@dimen/company_1dp"
+                android:layout_gravity="center_vertical"
+                android:background="@color/main_color" />
+
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_horizontal"
+                android:background="@color/white"
+                android:padding="@dimen/company_10dp"
+                android:paddingRight="@dimen/company_10dp"
+                android:text="第三方账户登录"
+                android:textColor="@color/main_color" />
+
+        </FrameLayout>
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            android:layout_marginTop="@dimen/company_10dp"
+            android:layout_marginBottom="@dimen/company_25dp">
+
+            <RelativeLayout
+                android:layout_width="0dp"
+                android:layout_weight="1"
+                android:layout_height="wrap_content">
+
+                <ImageView
+                    android:layout_width="@dimen/company_50dp"
+                    android:layout_height="@dimen/company_50dp"
+                    android:background="@drawable/weixin_icon"
+                    android:layout_centerInParent="true"/>
+
+            </RelativeLayout>
+
+            <RelativeLayout
+                android:layout_width="0dp"
+                android:layout_weight="1"
+                android:layout_height="wrap_content">
+
+                <ImageView
+                    android:layout_width="@dimen/company_50dp"
+                    android:layout_height="@dimen/company_50dp"
+                    android:background="@drawable/qq_icon"
+                    android:layout_centerInParent="true"/>
+
+            </RelativeLayout>
+
+            <RelativeLayout
+                android:layout_width="0dp"
+                android:layout_weight="1"
+                android:layout_height="wrap_content">
+
+                <ImageView
+                    android:layout_width="@dimen/company_50dp"
+                    android:layout_height="@dimen/company_50dp"
+                    android:background="@drawable/weibo_icon"
+                    android:layout_centerInParent="true"/>
+
+            </RelativeLayout>
+
+        </LinearLayout>
+
+    </LinearLayout>
+
+</RelativeLayout>

+ 4 - 2
app/src/main/res/layout/view_main_bottom.xml

@@ -21,10 +21,10 @@
 
             <ImageView
                 android:id="@+id/iv_lab_home"
-                android:layout_width="@dimen/lab_size"
+                android:layout_width="wrap_content"
                 android:layout_height="@dimen/lab_size"
                 android:layout_gravity="center_horizontal"
-                android:src="@drawable/lab_home_icon"/>
+                android:src="@drawable/lab_home_icon" />
 
             <TextView
                 android:id="@+id/tv_lab_home"
@@ -53,6 +53,7 @@
             android:orientation="vertical">
 
             <ImageView
+                android:id="@+id/iv_lab_nearby"
                 android:layout_width="@dimen/lab_size"
                 android:layout_height="@dimen/lab_size"
                 android:layout_gravity="center_horizontal"
@@ -85,6 +86,7 @@
             android:orientation="vertical">
 
             <ImageView
+                android:id="@+id/iv_lab_usercenter"
                 android:layout_width="@dimen/lab_size"
                 android:layout_height="@dimen/lab_size"
                 android:layout_gravity="center_horizontal"

+ 1 - 0
app/src/main/res/values/colors.xml

@@ -10,4 +10,5 @@
     <color name="translucence">#0e000000</color>
 
     <color name="default_bg">#F0F0F0</color>
+    <color name="color_999">#999999</color>
 </resources>

+ 7 - 0
app/src/main/res/values/styles.xml

@@ -8,4 +8,11 @@
         <item name="colorAccent">@color/colorAccent</item>
     </style>
 
+    <style name="RightInRightOutAnim" parent="@android:style/Animation.Activity">
+        <item name="android:activityOpenEnterAnimation">@anim/slide_in_right</item>
+        <item name="android:activityCloseEnterAnimation">@anim/slide_in_left</item>
+        <item name="android:activityOpenExitAnimation">@anim/slide_out_left</item>
+        <item name="android:activityCloseExitAnimation">@anim/slide_out_right</item>
+    </style>
+
 </resources>

+ 42 - 4
library/src/main/java/com/common/library/base/LibBaseActivity.java

@@ -1,20 +1,58 @@
 package com.common.library.base;
 
 import android.os.Bundle;
-import android.os.PersistableBundle;
 import android.support.v7.app.AppCompatActivity;
+import android.view.View;
+
+import com.common.library.view.swipeback.SwipeBackLayout;
+import com.common.library.view.swipeback.Utils;
+import com.common.library.view.swipeback.app.SwipeBackActivityBase;
+import com.common.library.view.swipeback.app.SwipeBackActivityHelper;
 
 /**
  * 作者:fuchangle on 2018/1/29 10:30
  */
 
-public class LibBaseActivity extends AppCompatActivity{
+public class LibBaseActivity extends AppCompatActivity implements SwipeBackActivityBase{
 
     public static String CACHEPATH;
+    private SwipeBackActivityHelper mHelper;
 
     @Override
-    public void onCreate( Bundle savedInstanceState, PersistableBundle persistentState) {
-        super.onCreate(savedInstanceState, persistentState);
+    protected void onCreate( Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mHelper = new SwipeBackActivityHelper(this);
+        mHelper.onActivityCreate();
         CACHEPATH = getApplication().getExternalFilesDir(null) + "/fileCache";
     }
+
+    @Override
+    protected void onPostCreate(Bundle savedInstanceState) {
+        super.onPostCreate(savedInstanceState);
+        mHelper.onPostCreate();
+    }
+
+    @Override
+    public View findViewById(int id) {
+        View v = super.findViewById(id);
+        if (v == null && mHelper != null)
+            return mHelper.findViewById(id);
+        return v;
+    }
+
+    @Override
+    public SwipeBackLayout getSwipeBackLayout() {
+        return mHelper.getSwipeBackLayout();
+    }
+
+    @Override
+    public void setSwipeBackEnable(boolean enable) {
+        getSwipeBackLayout().setEnableGesture(enable);
+    }
+
+    @Override
+    public void scrollToFinishActivity() {
+        Utils.convertActivityToTranslucent(this);
+        getSwipeBackLayout().scrollToFinishActivity();
+    }
 }

+ 1 - 1
library/src/main/java/com/common/library/view/MaterialDialog.java

@@ -1,4 +1,4 @@
-package com.common.library.view;
+package com.common.library.view.materialdialog;
 
 import android.app.AlertDialog;
 import android.content.Context;

+ 605 - 0
library/src/main/java/com/common/library/view/swipeback/SwipeBackLayout.java

@@ -0,0 +1,605 @@
+package com.common.library.view.swipeback;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.support.v4.view.ViewCompat;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+import com.common.library.R;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SwipeBackLayout extends FrameLayout {
+    /**
+     * Minimum velocity that will be detected as a fling
+     */
+    private static final int MIN_FLING_VELOCITY = 400; // dips per second
+
+    private static final int DEFAULT_SCRIM_COLOR = 0x99000000;
+
+    private static final int FULL_ALPHA = 255;
+
+    /**
+     * Edge flag indicating that the left edge should be affected.
+     */
+    public static final int EDGE_LEFT = ViewDragHelper.EDGE_LEFT;
+
+    /**
+     * Edge flag indicating that the right edge should be affected.
+     */
+    public static final int EDGE_RIGHT = ViewDragHelper.EDGE_RIGHT;
+
+    /**
+     * Edge flag indicating that the bottom edge should be affected.
+     */
+    public static final int EDGE_BOTTOM = ViewDragHelper.EDGE_BOTTOM;
+
+    /**
+     * Edge flag set indicating all edges should be affected.
+     */
+    public static final int EDGE_ALL = EDGE_LEFT | EDGE_RIGHT | EDGE_BOTTOM;
+
+    /**
+     * A view is not currently being dragged or animating as a result of a
+     * fling/snap.
+     */
+    public static final int STATE_IDLE = ViewDragHelper.STATE_IDLE;
+
+    /**
+     * A view is currently being dragged. The position is currently changing as
+     * a result of user input or simulated user input.
+     */
+    public static final int STATE_DRAGGING = ViewDragHelper.STATE_DRAGGING;
+
+    /**
+     * A view is currently settling into place as a result of a fling or
+     * predefined non-interactive motion.
+     */
+    public static final int STATE_SETTLING = ViewDragHelper.STATE_SETTLING;
+
+    /**
+     * Default threshold of scroll
+     */
+    private static final float DEFAULT_SCROLL_THRESHOLD = 0.3f;
+
+    private static final int OVERSCROLL_DISTANCE = 10;
+
+    private static final int[] EDGE_FLAGS = {
+            EDGE_LEFT, EDGE_RIGHT, EDGE_BOTTOM, EDGE_ALL
+    };
+
+    private int mEdgeFlag;
+
+    /**
+     * Threshold of scroll, we will close the activity, when scrollPercent over
+     * this value;
+     */
+    private float mScrollThreshold = DEFAULT_SCROLL_THRESHOLD;
+
+    private Activity mActivity;
+
+    private boolean mEnable = true;
+
+    private View mContentView;
+
+    private ViewDragHelper mDragHelper;
+
+    private float mScrollPercent;
+
+    private int mContentLeft;
+
+    private int mContentTop;
+
+    /**
+     * The set of listeners to be sent events through.
+     */
+    private List<SwipeListener> mListeners;
+
+    private Drawable mShadowLeft;
+
+    private Drawable mShadowRight;
+
+    private Drawable mShadowBottom;
+
+    private float mScrimOpacity;
+
+    private int mScrimColor = DEFAULT_SCRIM_COLOR;
+
+    private boolean mInLayout;
+
+    private Rect mTmpRect = new Rect();
+
+    /**
+     * Edge being dragged
+     */
+    private int mTrackingEdge;
+
+    public SwipeBackLayout(Context context) {
+        this(context, null);
+    }
+
+    public SwipeBackLayout(Context context, AttributeSet attrs) {
+        this(context, attrs, R.attr.SwipeBackLayoutStyle);
+    }
+
+    public SwipeBackLayout(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs);
+        mDragHelper = ViewDragHelper.create(this, new ViewDragCallback());
+
+        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SwipeBackLayout, defStyle,
+                R.style.SwipeBackLayout);
+
+        int edgeSize = a.getDimensionPixelSize(R.styleable.SwipeBackLayout_edge_size, -1);
+        if (edgeSize > 0)
+            setEdgeSize(edgeSize);
+        int mode = EDGE_FLAGS[a.getInt(R.styleable.SwipeBackLayout_edge_flag, 0)];
+        setEdgeTrackingEnabled(mode);
+
+        int shadowLeft = a.getResourceId(R.styleable.SwipeBackLayout_shadow_left,
+                R.drawable.shadow_left);
+        int shadowRight = a.getResourceId(R.styleable.SwipeBackLayout_shadow_right,
+                R.drawable.shadow_right);
+        int shadowBottom = a.getResourceId(R.styleable.SwipeBackLayout_shadow_bottom,
+                R.drawable.shadow_bottom);
+        setShadow(shadowLeft, EDGE_LEFT);
+        setShadow(shadowRight, EDGE_RIGHT);
+        setShadow(shadowBottom, EDGE_BOTTOM);
+        a.recycle();
+        final float density = getResources().getDisplayMetrics().density;
+        final float minVel = MIN_FLING_VELOCITY * density;
+        mDragHelper.setMinVelocity(minVel);
+        mDragHelper.setMaxVelocity(minVel * 2f);
+    }
+
+    /**
+     * Sets the sensitivity of the NavigationLayout.
+     *
+     * @param context     The application context.
+     * @param sensitivity value between 0 and 1, the final value for touchSlop =
+     *                    ViewConfiguration.getScaledTouchSlop * (1 / s);
+     */
+    public void setSensitivity(Context context, float sensitivity) {
+        mDragHelper.setSensitivity(context, sensitivity);
+    }
+
+    /**
+     * Set up contentView which will be moved by user gesture
+     *
+     * @param view
+     */
+    private void setContentView(View view) {
+        mContentView = view;
+    }
+
+    public void setEnableGesture(boolean enable) {
+        mEnable = enable;
+    }
+
+    /**
+     * Enable edge tracking for the selected edges of the parent view. The
+     * callback's
+     * methods will only be invoked for edges for which edge tracking has been
+     * enabled.
+     *
+     * @param edgeFlags Combination of edge flags describing the edges to watch
+     * @see #EDGE_LEFT
+     * @see #EDGE_RIGHT
+     * @see #EDGE_BOTTOM
+     */
+    public void setEdgeTrackingEnabled(int edgeFlags) {
+        mEdgeFlag = edgeFlags;
+        mDragHelper.setEdgeTrackingEnabled(mEdgeFlag);
+    }
+
+    /**
+     * Set a color to use for the scrim that obscures primary content while a
+     * drawer is open.
+     *
+     * @param color Color to use in 0xAARRGGBB format.
+     */
+    public void setScrimColor(int color) {
+        mScrimColor = color;
+        invalidate();
+    }
+
+    /**
+     * Set the size of an edge. This is the range in pixels along the edges of
+     * this view that will actively detect edge touches or drags if edge
+     * tracking is enabled.
+     *
+     * @param size The size of an edge in pixels
+     */
+    public void setEdgeSize(int size) {
+        mDragHelper.setEdgeSize(size);
+    }
+
+    /**
+     * Register a callback to be invoked when a swipe event is sent to this
+     * view.
+     *
+     * @param listener the swipe listener to attach to this view
+     * @deprecated use {@link #addSwipeListener} instead
+     */
+    @Deprecated
+    public void setSwipeListener(SwipeListener listener) {
+        addSwipeListener(listener);
+    }
+
+    /**
+     * Add a callback to be invoked when a swipe event is sent to this view.
+     *
+     * @param listener the swipe listener to attach to this view
+     */
+    public void addSwipeListener(SwipeListener listener) {
+        if (mListeners == null) {
+            mListeners = new ArrayList<SwipeListener>();
+        }
+        mListeners.add(listener);
+    }
+
+    /**
+     * Removes a listener from the set of listeners
+     *
+     * @param listener
+     */
+    public void removeSwipeListener(SwipeListener listener) {
+        if (mListeners == null) {
+            return;
+        }
+        mListeners.remove(listener);
+    }
+
+    public static interface SwipeListener {
+        /**
+         * Invoke when state change
+         *
+         * @param state         flag to describe scroll state
+         * @param scrollPercent scroll percent of this view
+         * @see #STATE_IDLE
+         * @see #STATE_DRAGGING
+         * @see #STATE_SETTLING
+         */
+        public void onScrollStateChange(int state, float scrollPercent);
+
+        /**
+         * Invoke when edge touched
+         *
+         * @param edgeFlag edge flag describing the edge being touched
+         * @see #EDGE_LEFT
+         * @see #EDGE_RIGHT
+         * @see #EDGE_BOTTOM
+         */
+        public void onEdgeTouch(int edgeFlag);
+
+        /**
+         * Invoke when scroll percent over the threshold for the first time
+         */
+        public void onScrollOverThreshold();
+    }
+
+    /**
+     * Set scroll threshold, we will close the activity, when scrollPercent over
+     * this value
+     *
+     * @param threshold
+     */
+    public void setScrollThresHold(float threshold) {
+        if (threshold >= 1.0f || threshold <= 0) {
+            throw new IllegalArgumentException("Threshold value should be between 0 and 1.0");
+        }
+        mScrollThreshold = threshold;
+    }
+
+    /**
+     * Set a drawable used for edge shadow.
+     *
+     * @param shadow    Drawable to use
+     * @see #EDGE_LEFT
+     * @see #EDGE_RIGHT
+     * @see #EDGE_BOTTOM
+     */
+    public void setShadow(Drawable shadow, int edgeFlag) {
+        if ((edgeFlag & EDGE_LEFT) != 0) {
+            mShadowLeft = shadow;
+        } else if ((edgeFlag & EDGE_RIGHT) != 0) {
+            mShadowRight = shadow;
+        } else if ((edgeFlag & EDGE_BOTTOM) != 0) {
+            mShadowBottom = shadow;
+        }
+        invalidate();
+    }
+
+    /**
+     * Set a drawable used for edge shadow.
+     *
+     * @param resId     Resource of drawable to use
+     * @see #EDGE_LEFT
+     * @see #EDGE_RIGHT
+     * @see #EDGE_BOTTOM
+     */
+    public void setShadow(int resId, int edgeFlag) {
+        setShadow(getResources().getDrawable(resId), edgeFlag);
+    }
+
+    /**
+     * Scroll out contentView and finish the activity
+     */
+    public void scrollToFinishActivity() {
+        final int childWidth = mContentView.getWidth();
+        final int childHeight = mContentView.getHeight();
+
+        int left = 0, top = 0;
+        if ((mEdgeFlag & EDGE_LEFT) != 0) {
+            left = childWidth + mShadowLeft.getIntrinsicWidth() + OVERSCROLL_DISTANCE;
+            mTrackingEdge = EDGE_LEFT;
+        } else if ((mEdgeFlag & EDGE_RIGHT) != 0) {
+            left = -childWidth - mShadowRight.getIntrinsicWidth() - OVERSCROLL_DISTANCE;
+            mTrackingEdge = EDGE_RIGHT;
+        } else if ((mEdgeFlag & EDGE_BOTTOM) != 0) {
+            top = -childHeight - mShadowBottom.getIntrinsicHeight() - OVERSCROLL_DISTANCE;
+            mTrackingEdge = EDGE_BOTTOM;
+        }
+
+        mDragHelper.smoothSlideViewTo(mContentView, left, top);
+        invalidate();
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent event) {
+        if (!mEnable) {
+            return false;
+        }
+        try {
+            return mDragHelper.shouldInterceptTouchEvent(event);
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // FIXME: handle exception
+            // issues #9
+            return false;
+        }
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        if (!mEnable) {
+            return false;
+        }
+        mDragHelper.processTouchEvent(event);
+        return true;
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        mInLayout = true;
+        if (mContentView != null)
+            mContentView.layout(mContentLeft, mContentTop,
+                    mContentLeft + mContentView.getMeasuredWidth(),
+                    mContentTop + mContentView.getMeasuredHeight());
+        mInLayout = false;
+    }
+
+    @Override
+    public void requestLayout() {
+        if (!mInLayout) {
+            super.requestLayout();
+        }
+    }
+
+    @Override
+    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
+        final boolean drawContent = child == mContentView;
+
+        boolean ret = super.drawChild(canvas, child, drawingTime);
+        if (mScrimOpacity > 0 && drawContent
+                && mDragHelper.getViewDragState() != ViewDragHelper.STATE_IDLE) {
+            drawShadow(canvas, child);
+            drawScrim(canvas, child);
+        }
+        return ret;
+    }
+
+    private void drawScrim(Canvas canvas, View child) {
+        final int baseAlpha = (mScrimColor & 0xff000000) >>> 24;
+        final int alpha = (int) (baseAlpha * mScrimOpacity);
+        final int color = alpha << 24 | (mScrimColor & 0xffffff);
+
+        if ((mTrackingEdge & EDGE_LEFT) != 0) {
+            canvas.clipRect(0, 0, child.getLeft(), getHeight());
+        } else if ((mTrackingEdge & EDGE_RIGHT) != 0) {
+            canvas.clipRect(child.getRight(), 0, getRight(), getHeight());
+        } else if ((mTrackingEdge & EDGE_BOTTOM) != 0) {
+            canvas.clipRect(child.getLeft(), child.getBottom(), getRight(), getHeight());
+        }
+        canvas.drawColor(color);
+    }
+
+    private void drawShadow(Canvas canvas, View child) {
+        final Rect childRect = mTmpRect;
+        child.getHitRect(childRect);
+
+        if ((mEdgeFlag & EDGE_LEFT) != 0) {
+            mShadowLeft.setBounds(childRect.left - mShadowLeft.getIntrinsicWidth(), childRect.top,
+                    childRect.left, childRect.bottom);
+            mShadowLeft.setAlpha((int) (mScrimOpacity * FULL_ALPHA));
+            mShadowLeft.draw(canvas);
+        }
+
+        if ((mEdgeFlag & EDGE_RIGHT) != 0) {
+            mShadowRight.setBounds(childRect.right, childRect.top,
+                    childRect.right + mShadowRight.getIntrinsicWidth(), childRect.bottom);
+            mShadowRight.setAlpha((int) (mScrimOpacity * FULL_ALPHA));
+            mShadowRight.draw(canvas);
+        }
+
+        if ((mEdgeFlag & EDGE_BOTTOM) != 0) {
+            mShadowBottom.setBounds(childRect.left, childRect.bottom, childRect.right,
+                    childRect.bottom + mShadowBottom.getIntrinsicHeight());
+            mShadowBottom.setAlpha((int) (mScrimOpacity * FULL_ALPHA));
+            mShadowBottom.draw(canvas);
+        }
+    }
+
+    public void attachToActivity(Activity activity) {
+        mActivity = activity;
+        TypedArray a = activity.getTheme().obtainStyledAttributes(new int[]{
+                android.R.attr.windowBackground
+        });
+        int background = a.getResourceId(0, 0);
+        a.recycle();
+
+        ViewGroup decor = (ViewGroup) activity.getWindow().getDecorView();
+        ViewGroup decorChild = (ViewGroup) decor.getChildAt(0);
+        decorChild.setBackgroundResource(background);
+        decor.removeView(decorChild);
+        addView(decorChild);
+        setContentView(decorChild);
+        decor.addView(this);
+    }
+
+    @Override
+    public void computeScroll() {
+        mScrimOpacity = 1 - mScrollPercent;
+        if (mDragHelper.continueSettling(true)) {
+            ViewCompat.postInvalidateOnAnimation(this);
+        }
+    }
+
+    private class ViewDragCallback extends ViewDragHelper.Callback {
+        private boolean mIsScrollOverValid;
+
+        @Override
+        public boolean tryCaptureView(View view, int i) {
+            boolean ret = mDragHelper.isEdgeTouched(mEdgeFlag, i);
+            if (ret) {
+                if (mDragHelper.isEdgeTouched(EDGE_LEFT, i)) {
+                    mTrackingEdge = EDGE_LEFT;
+                } else if (mDragHelper.isEdgeTouched(EDGE_RIGHT, i)) {
+                    mTrackingEdge = EDGE_RIGHT;
+                } else if (mDragHelper.isEdgeTouched(EDGE_BOTTOM, i)) {
+                    mTrackingEdge = EDGE_BOTTOM;
+                }
+                if (mListeners != null && !mListeners.isEmpty()) {
+                    for (SwipeListener listener : mListeners) {
+                        listener.onEdgeTouch(mTrackingEdge);
+                    }
+                }
+                mIsScrollOverValid = true;
+            }
+            boolean directionCheck = false;
+            if (mEdgeFlag == EDGE_LEFT || mEdgeFlag == EDGE_RIGHT) {
+                directionCheck = !mDragHelper.checkTouchSlop(ViewDragHelper.DIRECTION_VERTICAL, i);
+            } else if (mEdgeFlag == EDGE_BOTTOM) {
+                directionCheck = !mDragHelper
+                        .checkTouchSlop(ViewDragHelper.DIRECTION_HORIZONTAL, i);
+            } else if (mEdgeFlag == EDGE_ALL) {
+                directionCheck = true;
+            }
+            return ret & directionCheck;
+        }
+
+        @Override
+        public int getViewHorizontalDragRange(View child) {
+            return mEdgeFlag & (EDGE_LEFT | EDGE_RIGHT);
+        }
+
+        @Override
+        public int getViewVerticalDragRange(View child) {
+            return mEdgeFlag & EDGE_BOTTOM;
+        }
+
+        @Override
+        public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
+            super.onViewPositionChanged(changedView, left, top, dx, dy);
+            if ((mTrackingEdge & EDGE_LEFT) != 0) {
+                mScrollPercent = Math.abs((float) left
+                        / (mContentView.getWidth() + mShadowLeft.getIntrinsicWidth()));
+            } else if ((mTrackingEdge & EDGE_RIGHT) != 0) {
+                mScrollPercent = Math.abs((float) left
+                        / (mContentView.getWidth() + mShadowRight.getIntrinsicWidth()));
+            } else if ((mTrackingEdge & EDGE_BOTTOM) != 0) {
+                mScrollPercent = Math.abs((float) top
+                        / (mContentView.getHeight() + mShadowBottom.getIntrinsicHeight()));
+            }
+            mContentLeft = left;
+            mContentTop = top;
+            invalidate();
+            if (mScrollPercent < mScrollThreshold && !mIsScrollOverValid) {
+                mIsScrollOverValid = true;
+            }
+            if (mListeners != null && !mListeners.isEmpty()
+                    && mDragHelper.getViewDragState() == STATE_DRAGGING
+                    && mScrollPercent >= mScrollThreshold && mIsScrollOverValid) {
+                mIsScrollOverValid = false;
+                for (SwipeListener listener : mListeners) {
+                    listener.onScrollOverThreshold();
+                }
+            }
+
+            if (mScrollPercent >= 1) {
+                if (!mActivity.isFinishing()) {
+                    mActivity.finish();
+                    mActivity.overridePendingTransition(0, 0);        
+                }
+            }
+        }
+
+        @Override
+        public void onViewReleased(View releasedChild, float xvel, float yvel) {
+            final int childWidth = releasedChild.getWidth();
+            final int childHeight = releasedChild.getHeight();
+
+            int left = 0, top = 0;
+            if ((mTrackingEdge & EDGE_LEFT) != 0) {
+                left = xvel > 0 || xvel == 0 && mScrollPercent > mScrollThreshold ? childWidth
+                        + mShadowLeft.getIntrinsicWidth() + OVERSCROLL_DISTANCE : 0;
+            } else if ((mTrackingEdge & EDGE_RIGHT) != 0) {
+                left = xvel < 0 || xvel == 0 && mScrollPercent > mScrollThreshold ? -(childWidth
+                        + mShadowLeft.getIntrinsicWidth() + OVERSCROLL_DISTANCE) : 0;
+            } else if ((mTrackingEdge & EDGE_BOTTOM) != 0) {
+                top = yvel < 0 || yvel == 0 && mScrollPercent > mScrollThreshold ? -(childHeight
+                        + mShadowBottom.getIntrinsicHeight() + OVERSCROLL_DISTANCE) : 0;
+            }
+
+            mDragHelper.settleCapturedViewAt(left, top);
+            invalidate();
+        }
+
+        @Override
+        public int clampViewPositionHorizontal(View child, int left, int dx) {
+            int ret = 0;
+            if ((mTrackingEdge & EDGE_LEFT) != 0) {
+                ret = Math.min(child.getWidth(), Math.max(left, 0));
+            } else if ((mTrackingEdge & EDGE_RIGHT) != 0) {
+                ret = Math.min(0, Math.max(left, -child.getWidth()));
+            }
+            return ret;
+        }
+
+        @Override
+        public int clampViewPositionVertical(View child, int top, int dy) {
+            int ret = 0;
+            if ((mTrackingEdge & EDGE_BOTTOM) != 0) {
+                ret = Math.min(0, Math.max(top, -child.getHeight()));
+            }
+            return ret;
+        }
+
+        @Override
+        public void onViewDragStateChanged(int state) {
+            super.onViewDragStateChanged(state);
+            if (mListeners != null && !mListeners.isEmpty()) {
+                for (SwipeListener listener : mListeners) {
+                    listener.onScrollStateChange(state, mScrollPercent);
+                }
+            }
+        }
+    }
+}

+ 103 - 0
library/src/main/java/com/common/library/view/swipeback/Utils.java

@@ -0,0 +1,103 @@
+
+package com.common.library.view.swipeback;
+
+import android.app.Activity;
+import android.app.ActivityOptions;
+import android.os.Build;
+
+import java.lang.reflect.Method;
+
+/**
+ * Created by Chaojun Wang on 6/9/14.
+ */
+public class Utils {
+    private Utils() {
+    }
+
+    /**
+     * Convert a translucent themed Activity
+     * {@link android.R.attr#windowIsTranslucent} to a fullscreen opaque
+     * Activity.
+     * <p>
+     * Call this whenever the background of a translucent Activity has changed
+     * to become opaque. Doing so will allow the {@link android.view.Surface} of
+     * the Activity behind to be released.
+     * <p>
+     * This call has no effect on non-translucent activities or on activities
+     * with the {@link android.R.attr#windowIsFloating} attribute.
+     */
+    public static void convertActivityFromTranslucent(Activity activity) {
+        try {
+            Method method = Activity.class.getDeclaredMethod("convertFromTranslucent");
+            method.setAccessible(true);
+            method.invoke(activity);
+        } catch (Throwable t) {
+        }
+    }
+
+    /**
+     * Convert a translucent themed Activity
+     * {@link android.R.attr#windowIsTranslucent} back from opaque to
+     * translucent following a call to
+     * {@link #convertActivityFromTranslucent(android.app.Activity)} .
+     * <p>
+     * Calling this allows the Activity behind this one to be seen again. Once
+     * all such Activities have been redrawn
+     * <p>
+     * This call has no effect on non-translucent activities or on activities
+     * with the {@link android.R.attr#windowIsFloating} attribute.
+     */
+    public static void convertActivityToTranslucent(Activity activity) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+            convertActivityToTranslucentAfterL(activity);
+        } else {
+            convertActivityToTranslucentBeforeL(activity);
+        }
+    }
+
+    /**
+     * Calling the convertToTranslucent method on platforms before Android 5.0
+     */
+    public static void convertActivityToTranslucentBeforeL(Activity activity) {
+        try {
+            Class<?>[] classes = Activity.class.getDeclaredClasses();
+            Class<?> translucentConversionListenerClazz = null;
+            for (Class clazz : classes) {
+                if (clazz.getSimpleName().contains("TranslucentConversionListener")) {
+                    translucentConversionListenerClazz = clazz;
+                }
+            }
+            Method method = Activity.class.getDeclaredMethod("convertToTranslucent",
+                    translucentConversionListenerClazz);
+            method.setAccessible(true);
+            method.invoke(activity, new Object[] {
+                null
+            });
+        } catch (Throwable t) {
+        }
+    }
+
+    /**
+     * Calling the convertToTranslucent method on platforms after Android 5.0
+     */
+    private static void convertActivityToTranslucentAfterL(Activity activity) {
+        try {
+            Method getActivityOptions = Activity.class.getDeclaredMethod("getActivityOptions");
+            getActivityOptions.setAccessible(true);
+            Object options = getActivityOptions.invoke(activity);
+
+            Class<?>[] classes = Activity.class.getDeclaredClasses();
+            Class<?> translucentConversionListenerClazz = null;
+            for (Class clazz : classes) {
+                if (clazz.getSimpleName().contains("TranslucentConversionListener")) {
+                    translucentConversionListenerClazz = clazz;
+                }
+            }
+            Method convertToTranslucent = Activity.class.getDeclaredMethod("convertToTranslucent",
+                    translucentConversionListenerClazz, ActivityOptions.class);
+            convertToTranslucent.setAccessible(true);
+            convertToTranslucent.invoke(activity, null, options);
+        } catch (Throwable t) {
+        }
+    }
+}

Datei-Diff unterdrückt, da er zu groß ist
+ 1580 - 0
library/src/main/java/com/common/library/view/swipeback/ViewDragHelper.java


+ 50 - 0
library/src/main/java/com/common/library/view/swipeback/app/SwipeBackActivity.java

@@ -0,0 +1,50 @@
+
+package com.common.library.view.swipeback.app;
+
+import android.os.Bundle;
+import android.support.v7.app.AppCompatActivity;
+import android.view.View;
+
+import com.common.library.view.swipeback.SwipeBackLayout;
+import com.common.library.view.swipeback.Utils;
+
+public class SwipeBackActivity extends AppCompatActivity implements SwipeBackActivityBase {
+    private SwipeBackActivityHelper mHelper;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mHelper = new SwipeBackActivityHelper(this);
+        mHelper.onActivityCreate();
+    }
+
+    @Override
+    protected void onPostCreate(Bundle savedInstanceState) {
+        super.onPostCreate(savedInstanceState);
+        mHelper.onPostCreate();
+    }
+
+    @Override
+    public View findViewById(int id) {
+        View v = super.findViewById(id);
+        if (v == null && mHelper != null)
+            return mHelper.findViewById(id);
+        return v;
+    }
+
+    @Override
+    public SwipeBackLayout getSwipeBackLayout() {
+        return mHelper.getSwipeBackLayout();
+    }
+
+    @Override
+    public void setSwipeBackEnable(boolean enable) {
+        getSwipeBackLayout().setEnableGesture(enable);
+    }
+
+    @Override
+    public void scrollToFinishActivity() {
+        Utils.convertActivityToTranslucent(this);
+        getSwipeBackLayout().scrollToFinishActivity();
+    }
+}

+ 21 - 0
library/src/main/java/com/common/library/view/swipeback/app/SwipeBackActivityBase.java

@@ -0,0 +1,21 @@
+package com.common.library.view.swipeback.app;
+
+import com.common.library.view.swipeback.SwipeBackLayout;
+
+/**
+ * @author Yrom
+ */
+public interface SwipeBackActivityBase {
+    /**
+     * @return the SwipeBackLayout associated with this activity.
+     */
+    public abstract SwipeBackLayout getSwipeBackLayout();
+
+    public abstract void setSwipeBackEnable(boolean enable);
+
+    /**
+     * Scroll out contentView and finish the activity
+     */
+    public abstract void scrollToFinishActivity();
+
+}

+ 62 - 0
library/src/main/java/com/common/library/view/swipeback/app/SwipeBackActivityHelper.java

@@ -0,0 +1,62 @@
+package com.common.library.view.swipeback.app;
+
+import android.app.Activity;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
+import android.view.LayoutInflater;
+import android.view.View;
+
+import com.common.library.R;
+import com.common.library.view.swipeback.SwipeBackLayout;
+import com.common.library.view.swipeback.Utils;
+
+/**
+ * @author Yrom
+ */
+public class SwipeBackActivityHelper {
+    private Activity mActivity;
+
+    private SwipeBackLayout mSwipeBackLayout;
+
+    public SwipeBackActivityHelper(Activity activity) {
+        mActivity = activity;
+    }
+
+    @SuppressWarnings("deprecation")
+    public void onActivityCreate() {
+        mActivity.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
+        mActivity.getWindow().getDecorView().setBackgroundDrawable(null);
+        mSwipeBackLayout = (SwipeBackLayout) LayoutInflater.from(mActivity).inflate(
+                R.layout.swipeback_layout, null);
+        mSwipeBackLayout.addSwipeListener(new SwipeBackLayout.SwipeListener() {
+            @Override
+            public void onScrollStateChange(int state, float scrollPercent) {
+            }
+
+            @Override
+            public void onEdgeTouch(int edgeFlag) {
+                Utils.convertActivityToTranslucent(mActivity);
+            }
+
+            @Override
+            public void onScrollOverThreshold() {
+
+            }
+        });
+    }
+
+    public void onPostCreate() {
+        mSwipeBackLayout.attachToActivity(mActivity);
+    }
+
+    public View findViewById(int id) {
+        if (mSwipeBackLayout != null) {
+            return mSwipeBackLayout.findViewById(id);
+        }
+        return null;
+    }
+
+    public SwipeBackLayout getSwipeBackLayout() {
+        return mSwipeBackLayout;
+    }
+}

+ 48 - 0
library/src/main/java/com/common/library/view/swipeback/app/SwipeBackPreferenceActivity.java

@@ -0,0 +1,48 @@
+
+package com.common.library.view.swipeback.app;
+
+import android.os.Bundle;
+import android.preference.PreferenceActivity;
+import android.view.View;
+
+import com.common.library.view.swipeback.SwipeBackLayout;
+
+
+public class SwipeBackPreferenceActivity extends PreferenceActivity implements SwipeBackActivityBase {
+    private SwipeBackActivityHelper mHelper;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mHelper = new SwipeBackActivityHelper(this);
+        mHelper.onActivityCreate();
+    }
+
+    @Override
+    protected void onPostCreate(Bundle savedInstanceState) {
+        super.onPostCreate(savedInstanceState);
+        mHelper.onPostCreate();
+    }
+
+    @Override
+    public View findViewById(int id) {
+        View v = super.findViewById(id);
+        if (v == null && mHelper != null)
+            return mHelper.findViewById(id);
+        return v;
+    }
+    
+    @Override
+    public SwipeBackLayout getSwipeBackLayout() {
+        return mHelper.getSwipeBackLayout();
+    }
+    @Override
+    public void setSwipeBackEnable(boolean enable) {
+        getSwipeBackLayout().setEnableGesture(enable);
+    }
+
+    @Override
+    public void scrollToFinishActivity() {
+        getSwipeBackLayout().scrollToFinishActivity();
+    }
+}

+ 6 - 0
library/src/main/res/layout/swipeback_layout.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<com.common.library.view.swipeback.SwipeBackLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/swipe"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" />
+