diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 00000000..797c2f4b
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,12 @@
+language: android
+android:
+ components:
+ - tools
+ - platform-tools
+ - build-tools-25.0.2
+ - android-25
+ - extra-android-support
+ - extra
+ - extra-android-m2repository
+script:
+ - ./gradlew assembleDebug
\ No newline at end of file
diff --git a/README.md b/README.md
index 6adde701..55c53938 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,8 @@
-# Android Swipe Layout
+# Android Swipe Layout [](https://travis-ci.org/daimajia/AndroidSwipeLayout)
+
+[](https://gitter.im/daimajia/AndroidSwipeLayout?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+
+[](https://insight.io/github.com/daimajia/AndroidSwipeLayout)
This is the brother of [AndroidViewHover](https://github.com/daimajia/AndroidViewHover).
@@ -14,7 +18,7 @@ Time passed, finally...as you see right now.

-[Download Demo](https://github.com/daimajia/AndroidSwipeLayout/releases/download/v1.1.6/AndroidSwipeLayout-v1.1.6.apk)
+[Download Demo](https://github.com/daimajia/AndroidSwipeLayout/releases/download/v1.1.8/AndroidSwipeLayout-v1.1.8.apk)
Before I made this, I actually found some libraries (eg.[SwipeListView](https://github.com/47deg/android-swipelistview)) that helps developers to integrate swiping with your UI component.
@@ -36,8 +40,9 @@ When I start to make this library, I set some goals:
```groovy
dependencies {
- compile 'com.android.support:support-v4:20.+'
- compile "com.daimajia.swipelayout:library:1.1.7@aar"
+ compile 'com.android.support:recyclerview-v7:21.0.0'
+ compile 'com.android.support:support-v4:20.+'
+ compile "com.daimajia.swipelayout:library:1.2.0@aar"
}
```
@@ -49,20 +54,27 @@ dependencies {
support-v4
r6
+
+ com.google.android
+ recyclerview-v7
+ 21.0.0
+
com.daimajia.swipelayout
library
- 1.1.7
+ 1.2.0
apklib
```
#### Eclipse
-[AndroidSwipeLayout-v1.1.6.jar](https://github.com/daimajia/AndroidSwipeLayout/releases/download/v1.1.6/AndroidSwipeLayout-v1.1.6.jar)
+[AndroidSwipeLayout-v1.1.8.jar](https://github.com/daimajia/AndroidSwipeLayout/releases/download/v1.1.8/AndroidSwipeLayout-v1.1.8.jar)
### Step 2
+**Make sure to use the internal adapter instead of your own!**
+
[Wiki Usage](https://github.com/daimajia/AndroidSwipeLayout/wiki/usage)
## Wiki
diff --git a/build.gradle b/build.gradle
index a75fc818..82697f55 100644
--- a/build.gradle
+++ b/build.gradle
@@ -3,9 +3,13 @@
buildscript {
repositories {
jcenter()
+ maven {
+ url "https://jitpack.io"
+ }
}
dependencies {
- classpath 'com.android.tools.build:gradle:0.12.+'
+ classpath 'com.android.tools.build:gradle:2.3.0'
+ classpath 'com.github.dcendents:android-maven-plugin:1.2'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
@@ -15,5 +19,8 @@ buildscript {
allprojects {
repositories {
jcenter()
+ maven {
+ url "https://jitpack.io"
+ }
}
}
diff --git a/demo/build.gradle b/demo/build.gradle
index ae2fca12..09dca2ba 100644
--- a/demo/build.gradle
+++ b/demo/build.gradle
@@ -1,11 +1,13 @@
apply plugin: 'com.android.application'
+repositories {
+ jcenter()
+}
+
android {
compileSdkVersion Integer.parseInt(project.ANDROID_BUILD_SDK_VERSION)
buildToolsVersion project.ANDROID_BUILD_TOOLS_VERSION
-
defaultConfig {
- applicationId "com.daimajia.swipedemo"
minSdkVersion Integer.parseInt(project.ANDROID_BUILD_MIN_SDK_VERSION)
targetSdkVersion Integer.parseInt(project.ANDROID_BUILD_TARGET_SDK_VERSION)
versionName project.VERSION_NAME
@@ -13,16 +15,21 @@ android {
}
buildTypes {
release {
- runProguard false
+ minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
+ lintOptions {
+ abortOnError false
+ }
}
dependencies {
compile project(":library")
- compile 'com.nineoldandroids:library:2.4.0'
+ compile 'com.android.support:recyclerview-v7:25.1.1'
compile 'com.daimajia.easing:library:1.0.0@aar'
compile 'com.daimajia.androidanimations:library:1.1.2@aar'
compile 'com.nineoldandroids:library:2.4.0'
+ // This dude gave a shoutout to you (daimajia) on his github page:
+ compile 'jp.wasabeef:recyclerview-animators:1.0.3@aar'
}
diff --git a/demo/src/main/AndroidManifest.xml b/demo/src/main/AndroidManifest.xml
index 34156678..0f57bf1a 100644
--- a/demo/src/main/AndroidManifest.xml
+++ b/demo/src/main/AndroidManifest.xml
@@ -1,24 +1,28 @@
+ xmlns:tools="http://schemas.android.com/tools"
+ package="com.daimajia.swipedemo">
+
+
+ android:theme="@style/AppTheme">
+ android:label="@string/app_name">
-
-
-
+
+
+
+
diff --git a/demo/src/main/java/com/daimajia/swipedemo/GridViewExample.java b/demo/src/main/java/com/daimajia/swipedemo/GridViewExample.java
index 8e79c45b..42fae4da 100644
--- a/demo/src/main/java/com/daimajia/swipedemo/GridViewExample.java
+++ b/demo/src/main/java/com/daimajia/swipedemo/GridViewExample.java
@@ -7,7 +7,7 @@
import android.widget.AdapterView;
import android.widget.GridView;
-import com.daimajia.swipe.implments.SwipeItemMangerImpl;
+import com.daimajia.swipe.util.Attributes;
import com.daimajia.swipedemo.adapter.GridViewAdapter;
public class GridViewExample extends Activity{
@@ -18,7 +18,7 @@ protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.gridview);
final GridView gridView = (GridView)findViewById(R.id.gridview);
final GridViewAdapter adapter = new GridViewAdapter(this);
- adapter.setMode(SwipeItemMangerImpl.Mode.Multiple);
+ adapter.setMode(Attributes.Mode.Multiple);
gridView.setAdapter(adapter);
gridView.setSelected(false);
gridView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
diff --git a/demo/src/main/java/com/daimajia/swipedemo/ListViewExample.java b/demo/src/main/java/com/daimajia/swipedemo/ListViewExample.java
index 3079cf4a..f957fc8d 100644
--- a/demo/src/main/java/com/daimajia/swipedemo/ListViewExample.java
+++ b/demo/src/main/java/com/daimajia/swipedemo/ListViewExample.java
@@ -1,8 +1,10 @@
package com.daimajia.swipedemo;
+import android.app.ActionBar;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
+import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
@@ -14,7 +16,8 @@
import android.widget.ListView;
import android.widget.Toast;
-import com.daimajia.swipe.implments.SwipeItemMangerImpl;
+import com.daimajia.swipe.SwipeLayout;
+import com.daimajia.swipe.util.Attributes;
import com.daimajia.swipedemo.adapter.ListViewAdapter;
public class ListViewExample extends Activity {
@@ -22,11 +25,18 @@ public class ListViewExample extends Activity {
private ListView mListView;
private ListViewAdapter mAdapter;
private Context mContext = this;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.listview);
- mListView = (ListView)findViewById(R.id.listview);
+ mListView = (ListView) findViewById(R.id.listview);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
+ ActionBar actionBar = getActionBar();
+ if (actionBar != null) {
+ actionBar.setTitle("ListView");
+ }
+ }
/**
* The following comment is the sample usage of ArraySwipeAdapter.
@@ -39,17 +49,17 @@ protected void onCreate(Bundle savedInstanceState) {
mAdapter = new ListViewAdapter(this);
mListView.setAdapter(mAdapter);
- mAdapter.setMode(SwipeItemMangerImpl.Mode.Single);
+ mAdapter.setMode(Attributes.Mode.Single);
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView> parent, View view, int position, long id) {
- Toast.makeText(mContext, "Click", Toast.LENGTH_SHORT).show();
+ ((SwipeLayout)(mListView.getChildAt(position - mListView.getFirstVisiblePosition()))).open(true);
}
});
mListView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
- Log.e("ListView","OnTouch");
+ Log.e("ListView", "OnTouch");
return false;
}
});
@@ -57,13 +67,13 @@ public boolean onTouch(View v, MotionEvent event) {
@Override
public boolean onItemLongClick(AdapterView> parent, View view, int position, long id) {
Toast.makeText(mContext, "OnItemLongClickListener", Toast.LENGTH_SHORT).show();
- return false;
+ return true;
}
});
mListView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
- Log.e("ListView","onScrollStateChanged");
+ Log.e("ListView", "onScrollStateChanged");
}
@Override
@@ -104,10 +114,14 @@ public boolean onOptionsItemSelected(MenuItem item) {
startActivity(new Intent(this, ListViewExample.class));
finish();
return true;
- }else if(id == R.id.action_gridview){
+ } else if (id == R.id.action_gridview) {
startActivity(new Intent(this, GridViewExample.class));
finish();
return true;
+ } else if (id == R.id.action_recycler) {
+ startActivity(new Intent(this, RecyclerViewExample.class));
+ finish();
+ return true;
}
return super.onOptionsItemSelected(item);
}
diff --git a/demo/src/main/java/com/daimajia/swipedemo/MyActivity.java b/demo/src/main/java/com/daimajia/swipedemo/MyActivity.java
index 18fb36f7..8a476218 100644
--- a/demo/src/main/java/com/daimajia/swipedemo/MyActivity.java
+++ b/demo/src/main/java/com/daimajia/swipedemo/MyActivity.java
@@ -4,6 +4,7 @@
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
+import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
@@ -27,8 +28,12 @@ protected void onCreate(Bundle savedInstanceState) {
//sample1
sample1 = (SwipeLayout) findViewById(R.id.sample1);
- sample1.setShowMode(SwipeLayout.ShowMode.LayDown);
- sample1.setDragEdge(SwipeLayout.DragEdge.Left);
+ sample1.setShowMode(SwipeLayout.ShowMode.PullOut);
+ View starBottView = sample1.findViewById(R.id.starbott);
+ sample1.addDrag(SwipeLayout.DragEdge.Left, sample1.findViewById(R.id.bottom_wrapper));
+ sample1.addDrag(SwipeLayout.DragEdge.Right, sample1.findViewById(R.id.bottom_wrapper_2));
+ sample1.addDrag(SwipeLayout.DragEdge.Top, starBottView);
+ sample1.addDrag(SwipeLayout.DragEdge.Bottom, starBottView);
sample1.addRevealListener(R.id.delete, new SwipeLayout.OnRevealListener() {
@Override
public void onReveal(View child, SwipeLayout.DragEdge edge, float fraction, int distance) {
@@ -36,10 +41,58 @@ public void onReveal(View child, SwipeLayout.DragEdge edge, float fraction, int
}
});
+ sample1.getSurfaceView().setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Toast.makeText(MyActivity.this, "Click on surface", Toast.LENGTH_SHORT).show();
+ Log.d(MyActivity.class.getName(), "click on surface");
+ }
+ });
+ sample1.getSurfaceView().setOnLongClickListener(new View.OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View v) {
+ Toast.makeText(MyActivity.this, "longClick on surface", Toast.LENGTH_SHORT).show();
+ Log.d(MyActivity.class.getName(), "longClick on surface");
+ return true;
+ }
+ });
+ sample1.findViewById(R.id.star2).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Toast.makeText(MyActivity.this, "Star", Toast.LENGTH_SHORT).show();
+ }
+ });
+
+ sample1.findViewById(R.id.trash2).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Toast.makeText(MyActivity.this, "Trash Bin", Toast.LENGTH_SHORT).show();
+ }
+ });
+
+ sample1.findViewById(R.id.magnifier2).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Toast.makeText(MyActivity.this, "Magnifier", Toast.LENGTH_SHORT).show();
+ }
+ });
+
+ sample1.addRevealListener(R.id.starbott, new SwipeLayout.OnRevealListener() {
+ @Override
+ public void onReveal(View child, SwipeLayout.DragEdge edge, float fraction, int distance) {
+ View star = child.findViewById(R.id.star);
+ float d = child.getHeight() / 2 - star.getHeight() / 2;
+ ViewHelper.setTranslationY(star, d * fraction);
+ ViewHelper.setScaleX(star, fraction + 0.6f);
+ ViewHelper.setScaleY(star, fraction + 0.6f);
+ }
+ });
+
//sample2
sample2 = (SwipeLayout) findViewById(R.id.sample2);
sample2.setShowMode(SwipeLayout.ShowMode.LayDown);
+ sample2.addDrag(SwipeLayout.DragEdge.Right, sample2.findViewWithTag("Bottom2"));
// sample2.setShowMode(SwipeLayout.ShowMode.PullOut);
sample2.findViewById(R.id.star).setOnClickListener(new View.OnClickListener() {
@Override
@@ -68,11 +121,17 @@ public void onClick(View v) {
Toast.makeText(MyActivity.this, "Yo", Toast.LENGTH_SHORT).show();
}
});
+ sample2.getSurfaceView().setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Toast.makeText(MyActivity.this, "Click on surface", Toast.LENGTH_SHORT).show();
+ }
+ });
//sample3
sample3 = (SwipeLayout) findViewById(R.id.sample3);
- sample3.setDragEdge(SwipeLayout.DragEdge.Top);
+ sample3.addDrag(SwipeLayout.DragEdge.Top, sample3.findViewWithTag("Bottom3"));
sample3.addRevealListener(R.id.bottom_wrapper_child1, new SwipeLayout.OnRevealListener() {
@Override
public void onReveal(View child, SwipeLayout.DragEdge edge, float fraction, int distance) {
@@ -85,12 +144,18 @@ public void onReveal(View child, SwipeLayout.DragEdge edge, float fraction, int
child.setBackgroundColor(c);
}
});
- sample3.findViewById(R.id.star).setOnClickListener(new View.OnClickListener() {
+ sample3.findViewById(R.id.bottom_wrapper_child1).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MyActivity.this, "Yo!", Toast.LENGTH_SHORT).show();
}
});
+ sample3.getSurfaceView().setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Toast.makeText(MyActivity.this, "Click on surface", Toast.LENGTH_SHORT).show();
+ }
+ });
}
@@ -113,9 +178,11 @@ public boolean onOptionsItemSelected(MenuItem item) {
} else if (id == R.id.action_gridview) {
startActivity(new Intent(this, GridViewExample.class));
return true;
- } else if(id == R.id.action_nexted){
+ } else if (id == R.id.action_nested) {
startActivity(new Intent(this, NestedExample.class));
return true;
+ } else if (id == R.id.action_recycler) {
+ startActivity(new Intent(this, RecyclerViewExample.class));
}
return super.onOptionsItemSelected(item);
}
diff --git a/demo/src/main/java/com/daimajia/swipedemo/RecyclerViewExample.java b/demo/src/main/java/com/daimajia/swipedemo/RecyclerViewExample.java
new file mode 100644
index 00000000..fd42733f
--- /dev/null
+++ b/demo/src/main/java/com/daimajia/swipedemo/RecyclerViewExample.java
@@ -0,0 +1,111 @@
+package com.daimajia.swipedemo;
+
+import android.app.ActionBar;
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Build;
+import android.os.Bundle;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+
+import com.daimajia.swipe.util.Attributes;
+import com.daimajia.swipedemo.adapter.RecyclerViewAdapter;
+import com.daimajia.swipedemo.adapter.util.DividerItemDecoration;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import jp.wasabeef.recyclerview.animators.FadeInLeftAnimator;
+
+public class RecyclerViewExample extends Activity {
+
+ /**
+ * RecyclerView: The new recycler view replaces the list view. Its more modular and therefore we
+ * must implement some of the functionality ourselves and attach it to our recyclerview.
+ *
+ * 1) Position items on the screen: This is done with LayoutManagers
+ * 2) Animate & Decorate views: This is done with ItemAnimators & ItemDecorators
+ * 3) Handle any touch events apart from scrolling: This is now done in our adapter's ViewHolder
+ */
+
+ private RecyclerView recyclerView;
+ private RecyclerView.Adapter mAdapter;
+
+ private ArrayList mDataSet;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.recyclerview);
+ recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
+ ActionBar actionBar = getActionBar();
+ if (actionBar != null) {
+ actionBar.setTitle("RecyclerView");
+ }
+ }
+
+ // Layout Managers:
+ recyclerView.setLayoutManager(new LinearLayoutManager(this));
+
+ // Item Decorator:
+ recyclerView.addItemDecoration(new DividerItemDecoration(getResources().getDrawable(R.drawable.divider)));
+ recyclerView.setItemAnimator(new FadeInLeftAnimator());
+
+ // Adapter:
+ String[] adapterData = new String[]{"Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut", "Delaware", "Florida", "Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts", "Michigan", "Minnesota", "Mississippi", "Missouri", "Montana", "Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico", "New York", "North Carolina", "North Dakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Rhode Island", "South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", "Vermont", "Virginia", "Washington", "West Virginia", "Wisconsin", "Wyoming"};
+ mDataSet = new ArrayList(Arrays.asList(adapterData));
+ mAdapter = new RecyclerViewAdapter(this, mDataSet);
+ ((RecyclerViewAdapter) mAdapter).setMode(Attributes.Mode.Single);
+ recyclerView.setAdapter(mAdapter);
+
+ /* Listeners */
+ recyclerView.setOnScrollListener(onScrollListener);
+ }
+
+ /**
+ * Substitute for our onScrollListener for RecyclerView
+ */
+ RecyclerView.OnScrollListener onScrollListener = new RecyclerView.OnScrollListener() {
+ @Override
+ public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
+ super.onScrollStateChanged(recyclerView, newState);
+ Log.e("ListView", "onScrollStateChanged");
+ }
+
+ @Override
+ public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
+ super.onScrolled(recyclerView, dx, dy);
+ // Could hide open views here if you wanted. //
+ }
+ };
+
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ getMenuInflater().inflate(R.menu.my, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ // Handle action bar item clicks here. The action bar will
+ // automatically handle clicks on the Home/Up button, so long
+ // as you specify a parent activity in AndroidManifest.xml.
+ int id = item.getItemId();
+ if (id == R.id.action_listview) {
+ startActivity(new Intent(this, ListViewExample.class));
+ finish();
+ return true;
+ } else if (id == R.id.action_gridview) {
+ startActivity(new Intent(this, GridViewExample.class));
+ finish();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+}
diff --git a/demo/src/main/java/com/daimajia/swipedemo/adapter/ListViewAdapter.java b/demo/src/main/java/com/daimajia/swipedemo/adapter/ListViewAdapter.java
index 074e2de2..e34f31de 100644
--- a/demo/src/main/java/com/daimajia/swipedemo/adapter/ListViewAdapter.java
+++ b/demo/src/main/java/com/daimajia/swipedemo/adapter/ListViewAdapter.java
@@ -43,6 +43,12 @@ public void onDoubleClick(SwipeLayout layout, boolean surface) {
Toast.makeText(mContext, "DoubleClick", Toast.LENGTH_SHORT).show();
}
});
+ v.findViewById(R.id.delete).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Toast.makeText(mContext, "click delete", Toast.LENGTH_SHORT).show();
+ }
+ });
return v;
}
diff --git a/demo/src/main/java/com/daimajia/swipedemo/adapter/RecyclerViewAdapter.java b/demo/src/main/java/com/daimajia/swipedemo/adapter/RecyclerViewAdapter.java
new file mode 100644
index 00000000..3b4c34d4
--- /dev/null
+++ b/demo/src/main/java/com/daimajia/swipedemo/adapter/RecyclerViewAdapter.java
@@ -0,0 +1,104 @@
+package com.daimajia.swipedemo.adapter;
+
+import android.content.Context;
+import android.support.v7.widget.RecyclerView;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.daimajia.androidanimations.library.Techniques;
+import com.daimajia.androidanimations.library.YoYo;
+import com.daimajia.swipe.SimpleSwipeListener;
+import com.daimajia.swipe.SwipeLayout;
+import com.daimajia.swipe.adapters.RecyclerSwipeAdapter;
+import com.daimajia.swipedemo.R;
+
+import java.util.ArrayList;
+
+public class RecyclerViewAdapter extends RecyclerSwipeAdapter {
+
+ public static class SimpleViewHolder extends RecyclerView.ViewHolder {
+ SwipeLayout swipeLayout;
+ TextView textViewPos;
+ TextView textViewData;
+ Button buttonDelete;
+
+ public SimpleViewHolder(View itemView) {
+ super(itemView);
+ swipeLayout = (SwipeLayout) itemView.findViewById(R.id.swipe);
+ textViewPos = (TextView) itemView.findViewById(R.id.position);
+ textViewData = (TextView) itemView.findViewById(R.id.text_data);
+ buttonDelete = (Button) itemView.findViewById(R.id.delete);
+
+ itemView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Log.d(getClass().getSimpleName(), "onItemSelected: " + textViewData.getText().toString());
+ Toast.makeText(view.getContext(), "onItemSelected: " + textViewData.getText().toString(), Toast.LENGTH_SHORT).show();
+ }
+ });
+ }
+ }
+
+ private Context mContext;
+ private ArrayList mDataset;
+
+ //protected SwipeItemRecyclerMangerImpl mItemManger = new SwipeItemRecyclerMangerImpl(this);
+
+ public RecyclerViewAdapter(Context context, ArrayList objects) {
+ this.mContext = context;
+ this.mDataset = objects;
+ }
+
+ @Override
+ public SimpleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_item, parent, false);
+ return new SimpleViewHolder(view);
+ }
+
+ @Override
+ public void onBindViewHolder(final SimpleViewHolder viewHolder, final int position) {
+ String item = mDataset.get(position);
+ viewHolder.swipeLayout.setShowMode(SwipeLayout.ShowMode.LayDown);
+ viewHolder.swipeLayout.addSwipeListener(new SimpleSwipeListener() {
+ @Override
+ public void onOpen(SwipeLayout layout) {
+ YoYo.with(Techniques.Tada).duration(500).delay(100).playOn(layout.findViewById(R.id.trash));
+ }
+ });
+ viewHolder.swipeLayout.setOnDoubleClickListener(new SwipeLayout.DoubleClickListener() {
+ @Override
+ public void onDoubleClick(SwipeLayout layout, boolean surface) {
+ Toast.makeText(mContext, "DoubleClick", Toast.LENGTH_SHORT).show();
+ }
+ });
+ viewHolder.buttonDelete.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ mItemManger.removeShownLayouts(viewHolder.swipeLayout);
+ mDataset.remove(position);
+ notifyItemRemoved(position);
+ notifyItemRangeChanged(position, mDataset.size());
+ mItemManger.closeAllItems();
+ Toast.makeText(view.getContext(), "Deleted " + viewHolder.textViewData.getText().toString() + "!", Toast.LENGTH_SHORT).show();
+ }
+ });
+ viewHolder.textViewPos.setText((position + 1) + ".");
+ viewHolder.textViewData.setText(item);
+ mItemManger.bind(viewHolder.itemView, position);
+ }
+
+ @Override
+ public int getItemCount() {
+ return mDataset.size();
+ }
+
+ @Override
+ public int getSwipeLayoutResourceId(int position) {
+ return R.id.swipe;
+ }
+}
diff --git a/demo/src/main/java/com/daimajia/swipedemo/adapter/util/DividerItemDecoration.java b/demo/src/main/java/com/daimajia/swipedemo/adapter/util/DividerItemDecoration.java
new file mode 100644
index 00000000..85b5b3d2
--- /dev/null
+++ b/demo/src/main/java/com/daimajia/swipedemo/adapter/util/DividerItemDecoration.java
@@ -0,0 +1,125 @@
+package com.daimajia.swipedemo.adapter.util;
+
+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.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.util.AttributeSet;
+import android.view.View;
+
+public class DividerItemDecoration extends RecyclerView.ItemDecoration {
+
+ private Drawable mDivider;
+ private boolean mShowFirstDivider = false;
+ private boolean mShowLastDivider = false;
+
+
+ public DividerItemDecoration(Context context, AttributeSet attrs) {
+ final TypedArray a = context
+ .obtainStyledAttributes(attrs, new int[]{android.R.attr.listDivider});
+ mDivider = a.getDrawable(0);
+ a.recycle();
+ }
+
+ public DividerItemDecoration(Context context, AttributeSet attrs, boolean showFirstDivider,
+ boolean showLastDivider) {
+ this(context, attrs);
+ mShowFirstDivider = showFirstDivider;
+ mShowLastDivider = showLastDivider;
+ }
+
+ public DividerItemDecoration(Drawable divider) {
+ mDivider = divider;
+ }
+
+ public DividerItemDecoration(Drawable divider, boolean showFirstDivider,
+ boolean showLastDivider) {
+ this(divider);
+ mShowFirstDivider = showFirstDivider;
+ mShowLastDivider = showLastDivider;
+ }
+
+ @Override
+ public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
+ RecyclerView.State state) {
+ super.getItemOffsets(outRect, view, parent, state);
+ if (mDivider == null) {
+ return;
+ }
+ if (parent.getChildPosition(view) < 1) {
+ return;
+ }
+
+ if (getOrientation(parent) == LinearLayoutManager.VERTICAL) {
+ outRect.top = mDivider.getIntrinsicHeight();
+ } else {
+ outRect.left = mDivider.getIntrinsicWidth();
+ }
+ }
+
+ @Override
+ public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
+ if (mDivider == null) {
+ super.onDrawOver(c, parent, state);
+ return;
+ }
+
+ // Initialization needed to avoid compiler warning
+ int left = 0, right = 0, top = 0, bottom = 0, size;
+ int orientation = getOrientation(parent);
+ int childCount = parent.getChildCount();
+
+ if (orientation == LinearLayoutManager.VERTICAL) {
+ size = mDivider.getIntrinsicHeight();
+ left = parent.getPaddingLeft();
+ right = parent.getWidth() - parent.getPaddingRight();
+ } else { //horizontal
+ size = mDivider.getIntrinsicWidth();
+ top = parent.getPaddingTop();
+ bottom = parent.getHeight() - parent.getPaddingBottom();
+ }
+
+ for (int i = mShowFirstDivider ? 0 : 1; i < childCount; i++) {
+ View child = parent.getChildAt(i);
+ RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
+
+ if (orientation == LinearLayoutManager.VERTICAL) {
+ top = child.getTop() - params.topMargin;
+ bottom = top + size;
+ } else { //horizontal
+ left = child.getLeft() - params.leftMargin;
+ right = left + size;
+ }
+ mDivider.setBounds(left, top, right, bottom);
+ mDivider.draw(c);
+ }
+
+ // show last divider
+ if (mShowLastDivider && childCount > 0) {
+ View child = parent.getChildAt(childCount - 1);
+ RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
+ if (orientation == LinearLayoutManager.VERTICAL) {
+ top = child.getBottom() + params.bottomMargin;
+ bottom = top + size;
+ } else { // horizontal
+ left = child.getRight() + params.rightMargin;
+ right = left + size;
+ }
+ mDivider.setBounds(left, top, right, bottom);
+ mDivider.draw(c);
+ }
+ }
+
+ private int getOrientation(RecyclerView parent) {
+ if (parent.getLayoutManager() instanceof LinearLayoutManager) {
+ LinearLayoutManager layoutManager = (LinearLayoutManager) parent.getLayoutManager();
+ return layoutManager.getOrientation();
+ } else {
+ throw new IllegalStateException(
+ "DividerItemDecoration can only be used with a LinearLayoutManager.");
+ }
+ }
+}
\ No newline at end of file
diff --git a/demo/src/main/java/com/daimajia/swipedemo/adapter/util/RecyclerItemClickListener.java b/demo/src/main/java/com/daimajia/swipedemo/adapter/util/RecyclerItemClickListener.java
new file mode 100644
index 00000000..613e8e52
--- /dev/null
+++ b/demo/src/main/java/com/daimajia/swipedemo/adapter/util/RecyclerItemClickListener.java
@@ -0,0 +1,45 @@
+package com.daimajia.swipedemo.adapter.util;
+
+import android.content.Context;
+import android.support.v7.widget.RecyclerView;
+import android.view.GestureDetector;
+import android.view.MotionEvent;
+import android.view.View;
+
+public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
+ private OnItemClickListener mListener;
+
+ public interface OnItemClickListener {
+ public void onItemClick(View view, int position);
+ }
+
+ GestureDetector mGestureDetector;
+
+ public RecyclerItemClickListener(Context context, OnItemClickListener listener) {
+ mListener = listener;
+ mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
+ @Override
+ public boolean onSingleTapUp(MotionEvent e) {
+ return true;
+ }
+ });
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) {
+ View childView = view.findChildViewUnder(e.getX(), e.getY());
+ if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
+ mListener.onItemClick(childView, view.getChildPosition(childView));
+ }
+ return false;
+ }
+
+ @Override
+ public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) {
+ }
+
+ @Override
+ public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
+
+ }
+}
diff --git a/demo/src/main/res/drawable/dark_gray.xml b/demo/src/main/res/drawable/dark_gray.xml
new file mode 100644
index 00000000..46878503
--- /dev/null
+++ b/demo/src/main/res/drawable/dark_gray.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/demo/src/main/res/drawable/divider.xml b/demo/src/main/res/drawable/divider.xml
new file mode 100644
index 00000000..111d79d3
--- /dev/null
+++ b/demo/src/main/res/drawable/divider.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/demo/src/main/res/drawable/red.xml b/demo/src/main/res/drawable/red.xml
new file mode 100644
index 00000000..707047e9
--- /dev/null
+++ b/demo/src/main/res/drawable/red.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/demo/src/main/res/drawable/white.xml b/demo/src/main/res/drawable/white.xml
new file mode 100644
index 00000000..8dfff14a
--- /dev/null
+++ b/demo/src/main/res/drawable/white.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/demo/src/main/res/layout/listview_item.xml b/demo/src/main/res/layout/listview_item.xml
index 54cc383a..4b2c5074 100644
--- a/demo/src/main/res/layout/listview_item.xml
+++ b/demo/src/main/res/layout/listview_item.xml
@@ -1,57 +1,62 @@
-
-
+
+
+ android:layout_height="80dp"
+ android:background="#FF5534"
+ android:gravity="center"
+ android:tag="Bottom3"
+ android:weightSum="10">
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+ android:layout_height="match_parent"
+ android:tag="Hover"
+ android:text="Do not, for one repulse, forgo the purpose that you resolved to effort. " />
+
+
\ No newline at end of file
diff --git a/demo/src/main/res/layout/main.xml b/demo/src/main/res/layout/main.xml
index 759c1c98..cf05988e 100644
--- a/demo/src/main/res/layout/main.xml
+++ b/demo/src/main/res/layout/main.xml
@@ -1,12 +1,17 @@
-
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
diff --git a/demo/src/main/res/layout/recyclerview.xml b/demo/src/main/res/layout/recyclerview.xml
new file mode 100644
index 00000000..3f1387f0
--- /dev/null
+++ b/demo/src/main/res/layout/recyclerview.xml
@@ -0,0 +1,7 @@
+
+
+
\ No newline at end of file
diff --git a/demo/src/main/res/layout/recyclerview_item.xml b/demo/src/main/res/layout/recyclerview_item.xml
new file mode 100644
index 00000000..4cb9102e
--- /dev/null
+++ b/demo/src/main/res/layout/recyclerview_item.xml
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demo/src/main/res/layout/sample1.xml b/demo/src/main/res/layout/sample1.xml
index 3d20f8cf..350bdb0f 100644
--- a/demo/src/main/res/layout/sample1.xml
+++ b/demo/src/main/res/layout/sample1.xml
@@ -1,8 +1,12 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ android:layout_height="match_parent">
+
+
+
+
+
diff --git a/demo/src/main/res/layout/sample2.xml b/demo/src/main/res/layout/sample2.xml
index 539e5fa9..08da313e 100644
--- a/demo/src/main/res/layout/sample2.xml
+++ b/demo/src/main/res/layout/sample2.xml
@@ -26,7 +26,7 @@
android:id="@+id/trash"
android:src="@drawable/trash"
android:layout_width="70dp"
- android:background="#FF3B30"
+ android:background="@drawable/red"
android:paddingLeft="25dp"
android:paddingRight="25dp"
android:layout_height="match_parent" />
@@ -35,7 +35,7 @@
-
-
-
+ android:layout_height="match_parent" />
\ No newline at end of file
diff --git a/demo/src/main/res/menu/my.xml b/demo/src/main/res/menu/my.xml
index 087d48c1..df546330 100644
--- a/demo/src/main/res/menu/my.xml
+++ b/demo/src/main/res/menu/my.xml
@@ -1,14 +1,19 @@
diff --git a/demo/src/main/res/values/colors.xml b/demo/src/main/res/values/colors.xml
index 3768db71..35111398 100644
--- a/demo/src/main/res/values/colors.xml
+++ b/demo/src/main/res/values/colors.xml
@@ -2,4 +2,8 @@
#E8E8E0
#DBDBD3
+ #FF3B00
+ #990000
+ #4C535B
+ #ff7e8a97
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
index f6b05d25..beab8970 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -18,11 +18,11 @@
# org.gradle.parallel=true
-VERSION_NAME=1.1.7
-VERSION_CODE=18
+VERSION_NAME=1.2.0
+VERSION_CODE=22
GROUP=com.daimajia.swipelayout
-ANDROID_BUILD_MIN_SDK_VERSION=8
-ANDROID_BUILD_TARGET_SDK_VERSION=20
-ANDROID_BUILD_SDK_VERSION=20
-ANDROID_BUILD_TOOLS_VERSION=20.0.0
+ANDROID_BUILD_MIN_SDK_VERSION=9
+ANDROID_BUILD_TARGET_SDK_VERSION=25
+ANDROID_BUILD_SDK_VERSION=25
+ANDROID_BUILD_TOOLS_VERSION=25.0.2
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 1e61d1fd..776d2a5a 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Wed Apr 10 15:27:10 PDT 2013
+#Thu Mar 09 16:07:03 CST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=http\://services.gradle.org/distributions/gradle-1.12-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
diff --git a/library/build.gradle b/library/build.gradle
index 7a178216..906272e1 100644
--- a/library/build.gradle
+++ b/library/build.gradle
@@ -5,13 +5,22 @@ android {
buildToolsVersion project.ANDROID_BUILD_TOOLS_VERSION
defaultConfig {
- applicationId "com.daimajia.swipe"
- minSdkVersion 8
+ minSdkVersion 9
targetSdkVersion Integer.parseInt(project.ANDROID_BUILD_TARGET_SDK_VERSION)
}
}
dependencies {
- compile 'com.android.support:support-v4:20.+'
+ compile 'com.android.support:recyclerview-v7:25.2.0'
+ compile 'com.android.support:support-v4:25.2.0'
+}
+apply from: './gradle-mvn-push.gradle'
+
+// build a jar with source files
+task sourcesJar(type: Jar) {
+ from android.sourceSets.main.java.srcDirs
+ classifier = 'sources'
+}
+artifacts {
+ archives sourcesJar
}
-apply from: './gradle-mvn-push.gradle'
\ No newline at end of file
diff --git a/library/src/main/AndroidManifest.xml b/library/src/main/AndroidManifest.xml
index d481b7ff..aebf83d9 100644
--- a/library/src/main/AndroidManifest.xml
+++ b/library/src/main/AndroidManifest.xml
@@ -1,2 +1,3 @@
-
-
+
+
+
diff --git a/library/src/main/java/com/daimajia/swipe/SwipeLayout.java b/library/src/main/java/com/daimajia/swipe/SwipeLayout.java
index 0fa4825e..6703123c 100644
--- a/library/src/main/java/com/daimajia/swipe/SwipeLayout.java
+++ b/library/src/main/java/com/daimajia/swipe/SwipeLayout.java
@@ -3,53 +3,75 @@
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Rect;
+import android.support.v4.view.GravityCompat;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.ViewDragHelper;
import android.util.AttributeSet;
import android.view.GestureDetector;
+import android.view.Gravity;
+import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.View;
+import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.ViewParent;
-import android.widget.Adapter;
+import android.widget.AbsListView;
import android.widget.AdapterView;
-import android.widget.BaseAdapter;
import android.widget.FrameLayout;
-import android.widget.ListAdapter;
+import java.lang.reflect.Method;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class SwipeLayout extends FrameLayout {
+ @Deprecated
+ public static final int EMPTY_LAYOUT = -1;
+ private static final int DRAG_LEFT = 1;
+ private static final int DRAG_RIGHT = 2;
+ private static final int DRAG_TOP = 4;
+ private static final int DRAG_BOTTOM = 8;
+ private static final DragEdge DefaultDragEdge = DragEdge.Right;
+ private int mTouchSlop;
+
+ private DragEdge mCurrentDragEdge = DefaultDragEdge;
private ViewDragHelper mDragHelper;
private int mDragDistance = 0;
- private DragEdge mDragEdge;
+ private LinkedHashMap mDragEdges = new LinkedHashMap<>();
private ShowMode mShowMode;
- private List mSwipeListeners = new ArrayList();
- private List mSwipeDeniers = new ArrayList();
- private Map> mRevealListeners = new HashMap>();
- private Map mShowEntirely = new HashMap();
+ private float[] mEdgeSwipesOffset = new float[4];
+
+ private List mSwipeListeners = new ArrayList<>();
+ private List mSwipeDeniers = new ArrayList<>();
+ private Map> mRevealListeners = new HashMap<>();
+ private Map mShowEntirely = new HashMap<>();
+ private Map mViewBoundCache = new HashMap<>();//save all children's bound, restore in onLayout
private DoubleClickListener mDoubleClickListener;
private boolean mSwipeEnabled = true;
+ private boolean[] mSwipesEnabled = new boolean[]{true, true, true, true};
+ private boolean mClickToClose = false;
+ private float mWillOpenPercentAfterOpen = 0.75f;
+ private float mWillOpenPercentAfterClose = 0.25f;
- public static enum DragEdge {
+ public enum DragEdge {
Left,
- Right,
Top,
- Bottom;
- };
-
- public static enum ShowMode {
- LayDown, PullOut
+ Right,
+ Bottom
}
+ public enum ShowMode {
+ LayDown,
+ PullOut
+ }
public SwipeLayout(Context context) {
this(context, null);
@@ -62,43 +84,69 @@ public SwipeLayout(Context context, AttributeSet attrs) {
public SwipeLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mDragHelper = ViewDragHelper.create(this, mDragHelperCallback);
+ mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SwipeLayout);
- int ordinal = a.getInt(R.styleable.SwipeLayout_drag_edge, DragEdge.Right.ordinal());
- mDragEdge = DragEdge.values()[ordinal];
- ordinal = a.getInt(R.styleable.SwipeLayout_show_mode, ShowMode.PullOut.ordinal());
+ int dragEdgeChoices = a.getInt(R.styleable.SwipeLayout_drag_edge, DRAG_RIGHT);
+ mEdgeSwipesOffset[DragEdge.Left.ordinal()] = a.getDimension(R.styleable.SwipeLayout_leftEdgeSwipeOffset, 0);
+ mEdgeSwipesOffset[DragEdge.Right.ordinal()] = a.getDimension(R.styleable.SwipeLayout_rightEdgeSwipeOffset, 0);
+ mEdgeSwipesOffset[DragEdge.Top.ordinal()] = a.getDimension(R.styleable.SwipeLayout_topEdgeSwipeOffset, 0);
+ mEdgeSwipesOffset[DragEdge.Bottom.ordinal()] = a.getDimension(R.styleable.SwipeLayout_bottomEdgeSwipeOffset, 0);
+ setClickToClose(a.getBoolean(R.styleable.SwipeLayout_clickToClose, mClickToClose));
+
+ if ((dragEdgeChoices & DRAG_LEFT) == DRAG_LEFT) {
+ mDragEdges.put(DragEdge.Left, null);
+ }
+ if ((dragEdgeChoices & DRAG_TOP) == DRAG_TOP) {
+ mDragEdges.put(DragEdge.Top, null);
+ }
+ if ((dragEdgeChoices & DRAG_RIGHT) == DRAG_RIGHT) {
+ mDragEdges.put(DragEdge.Right, null);
+ }
+ if ((dragEdgeChoices & DRAG_BOTTOM) == DRAG_BOTTOM) {
+ mDragEdges.put(DragEdge.Bottom, null);
+ }
+ int ordinal = a.getInt(R.styleable.SwipeLayout_show_mode, ShowMode.PullOut.ordinal());
mShowMode = ShowMode.values()[ordinal];
+ a.recycle();
+
}
+ public interface SwipeListener {
+ void onStartOpen(SwipeLayout layout);
- public interface SwipeListener{
- public void onStartOpen(SwipeLayout layout);
- public void onOpen(SwipeLayout layout);
- public void onStartClose(SwipeLayout layout);
- public void onClose(SwipeLayout layout);
- public void onUpdate(SwipeLayout layout, int leftOffset, int topOffset);
- public void onHandRelease(SwipeLayout layout, float xvel, float yvel);
+ void onOpen(SwipeLayout layout);
+
+ void onStartClose(SwipeLayout layout);
+
+ void onClose(SwipeLayout layout);
+
+ void onUpdate(SwipeLayout layout, int leftOffset, int topOffset);
+
+ void onHandRelease(SwipeLayout layout, float xvel, float yvel);
}
- public void addSwipeListener(SwipeListener l){
+ public void addSwipeListener(SwipeListener l) {
mSwipeListeners.add(l);
}
- public void removeSwipeListener(SwipeListener l){
+ public void removeSwipeListener(SwipeListener l) {
mSwipeListeners.remove(l);
}
- public static interface SwipeDenier {
- /*
- * Called in onInterceptTouchEvent
- * Determines if this swipe event should be denied
- * Implement this interface if you are using views with swipe gestures
- * As a child of SwipeLayout
- *
- * @return true deny
- * false allow
- */
- public boolean shouldDenySwipe(MotionEvent ev);
+ public void removeAllSwipeListener() {
+ mSwipeListeners.clear();
+ }
+
+ public interface SwipeDenier {
+ /*
+ * Called in onInterceptTouchEvent Determines if this swipe event should
+ * be denied Implement this interface if you are using views with swipe
+ * gestures As a child of SwipeLayout
+ *
+ * @return true deny false allow
+ */
+ boolean shouldDenySwipe(MotionEvent ev);
}
public void addSwipeDenier(SwipeDenier denier) {
@@ -114,53 +162,56 @@ public void removeAllSwipeDeniers() {
}
public interface OnRevealListener {
- public void onReveal(View child, DragEdge edge, float fraction, int distance);
+ void onReveal(View child, DragEdge edge, float fraction, int distance);
}
/**
- * bind a view with a specific {@link com.daimajia.swipe.SwipeLayout.OnRevealListener}
+ * bind a view with a specific
+ * {@link com.daimajia.swipe.SwipeLayout.OnRevealListener}
+ *
* @param childId the view id.
- * @param l the target {@link com.daimajia.swipe.SwipeLayout.OnRevealListener}
+ * @param l the target
+ * {@link com.daimajia.swipe.SwipeLayout.OnRevealListener}
*/
- public void addRevealListener(int childId, OnRevealListener l){
- View child = findViewById(childId);
- if(child == null){
+ public void addRevealListener(int childId, OnRevealListener l) {
+ View child = findViewById(childId);
+ if (child == null) {
throw new IllegalArgumentException("Child does not belong to SwipeListener.");
}
- if(!mShowEntirely.containsKey(child)){
+ if (!mShowEntirely.containsKey(child)) {
mShowEntirely.put(child, false);
}
- if(mRevealListeners.get(child) == null)
+ if (mRevealListeners.get(child) == null)
mRevealListeners.put(child, new ArrayList());
mRevealListeners.get(child).add(l);
}
/**
- * bind multiple views with an {@link com.daimajia.swipe.SwipeLayout.OnRevealListener}.
+ * bind multiple views with an
+ * {@link com.daimajia.swipe.SwipeLayout.OnRevealListener}.
+ *
* @param childIds the view id.
- * @param l the {@link com.daimajia.swipe.SwipeLayout.OnRevealListener}
+ * @param l the {@link com.daimajia.swipe.SwipeLayout.OnRevealListener}
*/
- public void addRevealListener(int[] childIds, OnRevealListener l){
- for(int i : childIds)
+ public void addRevealListener(int[] childIds, OnRevealListener l) {
+ for (int i : childIds)
addRevealListener(i, l);
}
- public void removeRevealListener(int childId, OnRevealListener l){
+ public void removeRevealListener(int childId, OnRevealListener l) {
View child = findViewById(childId);
- if(child == null)
- return;
+ if (child == null) return;
mShowEntirely.remove(child);
- if(mRevealListeners.containsKey(child))
- mRevealListeners.get(child).remove(l);
+ if (mRevealListeners.containsKey(child)) mRevealListeners.get(child).remove(l);
}
- public void removeAllRevealListeners(int childId){
+ public void removeAllRevealListeners(int childId) {
View child = findViewById(childId);
- if(child != null){
+ if (child != null) {
mRevealListeners.remove(child);
mShowEntirely.remove(child);
}
@@ -170,39 +221,36 @@ public void removeAllRevealListeners(int childId){
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
- if(child == getSurfaceView()){
- switch (mDragEdge){
+ if (child == getSurfaceView()) {
+ switch (mCurrentDragEdge) {
case Top:
case Bottom:
return getPaddingLeft();
case Left:
- if(left < getPaddingLeft())
- return getPaddingLeft();
- if(left > getPaddingLeft() + mDragDistance)
+ if (left < getPaddingLeft()) return getPaddingLeft();
+ if (left > getPaddingLeft() + mDragDistance)
return getPaddingLeft() + mDragDistance;
break;
case Right:
- if(left > getPaddingLeft())
- return getPaddingLeft();
- if(left < getPaddingLeft() - mDragDistance)
+ if (left > getPaddingLeft()) return getPaddingLeft();
+ if (left < getPaddingLeft() - mDragDistance)
return getPaddingLeft() - mDragDistance;
break;
}
- }else if(child == getBottomView()){
+ } else if (getCurrentBottomView() == child) {
- switch (mDragEdge){
+ switch (mCurrentDragEdge) {
case Top:
case Bottom:
return getPaddingLeft();
case Left:
- if(mShowMode == ShowMode.PullOut){
- if(left > getPaddingLeft())
- return getPaddingLeft();
+ if (mShowMode == ShowMode.PullOut) {
+ if (left > getPaddingLeft()) return getPaddingLeft();
}
break;
case Right:
- if(mShowMode == ShowMode.PullOut){
- if(left < getMeasuredWidth() - mDragDistance){
+ if (mShowMode == ShowMode.PullOut) {
+ if (left < getMeasuredWidth() - mDragDistance) {
return getMeasuredWidth() - mDragDistance;
}
}
@@ -214,49 +262,49 @@ public int clampViewPositionHorizontal(View child, int left, int dx) {
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
- if(child == getSurfaceView()){
- switch (mDragEdge){
+ if (child == getSurfaceView()) {
+ switch (mCurrentDragEdge) {
case Left:
case Right:
return getPaddingTop();
case Top:
- if(top < getPaddingTop())
- return getPaddingTop();
- if(top > getPaddingTop() + mDragDistance)
+ if (top < getPaddingTop()) return getPaddingTop();
+ if (top > getPaddingTop() + mDragDistance)
return getPaddingTop() + mDragDistance;
break;
case Bottom:
- if(top < getPaddingTop() - mDragDistance){
+ if (top < getPaddingTop() - mDragDistance) {
return getPaddingTop() - mDragDistance;
}
- if(top > getPaddingTop()){
+ if (top > getPaddingTop()) {
return getPaddingTop();
}
}
- }else{
- switch (mDragEdge){
+ } else {
+ View surfaceView = getSurfaceView();
+ int surfaceViewTop = surfaceView == null ? 0 : surfaceView.getTop();
+ switch (mCurrentDragEdge) {
case Left:
case Right:
return getPaddingTop();
case Top:
- if(mShowMode == ShowMode.PullOut){
- if(top > getPaddingTop())
+ if (mShowMode == ShowMode.PullOut) {
+ if (top > getPaddingTop()) return getPaddingTop();
+ } else {
+ if (surfaceViewTop + dy < getPaddingTop())
return getPaddingTop();
- }else{
- if(getSurfaceView().getTop() + dy < getPaddingTop())
- return getPaddingTop();
- if(getSurfaceView().getTop() + dy > getPaddingTop() + mDragDistance)
+ if (surfaceViewTop + dy > getPaddingTop() + mDragDistance)
return getPaddingTop() + mDragDistance;
}
break;
case Bottom:
- if(mShowMode == ShowMode.PullOut){
- if(top < getMeasuredHeight() - mDragDistance)
+ if (mShowMode == ShowMode.PullOut) {
+ if (top < getMeasuredHeight() - mDragDistance)
return getMeasuredHeight() - mDragDistance;
- }else{
- if(getSurfaceView().getTop() + dy >= getPaddingTop())
+ } else {
+ if (surfaceViewTop + dy >= getPaddingTop())
return getPaddingTop();
- if(getSurfaceView().getTop() + dy <= getPaddingTop() - mDragDistance)
+ if (surfaceViewTop + dy <= getPaddingTop() - mDragDistance)
return getPaddingTop() - mDragDistance;
}
}
@@ -266,7 +314,11 @@ public int clampViewPositionVertical(View child, int top, int dy) {
@Override
public boolean tryCaptureView(View child, int pointerId) {
- return child == getSurfaceView() || child == getBottomView();
+ boolean result = child == getSurfaceView() || getBottomViews().contains(child);
+ if (result) {
+ isCloseBeforeDrag = getOpenStatus() == Status.Close;
+ }
+ return result;
}
@Override
@@ -279,19 +331,14 @@ public int getViewVerticalDragRange(View child) {
return mDragDistance;
}
+ boolean isCloseBeforeDrag = true;
+
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
- for(SwipeListener l : mSwipeListeners)
+ processHandRelease(xvel, yvel, isCloseBeforeDrag);
+ for (SwipeListener l : mSwipeListeners) {
l.onHandRelease(SwipeLayout.this, xvel, yvel);
- if(releasedChild == getSurfaceView()){
- processSurfaceRelease(xvel, yvel);
- }else if(releasedChild == getBottomView()){
- if(getShowMode() == ShowMode.PullOut){
- processBottomPullOutRelease(xvel, yvel);
- }else if(getShowMode() == ShowMode.LayDown){
- processBottomLayDownMode(xvel, yvel);
- }
}
invalidate();
@@ -299,34 +346,46 @@ public void onViewReleased(View releasedChild, float xvel, float yvel) {
@Override
public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
- int evLeft = getSurfaceView().getLeft(), evRight = getSurfaceView().getRight(),
- evTop = getSurfaceView().getTop(),evBottom = getSurfaceView().getBottom();
- if(changedView == getSurfaceView()){
-
- if(mShowMode == ShowMode.PullOut){
- if(mDragEdge == DragEdge.Left || mDragEdge == DragEdge.Right)
- getBottomView().offsetLeftAndRight(dx);
- else
- getBottomView().offsetTopAndBottom(dy);
+ View surfaceView = getSurfaceView();
+ if (surfaceView == null) return;
+ View currentBottomView = getCurrentBottomView();
+ int evLeft = surfaceView.getLeft(),
+ evRight = surfaceView.getRight(),
+ evTop = surfaceView.getTop(),
+ evBottom = surfaceView.getBottom();
+ if (changedView == surfaceView) {
+
+ if (mShowMode == ShowMode.PullOut && currentBottomView != null) {
+ if (mCurrentDragEdge == DragEdge.Left || mCurrentDragEdge == DragEdge.Right) {
+ currentBottomView.offsetLeftAndRight(dx);
+ } else {
+ currentBottomView.offsetTopAndBottom(dy);
+ }
}
- }else if(changedView == getBottomView()){
+ } else if (getBottomViews().contains(changedView)) {
- if(mShowMode == ShowMode.PullOut){
- getSurfaceView().offsetLeftAndRight(dx);
- getSurfaceView().offsetTopAndBottom(dy);
- }else{
- Rect rect = computeBottomLayDown(mDragEdge);
- getBottomView().layout(rect.left, rect.top, rect.right, rect.bottom);
+ if (mShowMode == ShowMode.PullOut) {
+ surfaceView.offsetLeftAndRight(dx);
+ surfaceView.offsetTopAndBottom(dy);
+ } else {
+ Rect rect = computeBottomLayDown(mCurrentDragEdge);
+ if (currentBottomView != null) {
+ currentBottomView.layout(rect.left, rect.top, rect.right, rect.bottom);
+ }
- int newLeft = getSurfaceView().getLeft() + dx, newTop = getSurfaceView().getTop() + dy;
+ int newLeft = surfaceView.getLeft() + dx, newTop = surfaceView.getTop() + dy;
- if(mDragEdge == DragEdge.Left && newLeft < getPaddingLeft()) newLeft = getPaddingLeft();
- else if(mDragEdge == DragEdge.Right && newLeft > getPaddingLeft()) newLeft = getPaddingLeft();
- else if(mDragEdge == DragEdge.Top && newTop < getPaddingTop()) newTop = getPaddingTop();
- else if(mDragEdge == DragEdge.Bottom && newTop > getPaddingTop()) newTop = getPaddingTop();
+ if (mCurrentDragEdge == DragEdge.Left && newLeft < getPaddingLeft())
+ newLeft = getPaddingLeft();
+ else if (mCurrentDragEdge == DragEdge.Right && newLeft > getPaddingLeft())
+ newLeft = getPaddingLeft();
+ else if (mCurrentDragEdge == DragEdge.Top && newTop < getPaddingTop())
+ newTop = getPaddingTop();
+ else if (mCurrentDragEdge == DragEdge.Bottom && newTop > getPaddingTop())
+ newTop = getPaddingTop();
- getSurfaceView().layout(newLeft, newTop, newLeft + getMeasuredWidth(), newTop + getMeasuredHeight());
+ surfaceView.layout(newLeft, newTop, newLeft + getMeasuredWidth(), newTop + getMeasuredHeight());
}
}
@@ -335,106 +394,116 @@ public void onViewPositionChanged(View changedView, int left, int top, int dx, i
dispatchSwipeEvent(evLeft, evTop, dx, dy);
invalidate();
+
+ captureChildrenBound();
}
};
/**
- * the dispatchRevealEvent method may not always get accurate position, it makes the view may not always get the event when the view is
- * totally show( fraction = 1), so , we need to calculate every time.
- * @param child
- * @param relativePosition
- * @param edge
- * @param surfaceLeft
- * @param surfaceTop
- * @param surfaceRight
- * @param surfaceBottom
- * @return
+ * save children's bounds, so they can restore the bound in {@link #onLayout(boolean, int, int, int, int)}
*/
- protected boolean isViewTotallyFirstShowed(View child, Rect relativePosition, DragEdge edge, int surfaceLeft, int surfaceTop, int surfaceRight, int surfaceBottom){
- if(mShowEntirely.get(child))
- return false;
+ private void captureChildrenBound() {
+ View currentBottomView = getCurrentBottomView();
+ if (getOpenStatus() == Status.Close) {
+ mViewBoundCache.remove(currentBottomView);
+ return;
+ }
+
+ View[] views = new View[]{getSurfaceView(), currentBottomView};
+ for (View child : views) {
+ Rect rect = mViewBoundCache.get(child);
+ if (rect == null) {
+ rect = new Rect();
+ mViewBoundCache.put(child, rect);
+ }
+ rect.left = child.getLeft();
+ rect.top = child.getTop();
+ rect.right = child.getRight();
+ rect.bottom = child.getBottom();
+ }
+ }
+
+ /**
+ * the dispatchRevealEvent method may not always get accurate position, it
+ * makes the view may not always get the event when the view is totally
+ * show( fraction = 1), so , we need to calculate every time.
+ */
+ protected boolean isViewTotallyFirstShowed(View child, Rect relativePosition, DragEdge edge, int surfaceLeft,
+ int surfaceTop, int surfaceRight, int surfaceBottom) {
+ if (mShowEntirely.get(child)) return false;
int childLeft = relativePosition.left;
int childRight = relativePosition.right;
int childTop = relativePosition.top;
int childBottom = relativePosition.bottom;
boolean r = false;
- if(getShowMode() == ShowMode.LayDown) {
- if((edge == DragEdge.Right && surfaceRight <= childLeft)
- || (edge == DragEdge.Left && surfaceLeft >= childRight)
- || (edge == DragEdge.Top && surfaceTop >= childBottom)
- || (edge == DragEdge.Bottom && surfaceBottom <= childTop))
- r = true;
- }
- else if(getShowMode() == ShowMode.PullOut){
- if((edge == DragEdge.Right && childRight <= getWidth())
- || (edge == DragEdge.Left && childLeft >= getPaddingLeft())
- || (edge == DragEdge.Top && childTop >= getPaddingTop())
- || (edge == DragEdge.Bottom && childBottom <= getHeight()))
- r = true;
+ if (getShowMode() == ShowMode.LayDown) {
+ if ((edge == DragEdge.Right && surfaceRight <= childLeft)
+ || (edge == DragEdge.Left && surfaceLeft >= childRight)
+ || (edge == DragEdge.Top && surfaceTop >= childBottom)
+ || (edge == DragEdge.Bottom && surfaceBottom <= childTop)) r = true;
+ } else if (getShowMode() == ShowMode.PullOut) {
+ if ((edge == DragEdge.Right && childRight <= getWidth())
+ || (edge == DragEdge.Left && childLeft >= getPaddingLeft())
+ || (edge == DragEdge.Top && childTop >= getPaddingTop())
+ || (edge == DragEdge.Bottom && childBottom <= getHeight())) r = true;
}
return r;
}
- protected boolean isViewShowing(View child, Rect relativePosition, DragEdge availableEdge, int surfaceLeft, int surfaceTop, int surfaceRight, int surfaceBottom){
+ protected boolean isViewShowing(View child, Rect relativePosition, DragEdge availableEdge, int surfaceLeft,
+ int surfaceTop, int surfaceRight, int surfaceBottom) {
int childLeft = relativePosition.left;
int childRight = relativePosition.right;
int childTop = relativePosition.top;
int childBottom = relativePosition.bottom;
- if(getShowMode() == ShowMode.LayDown){
- switch (availableEdge){
+ if (getShowMode() == ShowMode.LayDown) {
+ switch (availableEdge) {
case Right:
- if(surfaceRight > childLeft && surfaceRight <= childRight){
+ if (surfaceRight > childLeft && surfaceRight <= childRight) {
return true;
}
break;
case Left:
- if(surfaceLeft < childRight && surfaceLeft >= childLeft){
+ if (surfaceLeft < childRight && surfaceLeft >= childLeft) {
return true;
}
break;
case Top:
- if(surfaceTop >= childTop && surfaceTop < childBottom){
- return true;
+ if (surfaceTop >= childTop && surfaceTop < childBottom) {
+ return true;
}
break;
case Bottom:
- if(surfaceBottom > childTop && surfaceBottom <= childBottom){
+ if (surfaceBottom > childTop && surfaceBottom <= childBottom) {
return true;
}
break;
}
- }else if(getShowMode() == ShowMode.PullOut){
- switch (availableEdge){
+ } else if (getShowMode() == ShowMode.PullOut) {
+ switch (availableEdge) {
case Right:
- if(childLeft <= getWidth() && childRight > getWidth())
- return true;
+ if (childLeft <= getWidth() && childRight > getWidth()) return true;
break;
case Left:
- if(childRight >= getPaddingLeft() && childLeft < getPaddingLeft())
- return true;
+ if (childRight >= getPaddingLeft() && childLeft < getPaddingLeft()) return true;
break;
case Top:
- if(childTop < getPaddingTop() && childBottom >= getPaddingTop())
- return true;
+ if (childTop < getPaddingTop() && childBottom >= getPaddingTop()) return true;
break;
case Bottom:
- if(childTop < getHeight() && childTop >= getPaddingTop())
- return true;
+ if (childTop < getHeight() && childTop >= getPaddingTop()) return true;
break;
}
}
return false;
}
-
-
- protected Rect getRelativePosition(View child){
+ protected Rect getRelativePosition(View child) {
View t = child;
- Rect r = new Rect(t.getLeft(), t.getTop(), 0 , 0);
- while(t.getParent() != null && t != getRootView()){
- t = (View)t.getParent();
- if(t == this)
- break;
+ Rect r = new Rect(t.getLeft(), t.getTop(), 0, 0);
+ while (t.getParent() != null && t != getRootView()) {
+ t = (View) t.getParent();
+ if (t == this) break;
r.left += t.getLeft();
r.top += t.getTop();
}
@@ -445,49 +514,52 @@ protected Rect getRelativePosition(View child){
private int mEventCounter = 0;
- protected void dispatchSwipeEvent(int surfaceLeft, int surfaceTop, int dx, int dy){
+ protected void dispatchSwipeEvent(int surfaceLeft, int surfaceTop, int dx, int dy) {
DragEdge edge = getDragEdge();
boolean open = true;
- if(edge == DragEdge.Left){
- if(dx < 0) open = false;
- }else if(edge == DragEdge.Right){
- if(dx > 0) open = false;
- }else if(edge == DragEdge.Top){
- if(dy < 0) open = false;
- }else if(edge == DragEdge.Bottom){
- if(dy > 0) open = false;
+ if (edge == DragEdge.Left) {
+ if (dx < 0) open = false;
+ } else if (edge == DragEdge.Right) {
+ if (dx > 0) open = false;
+ } else if (edge == DragEdge.Top) {
+ if (dy < 0) open = false;
+ } else if (edge == DragEdge.Bottom) {
+ if (dy > 0) open = false;
}
dispatchSwipeEvent(surfaceLeft, surfaceTop, open);
}
- protected void dispatchSwipeEvent(int surfaceLeft, int surfaceTop, boolean open){
+ protected void dispatchSwipeEvent(int surfaceLeft, int surfaceTop, boolean open) {
safeBottomView();
Status status = getOpenStatus();
- if(!mSwipeListeners.isEmpty()){
+ if (!mSwipeListeners.isEmpty()) {
mEventCounter++;
- for(SwipeListener l : mSwipeListeners){
- if(mEventCounter == 1){
- if(open){
+ for (SwipeListener l : mSwipeListeners) {
+ if (mEventCounter == 1) {
+ if (open) {
l.onStartOpen(this);
- }else{
+ } else {
l.onStartClose(this);
}
}
l.onUpdate(SwipeLayout.this, surfaceLeft - getPaddingLeft(), surfaceTop - getPaddingTop());
}
- if(status == Status.Close){
- for(SwipeListener l : mSwipeListeners){
+ if (status == Status.Close) {
+ for (SwipeListener l : mSwipeListeners) {
l.onClose(SwipeLayout.this);
}
mEventCounter = 0;
}
- if(status == Status.Open){
- getBottomView().setEnabled(true);
- for(SwipeListener l : mSwipeListeners){
+ if (status == Status.Open) {
+ View currentBottomView = getCurrentBottomView();
+ if (currentBottomView != null) {
+ currentBottomView.setEnabled(true);
+ }
+ for (SwipeListener l : mSwipeListeners) {
l.onOpen(SwipeLayout.this);
}
mEventCounter = 0;
@@ -498,84 +570,92 @@ protected void dispatchSwipeEvent(int surfaceLeft, int surfaceTop, boolean open)
/**
* prevent bottom view get any touch event. Especially in LayDown mode.
*/
- private void safeBottomView(){
+ private void safeBottomView() {
Status status = getOpenStatus();
- ViewGroup bottom = getBottomView();
+ List bottoms = getBottomViews();
- if(status == Status.Close){
- if(bottom.getVisibility() != INVISIBLE)
- bottom.setVisibility(INVISIBLE);
- }else {
- if(bottom.getVisibility() != VISIBLE)
- bottom.setVisibility(VISIBLE);
+ if (status == Status.Close) {
+ for (View bottom : bottoms) {
+ if (bottom != null && bottom.getVisibility() != INVISIBLE) {
+ bottom.setVisibility(INVISIBLE);
+ }
+ }
+ } else {
+ View currentBottomView = getCurrentBottomView();
+ if (currentBottomView != null && currentBottomView.getVisibility() != VISIBLE) {
+ currentBottomView.setVisibility(VISIBLE);
+ }
}
}
-
- protected void dispatchRevealEvent(final int surfaceLeft, final int surfaceTop, final int surfaceRight, final int surfaceBottom){
- if(mRevealListeners.isEmpty()) return;
- for(Map.Entry> entry : mRevealListeners.entrySet()){
+ protected void dispatchRevealEvent(final int surfaceLeft, final int surfaceTop, final int surfaceRight,
+ final int surfaceBottom) {
+ if (mRevealListeners.isEmpty()) return;
+ for (Map.Entry> entry : mRevealListeners.entrySet()) {
View child = entry.getKey();
Rect rect = getRelativePosition(child);
- if(isViewShowing(child,rect, mDragEdge, surfaceLeft, surfaceTop, surfaceRight, surfaceBottom)){
+ if (isViewShowing(child, rect, mCurrentDragEdge, surfaceLeft, surfaceTop,
+ surfaceRight, surfaceBottom)) {
mShowEntirely.put(child, false);
int distance = 0;
float fraction = 0f;
- if(getShowMode() == ShowMode.LayDown){
- switch (mDragEdge){
+ if (getShowMode() == ShowMode.LayDown) {
+ switch (mCurrentDragEdge) {
case Left:
distance = rect.left - surfaceLeft;
- fraction = distance/(float)child.getWidth();
+ fraction = distance / (float) child.getWidth();
break;
case Right:
distance = rect.right - surfaceRight;
- fraction = distance/(float)child.getWidth();
+ fraction = distance / (float) child.getWidth();
break;
case Top:
distance = rect.top - surfaceTop;
- fraction = distance/(float)child.getHeight();
+ fraction = distance / (float) child.getHeight();
break;
case Bottom:
distance = rect.bottom - surfaceBottom;
- fraction = distance/(float)child.getHeight();
+ fraction = distance / (float) child.getHeight();
break;
}
- }else if(getShowMode() == ShowMode.PullOut){
- switch (mDragEdge){
+ } else if (getShowMode() == ShowMode.PullOut) {
+ switch (mCurrentDragEdge) {
case Left:
distance = rect.right - getPaddingLeft();
- fraction = distance / (float)child.getWidth();
+ fraction = distance / (float) child.getWidth();
break;
case Right:
distance = rect.left - getWidth();
- fraction = distance / (float)child.getWidth();
+ fraction = distance / (float) child.getWidth();
break;
case Top:
distance = rect.bottom - getPaddingTop();
- fraction = distance/(float)child.getHeight();
+ fraction = distance / (float) child.getHeight();
break;
case Bottom:
distance = rect.top - getHeight();
- fraction = distance/(float)child.getHeight();
+ fraction = distance / (float) child.getHeight();
break;
}
}
- for(OnRevealListener l : entry.getValue()){
- l.onReveal(child, mDragEdge, Math.abs(fraction), distance);
- if(Math.abs(fraction) == 1){
+ for (OnRevealListener l : entry.getValue()) {
+ l.onReveal(child, mCurrentDragEdge, Math.abs(fraction), distance);
+ if (Math.abs(fraction) == 1) {
mShowEntirely.put(child, true);
}
}
}
- if(isViewTotallyFirstShowed(child, rect, mDragEdge, surfaceLeft, surfaceTop, surfaceRight, surfaceBottom)){
+ if (isViewTotallyFirstShowed(child, rect, mCurrentDragEdge, surfaceLeft, surfaceTop,
+ surfaceRight, surfaceBottom)) {
mShowEntirely.put(child, true);
- for(OnRevealListener l : entry.getValue()){
- if(mDragEdge == DragEdge.Left || mDragEdge == DragEdge.Right)
- l.onReveal(child, mDragEdge, 1, child.getWidth());
+ for (OnRevealListener l : entry.getValue()) {
+ if (mCurrentDragEdge == DragEdge.Left
+ || mCurrentDragEdge == DragEdge.Right)
+ l.onReveal(child, mCurrentDragEdge, 1, child.getWidth());
else
- l.onReveal(child, mDragEdge, 1, child.getHeight());
+ l.onReveal(child, mCurrentDragEdge, 1, child.getHeight());
}
}
@@ -585,395 +665,555 @@ protected void dispatchRevealEvent(final int surfaceLeft, final int surfaceTop,
@Override
public void computeScroll() {
super.computeScroll();
- if(mDragHelper.continueSettling(true)) {
+ if (mDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(this);
}
}
/**
- * {@link android.view.View.OnLayoutChangeListener} added in API 11.
- * I need to support it from API 8.
+ * {@link android.view.View.OnLayoutChangeListener} added in API 11. I need
+ * to support it from API 8.
*/
- public interface OnLayout{
- public void onLayout(SwipeLayout v);
+ public interface OnLayout {
+ void onLayout(SwipeLayout v);
}
private List mOnLayoutListeners;
- public void addOnLayoutListener(OnLayout l){
- if(mOnLayoutListeners == null)
- mOnLayoutListeners = new ArrayList();
+ public void addOnLayoutListener(OnLayout l) {
+ if (mOnLayoutListeners == null) mOnLayoutListeners = new ArrayList();
mOnLayoutListeners.add(l);
}
- public void removeOnLayoutListener(OnLayout l){
- if(mOnLayoutListeners != null)
- mOnLayoutListeners.remove(l);
+ public void removeOnLayoutListener(OnLayout l) {
+ if (mOnLayoutListeners != null) mOnLayoutListeners.remove(l);
}
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- int childCount = getChildCount();
- if(childCount != 2){
- throw new IllegalStateException("You need 2 views in SwipeLayout");
+ public void clearDragEdge() {
+ mDragEdges.clear();
+ }
+
+ public void setDrag(DragEdge dragEdge, int childId) {
+ clearDragEdge();
+ addDrag(dragEdge, childId);
+ }
+
+ public void setDrag(DragEdge dragEdge, View child) {
+ clearDragEdge();
+ addDrag(dragEdge, child);
+ }
+
+ public void addDrag(DragEdge dragEdge, int childId) {
+ addDrag(dragEdge, findViewById(childId), null);
+ }
+
+ public void addDrag(DragEdge dragEdge, View child) {
+ addDrag(dragEdge, child, null);
+ }
+
+ public void addDrag(DragEdge dragEdge, View child, ViewGroup.LayoutParams params) {
+ if (child == null) return;
+
+ if (params == null) {
+ params = generateDefaultLayoutParams();
}
- if(!(getChildAt(0) instanceof ViewGroup) || !(getChildAt(1) instanceof ViewGroup)){
- throw new IllegalArgumentException("The 2 children in SwipeLayout must be an instance of ViewGroup");
+ if (!checkLayoutParams(params)) {
+ params = generateLayoutParams(params);
}
+ int gravity = -1;
+ switch (dragEdge) {
+ case Left:
+ gravity = Gravity.LEFT;
+ break;
+ case Right:
+ gravity = Gravity.RIGHT;
+ break;
+ case Top:
+ gravity = Gravity.TOP;
+ break;
+ case Bottom:
+ gravity = Gravity.BOTTOM;
+ break;
+ }
+ if (params instanceof FrameLayout.LayoutParams) {
+ ((LayoutParams) params).gravity = gravity;
+ }
+ addView(child, 0, params);
+ }
- if(mShowMode == ShowMode.PullOut)
- layoutPullOut();
- else if(mShowMode == ShowMode.LayDown)
- layoutLayDown();
+ @Override
+ public void addView(View child, int index, ViewGroup.LayoutParams params) {
+ if (child == null) return;
+ int gravity = Gravity.NO_GRAVITY;
+ try {
+ gravity = (Integer) params.getClass().getField("gravity").get(params);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
- safeBottomView();
+ if (gravity > 0) {
+ gravity = GravityCompat.getAbsoluteGravity(gravity, ViewCompat.getLayoutDirection(this));
- if(mOnLayoutListeners != null)
- for(int i = 0; i < mOnLayoutListeners.size(); i++){
- mOnLayoutListeners.get(i).onLayout(this);
+ if ((gravity & Gravity.LEFT) == Gravity.LEFT) {
+ mDragEdges.put(DragEdge.Left, child);
+ }
+ if ((gravity & Gravity.RIGHT) == Gravity.RIGHT) {
+ mDragEdges.put(DragEdge.Right, child);
}
+ if ((gravity & Gravity.TOP) == Gravity.TOP) {
+ mDragEdges.put(DragEdge.Top, child);
+ }
+ if ((gravity & Gravity.BOTTOM) == Gravity.BOTTOM) {
+ mDragEdges.put(DragEdge.Bottom, child);
+ }
+ } else {
+ for (Map.Entry entry : mDragEdges.entrySet()) {
+ if (entry.getValue() == null) {
+ //means used the drag_edge attr, the no gravity child should be use set
+ mDragEdges.put(entry.getKey(), child);
+ break;
+ }
+ }
+ }
+ if (child.getParent() == this) {
+ return;
+ }
+ super.addView(child, index, params);
+ }
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ updateBottomViews();
+
+ if (mOnLayoutListeners != null) for (int i = 0; i < mOnLayoutListeners.size(); i++) {
+ mOnLayoutListeners.get(i).onLayout(this);
+ }
}
- void layoutPullOut(){
- Rect rect = computeSurfaceLayoutArea(false);
- getSurfaceView().layout(rect.left, rect.top, rect.right, rect.bottom);
- rect = computeBottomLayoutAreaViaSurface(ShowMode.PullOut, rect);
- getBottomView().layout(rect.left, rect.top, rect.right, rect.bottom);
- bringChildToFront(getSurfaceView());
+ void layoutPullOut() {
+ View surfaceView = getSurfaceView();
+ Rect surfaceRect = mViewBoundCache.get(surfaceView);
+ if (surfaceRect == null) surfaceRect = computeSurfaceLayoutArea(false);
+ if (surfaceView != null) {
+ surfaceView.layout(surfaceRect.left, surfaceRect.top, surfaceRect.right, surfaceRect.bottom);
+ bringChildToFront(surfaceView);
+ }
+ View currentBottomView = getCurrentBottomView();
+ Rect bottomViewRect = mViewBoundCache.get(currentBottomView);
+ if (bottomViewRect == null)
+ bottomViewRect = computeBottomLayoutAreaViaSurface(ShowMode.PullOut, surfaceRect);
+ if (currentBottomView != null) {
+ currentBottomView.layout(bottomViewRect.left, bottomViewRect.top, bottomViewRect.right, bottomViewRect.bottom);
+ }
}
- void layoutLayDown(){
- Rect rect = computeSurfaceLayoutArea(false);
- getSurfaceView().layout(rect.left, rect.top, rect.right, rect.bottom);
- rect = computeBottomLayoutAreaViaSurface(ShowMode.LayDown, rect);
- getBottomView().layout(rect.left, rect.top, rect.right, rect.bottom);
- bringChildToFront(getSurfaceView());
+ void layoutLayDown() {
+ View surfaceView = getSurfaceView();
+ Rect surfaceRect = mViewBoundCache.get(surfaceView);
+ if (surfaceRect == null) surfaceRect = computeSurfaceLayoutArea(false);
+ if (surfaceView != null) {
+ surfaceView.layout(surfaceRect.left, surfaceRect.top, surfaceRect.right, surfaceRect.bottom);
+ bringChildToFront(surfaceView);
+ }
+ View currentBottomView = getCurrentBottomView();
+ Rect bottomViewRect = mViewBoundCache.get(currentBottomView);
+ if (bottomViewRect == null)
+ bottomViewRect = computeBottomLayoutAreaViaSurface(ShowMode.LayDown, surfaceRect);
+ if (currentBottomView != null) {
+ currentBottomView.layout(bottomViewRect.left, bottomViewRect.top, bottomViewRect.right, bottomViewRect.bottom);
+ }
}
+ private boolean mIsBeingDragged;
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ private void checkCanDrag(MotionEvent ev) {
+ if (mIsBeingDragged) return;
+ if (getOpenStatus() == Status.Middle) {
+ mIsBeingDragged = true;
+ return;
+ }
+ Status status = getOpenStatus();
+ float distanceX = ev.getRawX() - sX;
+ float distanceY = ev.getRawY() - sY;
+ float angle = Math.abs(distanceY / distanceX);
+ angle = (float) Math.toDegrees(Math.atan(angle));
+ if (getOpenStatus() == Status.Close) {
+ DragEdge dragEdge;
+ if (angle < 45) {
+ if (distanceX > 0 && isLeftSwipeEnabled()) {
+ dragEdge = DragEdge.Left;
+ } else if (distanceX < 0 && isRightSwipeEnabled()) {
+ dragEdge = DragEdge.Right;
+ } else return;
- if(mDragEdge == DragEdge.Left || mDragEdge == DragEdge.Right)
- mDragDistance = getBottomView().getMeasuredWidth();
- else
- mDragDistance = getBottomView().getMeasuredHeight();
- }
+ } else {
+ if (distanceY > 0 && isTopSwipeEnabled()) {
+ dragEdge = DragEdge.Top;
+ } else if (distanceY < 0 && isBottomSwipeEnabled()) {
+ dragEdge = DragEdge.Bottom;
+ } else return;
+ }
+ setCurrentDragEdge(dragEdge);
+ }
- private boolean mTouchConsumedByChild = false;
+ boolean doNothing = false;
+ if (mCurrentDragEdge == DragEdge.Right) {
+ boolean suitable = (status == Status.Open && distanceX > mTouchSlop)
+ || (status == Status.Close && distanceX < -mTouchSlop);
+ suitable = suitable || (status == Status.Middle);
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
+ if (angle > 30 || !suitable) {
+ doNothing = true;
+ }
+ }
- if(!isEnabled() || !isEnabledInAdapterView()){
- return true;
+ if (mCurrentDragEdge == DragEdge.Left) {
+ boolean suitable = (status == Status.Open && distanceX < -mTouchSlop)
+ || (status == Status.Close && distanceX > mTouchSlop);
+ suitable = suitable || status == Status.Middle;
+
+ if (angle > 30 || !suitable) {
+ doNothing = true;
+ }
}
- if(!isSwipeEnabled()){
- return false;
+ if (mCurrentDragEdge == DragEdge.Top) {
+ boolean suitable = (status == Status.Open && distanceY < -mTouchSlop)
+ || (status == Status.Close && distanceY > mTouchSlop);
+ suitable = suitable || status == Status.Middle;
+
+ if (angle < 60 || !suitable) {
+ doNothing = true;
+ }
+ }
+
+ if (mCurrentDragEdge == DragEdge.Bottom) {
+ boolean suitable = (status == Status.Open && distanceY > mTouchSlop)
+ || (status == Status.Close && distanceY < -mTouchSlop);
+ suitable = suitable || status == Status.Middle;
+
+ if (angle < 60 || !suitable) {
+ doNothing = true;
+ }
}
+ mIsBeingDragged = !doNothing;
+ }
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ if (!isSwipeEnabled()) {
+ return false;
+ }
+ if (mClickToClose && getOpenStatus() == Status.Open && isTouchOnSurface(ev)) {
+ return true;
+ }
for (SwipeDenier denier : mSwipeDeniers) {
if (denier != null && denier.shouldDenySwipe(ev)) {
return false;
}
}
- //
- //if a child wants to handle the touch event,
- //then let it do it.
- //
- int action = ev.getActionMasked();
- switch (action){
+
+ switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
- Status status = getOpenStatus();
- if(status == Status.Close){
- mTouchConsumedByChild = childNeedHandleTouchEvent(getSurfaceView(), ev) != null;
- }else if(status == Status.Open){
- mTouchConsumedByChild = childNeedHandleTouchEvent(getBottomView(), ev) != null;
+ mDragHelper.processTouchEvent(ev);
+ mIsBeingDragged = false;
+ sX = ev.getRawX();
+ sY = ev.getRawY();
+ //if the swipe is in middle state(scrolling), should intercept the touch
+ if (getOpenStatus() == Status.Middle) {
+ mIsBeingDragged = true;
+ }
+ break;
+ case MotionEvent.ACTION_MOVE:
+ boolean beforeCheck = mIsBeingDragged;
+ checkCanDrag(ev);
+ if (mIsBeingDragged) {
+ ViewParent parent = getParent();
+ if (parent != null) {
+ parent.requestDisallowInterceptTouchEvent(true);
+ }
+ }
+ if (!beforeCheck && mIsBeingDragged) {
+ //let children has one chance to catch the touch, and request the swipe not intercept
+ //useful when swipeLayout wrap a swipeLayout or other gestural layout
+ return false;
}
break;
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_CANCEL:
- mTouchConsumedByChild = false;
- }
-
- if(mTouchConsumedByChild) return false;
- return mDragHelper.shouldInterceptTouchEvent(ev);
- }
- /**
- * if the ViewGroup children want to handle this event.
- * @param v
- * @param event
- * @return
- */
- private View childNeedHandleTouchEvent(ViewGroup v, MotionEvent event){
- if(v == null) return null;
- if(v.onTouchEvent(event))
- return v;
-
- int childCount = v.getChildCount();
- for(int i = childCount - 1; i >= 0; i--){
- View child = v.getChildAt(i);
- if(child instanceof ViewGroup){
- View grandChild = childNeedHandleTouchEvent((ViewGroup) child, event);
- if(grandChild != null)
- return grandChild;
- }else{
- if(childNeedHandleTouchEvent(v.getChildAt(i), event))
- return v.getChildAt(i);
- }
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP:
+ mIsBeingDragged = false;
+ mDragHelper.processTouchEvent(ev);
+ break;
+ default://handle other action, such as ACTION_POINTER_DOWN/UP
+ mDragHelper.processTouchEvent(ev);
}
- return null;
+ return mIsBeingDragged;
}
- /**
- * if the view (v) wants to handle this event.
- * @param v
- * @param event
- * @return
- */
- private boolean childNeedHandleTouchEvent(View v, MotionEvent event){
- if(v == null) return false;
-
- int[] loc = new int[2];
- v.getLocationOnScreen(loc);
- int left = loc[0], top = loc[1];
+ private float sX = -1, sY = -1;
- if(event.getRawX() > left && event.getRawX() < left + v.getWidth()
- && event.getRawY() > top && event.getRawY() < top + v.getHeight()){
- return v.onTouchEvent(event);
- }
-
- return false;
- }
-
- private float sX = -1 , sY = -1;
@Override
public boolean onTouchEvent(MotionEvent event) {
- if(!isEnabledInAdapterView() || !isEnabled())
- return true;
-
- if(!isSwipeEnabled())
- return super.onTouchEvent(event);
+ if (!isSwipeEnabled()) return super.onTouchEvent(event);
int action = event.getActionMasked();
- ViewParent parent = getParent();
-
gestureDetector.onTouchEvent(event);
- Status status = getOpenStatus();
- ViewGroup touching = null;
- if(status == Status.Close){
- touching = getSurfaceView();
- }else if(status == Status.Open){
- touching = getBottomView();
- }
- switch (action){
+ switch (action) {
case MotionEvent.ACTION_DOWN:
mDragHelper.processTouchEvent(event);
- parent.requestDisallowInterceptTouchEvent(true);
-
sX = event.getRawX();
sY = event.getRawY();
- if(touching != null)
- touching.setPressed(true);
- return true;
- case MotionEvent.ACTION_MOVE:{
- if(sX == -1 || sY == -1){
- // Trick:
- // When in nested mode, we need to send a constructed ACTION_DOWN MotionEvent to mDragHelper, to help
- // it initialize itself.
- event.setAction(MotionEvent.ACTION_DOWN);
+ case MotionEvent.ACTION_MOVE: {
+ //the drag state and the direction are already judged at onInterceptTouchEvent
+ checkCanDrag(event);
+ if (mIsBeingDragged) {
+ getParent().requestDisallowInterceptTouchEvent(true);
mDragHelper.processTouchEvent(event);
- parent.requestDisallowInterceptTouchEvent(true);
- sX = event.getRawX();
- sY = event.getRawY();
- return true;
}
+ break;
+ }
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
+ mIsBeingDragged = false;
+ mDragHelper.processTouchEvent(event);
+ break;
- float distanceX = event.getRawX() - sX;
- float distanceY = event.getRawY() - sY;
- float angle = Math.abs(distanceY / distanceX);
- angle = (float)Math.toDegrees(Math.atan(angle));
+ default://handle other action, such as ACTION_POINTER_DOWN/UP
+ mDragHelper.processTouchEvent(event);
+ }
- boolean doNothing = false;
- if(mDragEdge == DragEdge.Right){
- boolean suitable = (status == Status.Open && distanceX > 0) || (status == Status.Close && distanceX < 0);
- suitable = suitable || (status == Status.Middle);
+ return super.onTouchEvent(event) || mIsBeingDragged || action == MotionEvent.ACTION_DOWN;
+ }
- if(angle > 30 || !suitable){
- doNothing = true;
- }
- }
+ public boolean isClickToClose() {
+ return mClickToClose;
+ }
- if(mDragEdge == DragEdge.Left){
- boolean suitable = (status == Status.Open && distanceX < 0 ) || (status == Status.Close && distanceX > 0);
- suitable = suitable || status == Status.Middle;
+ public void setClickToClose(boolean mClickToClose) {
+ this.mClickToClose = mClickToClose;
+ }
- if(angle > 30 || ! suitable){
- doNothing = true;
- }
- }
+ public void setSwipeEnabled(boolean enabled) {
+ mSwipeEnabled = enabled;
+ }
- if(mDragEdge == DragEdge.Top){
- boolean suitable = (status == Status.Open && distanceY < 0 ) || (status == Status.Close && distanceY > 0);
- suitable = suitable || status == Status.Middle;
+ public boolean isSwipeEnabled() {
+ return mSwipeEnabled;
+ }
- if(angle < 60 || ! suitable){
- doNothing = true;
- }
- }
+ public boolean isLeftSwipeEnabled() {
+ View bottomView = mDragEdges.get(DragEdge.Left);
+ return bottomView != null && bottomView.getParent() == this
+ && bottomView != getSurfaceView() && mSwipesEnabled[DragEdge.Left.ordinal()];
+ }
- if(mDragEdge == DragEdge.Bottom){
- boolean suitable = (status == Status.Open && distanceY > 0 ) || (status == Status.Close && distanceY < 0);
- suitable = suitable || status == Status.Middle;
+ public void setLeftSwipeEnabled(boolean leftSwipeEnabled) {
+ this.mSwipesEnabled[DragEdge.Left.ordinal()] = leftSwipeEnabled;
+ }
- if(angle < 60 || ! suitable){
- doNothing = true;
- }
- }
+ public boolean isRightSwipeEnabled() {
+ View bottomView = mDragEdges.get(DragEdge.Right);
+ return bottomView != null && bottomView.getParent() == this
+ && bottomView != getSurfaceView() && mSwipesEnabled[DragEdge.Right.ordinal()];
+ }
- if(doNothing){
- parent.requestDisallowInterceptTouchEvent(false);
- return false;
- }else{
- if(touching != null){
- touching.setPressed(false);
- }
- parent.requestDisallowInterceptTouchEvent(true);
- mDragHelper.processTouchEvent(event);
- }
- break;
- }
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_CANCEL:
- {
- sX = -1;
- sY = -1;
- if(touching != null){
- touching.setPressed(false);
- }
- }
- default:
- parent.requestDisallowInterceptTouchEvent(true);
- mDragHelper.processTouchEvent(event);
- }
+ public void setRightSwipeEnabled(boolean rightSwipeEnabled) {
+ this.mSwipesEnabled[DragEdge.Right.ordinal()] = rightSwipeEnabled;
+ }
- return true;
+ public boolean isTopSwipeEnabled() {
+ View bottomView = mDragEdges.get(DragEdge.Top);
+ return bottomView != null && bottomView.getParent() == this
+ && bottomView != getSurfaceView() && mSwipesEnabled[DragEdge.Top.ordinal()];
}
- /**
- * if working in {@link android.widget.AdapterView}, we should response {@link android.widget.Adapter}
- * isEnable(int position).
- * @return true when item is enabled, else disabled.
+ public void setTopSwipeEnabled(boolean topSwipeEnabled) {
+ this.mSwipesEnabled[DragEdge.Top.ordinal()] = topSwipeEnabled;
+ }
+
+ public boolean isBottomSwipeEnabled() {
+ View bottomView = mDragEdges.get(DragEdge.Bottom);
+ return bottomView != null && bottomView.getParent() == this
+ && bottomView != getSurfaceView() && mSwipesEnabled[DragEdge.Bottom.ordinal()];
+ }
+
+ public void setBottomSwipeEnabled(boolean bottomSwipeEnabled) {
+ this.mSwipesEnabled[DragEdge.Bottom.ordinal()] = bottomSwipeEnabled;
+ }
+
+ /***
+ * Returns the percentage of revealing at which the view below should the view finish opening
+ * if it was already open before dragging
+ *
+ * @returns The percentage of view revealed to trigger, default value is 0.25
*/
- private boolean isEnabledInAdapterView(){
- AdapterView adapterView = getAdapterView();
- boolean enable = true;
- if(adapterView != null){
- Adapter adapter = adapterView.getAdapter();
- if(adapter != null){
- int p = adapterView.getPositionForView(SwipeLayout.this);
- if(adapter instanceof BaseAdapter){
- enable = ((BaseAdapter) adapter).isEnabled(p);
- }else if(adapter instanceof ListAdapter){
- enable = ((ListAdapter) adapter).isEnabled(p);
- }
- }
- }
- return enable;
+ public float getWillOpenPercentAfterOpen() {
+ return mWillOpenPercentAfterOpen;
}
- public void setSwipeEnabled(boolean enabled){
- mSwipeEnabled = enabled;
+ /***
+ * Allows to stablish at what percentage of revealing the view below should the view finish opening
+ * if it was already open before dragging
+ *
+ * @param willOpenPercentAfterOpen The percentage of view revealed to trigger, default value is 0.25
+ */
+ public void setWillOpenPercentAfterOpen(float willOpenPercentAfterOpen) {
+ this.mWillOpenPercentAfterOpen = willOpenPercentAfterOpen;
}
- public boolean isSwipeEnabled(){
- return mSwipeEnabled;
+ /***
+ * Returns the percentage of revealing at which the view below should the view finish opening
+ * if it was already closed before dragging
+ *
+ * @returns The percentage of view revealed to trigger, default value is 0.25
+ */
+ public float getWillOpenPercentAfterClose() {
+ return mWillOpenPercentAfterClose;
}
- private boolean insideAdapterView(){
+ /***
+ * Allows to stablish at what percentage of revealing the view below should the view finish opening
+ * if it was already closed before dragging
+ *
+ * @param willOpenPercentAfterClose The percentage of view revealed to trigger, default value is 0.75
+ */
+ public void setWillOpenPercentAfterClose(float willOpenPercentAfterClose) {
+ this.mWillOpenPercentAfterClose = willOpenPercentAfterClose;
+ }
+
+ private boolean insideAdapterView() {
return getAdapterView() != null;
}
- private AdapterView getAdapterView(){
+ private AdapterView getAdapterView() {
ViewParent t = getParent();
- while(t != null){
- if(t instanceof AdapterView){
- return (AdapterView)t;
- }
- t = t.getParent();
+ if (t instanceof AdapterView) {
+ return (AdapterView) t;
}
return null;
}
- private void performAdapterViewItemClick(MotionEvent e){
+ private void performAdapterViewItemClick() {
+ if (getOpenStatus() != Status.Close) return;
ViewParent t = getParent();
- while(t != null) {
- if(t instanceof AdapterView){
- AdapterView view = (AdapterView)t;
- int p = view.getPositionForView(SwipeLayout.this);
- if( p != AdapterView.INVALID_POSITION &&
- view.performItemClick(view.getChildAt(p), p, view.getAdapter().getItemId(p)))
- return;
- }else{
- if(t instanceof View && ((View) t).performClick())
- return;
+ if (t instanceof AdapterView) {
+ AdapterView view = (AdapterView) t;
+ int p = view.getPositionForView(SwipeLayout.this);
+ if (p != AdapterView.INVALID_POSITION) {
+ view.performItemClick(view.getChildAt(p - view.getFirstVisiblePosition()), p, view
+ .getAdapter().getItemId(p));
}
- t = t.getParent();
}
}
- private GestureDetector gestureDetector = new GestureDetector(getContext(), new SwipeDetector());
- class SwipeDetector extends GestureDetector.SimpleOnGestureListener{
- @Override
- public boolean onDown(MotionEvent e) {
- return true;
+ private boolean performAdapterViewItemLongClick() {
+ if (getOpenStatus() != Status.Close) return false;
+ ViewParent t = getParent();
+ if (t instanceof AdapterView) {
+ AdapterView view = (AdapterView) t;
+ int p = view.getPositionForView(SwipeLayout.this);
+ if (p == AdapterView.INVALID_POSITION) return false;
+ long vId = view.getItemIdAtPosition(p);
+ boolean handled = false;
+ try {
+ Method m = AbsListView.class.getDeclaredMethod("performLongPress", View.class, int.class, long.class);
+ m.setAccessible(true);
+ handled = (boolean) m.invoke(view, SwipeLayout.this, p, vId);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+
+ if (view.getOnItemLongClickListener() != null) {
+ handled = view.getOnItemLongClickListener().onItemLongClick(view, SwipeLayout.this, p, vId);
+ }
+ if (handled) {
+ view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+ }
+ }
+ return handled;
}
+ return false;
+ }
- /**
- * Simulate the touch event lifecycle. If you use SwipeLayout in {@link android.widget.AdapterView}
- * ({@link android.widget.ListView}, {@link android.widget.GridView} etc.) It will manually call
- * {@link android.widget.AdapterView}.performItemClick, performItemLongClick.
- * @param e
- * @return
- */
- @Override
- public boolean onSingleTapUp(MotionEvent e) {
- if(mDoubleClickListener == null){
- performAdapterViewItemClick(e);
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ if (insideAdapterView()) {
+ if (clickListener == null) {
+ setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ performAdapterViewItemClick();
+ }
+ });
+ }
+ if (longClickListener == null) {
+ setOnLongClickListener(new OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View v) {
+ performAdapterViewItemLongClick();
+ return true;
+ }
+ });
}
- return true;
}
+ }
- @Override
- public boolean onSingleTapConfirmed(MotionEvent e) {
- if(mDoubleClickListener != null){
- performAdapterViewItemClick(e);
- }
- return true;
+ OnClickListener clickListener;
+
+ @Override
+ public void setOnClickListener(OnClickListener l) {
+ super.setOnClickListener(l);
+ clickListener = l;
+ }
+
+ OnLongClickListener longClickListener;
+
+ @Override
+ public void setOnLongClickListener(OnLongClickListener l) {
+ super.setOnLongClickListener(l);
+ longClickListener = l;
+ }
+
+ private Rect hitSurfaceRect;
+
+ private boolean isTouchOnSurface(MotionEvent ev) {
+ View surfaceView = getSurfaceView();
+ if (surfaceView == null) {
+ return false;
}
+ if (hitSurfaceRect == null) {
+ hitSurfaceRect = new Rect();
+ }
+ surfaceView.getHitRect(hitSurfaceRect);
+ return hitSurfaceRect.contains((int) ev.getX(), (int) ev.getY());
+ }
+ private GestureDetector gestureDetector = new GestureDetector(getContext(), new SwipeDetector());
+
+ class SwipeDetector extends GestureDetector.SimpleOnGestureListener {
@Override
- public void onLongPress(MotionEvent e) {
- performLongClick();
+ public boolean onSingleTapUp(MotionEvent e) {
+ if (mClickToClose && isTouchOnSurface(e)) {
+ close();
+ }
+ return super.onSingleTapUp(e);
}
@Override
public boolean onDoubleTap(MotionEvent e) {
- if(mDoubleClickListener != null){
+ if (mDoubleClickListener != null) {
View target;
- ViewGroup bottom = getBottomView();
- ViewGroup surface = getSurfaceView();
- if(e.getX() > bottom.getLeft() && e.getX() < bottom.getRight()
- && e.getY() > bottom.getTop() && e.getY() < bottom.getBottom()){
+ View bottom = getCurrentBottomView();
+ View surface = getSurfaceView();
+ if (bottom != null && e.getX() > bottom.getLeft() && e.getX() < bottom.getRight()
+ && e.getY() > bottom.getTop() && e.getY() < bottom.getBottom()) {
target = bottom;
- }else{
+ } else {
target = surface;
}
mDoubleClickListener.onDoubleClick(SwipeLayout.this, target == surface);
@@ -982,314 +1222,439 @@ public boolean onDoubleTap(MotionEvent e) {
}
}
- public void setDragEdge(DragEdge dragEdge){
- mDragEdge = dragEdge;
- requestLayout();
- }
-
/**
- * set the drag distance, it will force set the bottom view's width or height via this value.
- * @param max
+ * set the drag distance, it will force set the bottom view's width or
+ * height via this value.
+ *
+ * @param max max distance in dp unit
*/
- public void setDragDistance(int max){
- if(max < 0)
- throw new IllegalArgumentException("Drag distance can not be < 0");
+ public void setDragDistance(int max) {
+ if (max < 0) max = 0;
mDragDistance = dp2px(max);
requestLayout();
}
/**
* There are 2 diffirent show mode.
- * {@link com.daimajia.swipe.SwipeLayout.ShowMode}.PullOut and {@link com.daimajia.swipe.SwipeLayout.ShowMode}.LayDown.
+ * {@link com.daimajia.swipe.SwipeLayout.ShowMode}.PullOut and
+ * {@link com.daimajia.swipe.SwipeLayout.ShowMode}.LayDown.
+ *
* @param mode
*/
- public void setShowMode(ShowMode mode){
+ public void setShowMode(ShowMode mode) {
mShowMode = mode;
requestLayout();
}
- public DragEdge getDragEdge(){
- return mDragEdge;
+ public DragEdge getDragEdge() {
+ return mCurrentDragEdge;
}
- public int getDragDistance(){
+ public int getDragDistance() {
return mDragDistance;
}
- public ShowMode getShowMode(){
+ public ShowMode getShowMode() {
return mShowMode;
}
- public ViewGroup getSurfaceView(){
- return (ViewGroup)getChildAt(1);
+ /**
+ * return null if there is no surface view(no children)
+ */
+ public View getSurfaceView() {
+ if (getChildCount() == 0) return null;
+ return getChildAt(getChildCount() - 1);
+ }
+
+ /**
+ * return null if there is no bottom view
+ */
+ public View getCurrentBottomView() {
+ List bottoms = getBottomViews();
+ if (mCurrentDragEdge.ordinal() < bottoms.size()) {
+ return bottoms.get(mCurrentDragEdge.ordinal());
+ }
+ return null;
}
- public ViewGroup getBottomView(){
- return (ViewGroup)getChildAt(0);
+ /**
+ * @return all bottomViews: left, top, right, bottom (may null if the edge is not set)
+ */
+ public List getBottomViews() {
+ ArrayList bottoms = new ArrayList();
+ for (DragEdge dragEdge : DragEdge.values()) {
+ bottoms.add(mDragEdges.get(dragEdge));
+ }
+ return bottoms;
}
public enum Status {
- Middle , Open, Close
+ Middle,
+ Open,
+ Close
}
/**
* get the open status.
- * @return {@link com.daimajia.swipe.SwipeLayout.Status}
- * Open , Close or Middle.
+ *
+ * @return {@link com.daimajia.swipe.SwipeLayout.Status} Open , Close or
+ * Middle.
*/
- public Status getOpenStatus(){
- int surfaceLeft = getSurfaceView().getLeft();
- int surfaceTop = getSurfaceView().getTop();
- if(surfaceLeft == getPaddingLeft() && surfaceTop == getPaddingTop())
+ public Status getOpenStatus() {
+ View surfaceView = getSurfaceView();
+ if (surfaceView == null) {
return Status.Close;
+ }
+ int surfaceLeft = surfaceView.getLeft();
+ int surfaceTop = surfaceView.getTop();
+ if (surfaceLeft == getPaddingLeft() && surfaceTop == getPaddingTop()) return Status.Close;
- if(surfaceLeft == (getPaddingLeft() - mDragDistance) || surfaceLeft == (getPaddingLeft() + mDragDistance)
+ if (surfaceLeft == (getPaddingLeft() - mDragDistance) || surfaceLeft == (getPaddingLeft() + mDragDistance)
|| surfaceTop == (getPaddingTop() - mDragDistance) || surfaceTop == (getPaddingTop() + mDragDistance))
return Status.Open;
return Status.Middle;
}
+
/**
* Process the surface release event.
- * @param xvel
- * @param yvel
+ *
+ * @param xvel xVelocity
+ * @param yvel yVelocity
+ * @param isCloseBeforeDragged the open state before drag
*/
- private void processSurfaceRelease(float xvel, float yvel){
- if(xvel == 0 && getOpenStatus() == Status.Middle)
- close();
-
- if(mDragEdge == DragEdge.Left || mDragEdge == DragEdge.Right){
- if(xvel > 0){
- if(mDragEdge == DragEdge.Left) open();
+ protected void processHandRelease(float xvel, float yvel, boolean isCloseBeforeDragged) {
+ float minVelocity = mDragHelper.getMinVelocity();
+ View surfaceView = getSurfaceView();
+ DragEdge currentDragEdge = mCurrentDragEdge;
+ if (currentDragEdge == null || surfaceView == null) {
+ return;
+ }
+ float willOpenPercent = (isCloseBeforeDragged ? mWillOpenPercentAfterClose : mWillOpenPercentAfterOpen);
+ if (currentDragEdge == DragEdge.Left) {
+ if (xvel > minVelocity) open();
+ else if (xvel < -minVelocity) close();
+ else {
+ float openPercent = 1f * getSurfaceView().getLeft() / mDragDistance;
+ if (openPercent > willOpenPercent) open();
else close();
}
- if(xvel < 0){
- if(mDragEdge == DragEdge.Left) close();
- else open();
- }
- }else{
- if(yvel > 0){
- if(mDragEdge == DragEdge.Top) open();
+ } else if (currentDragEdge == DragEdge.Right) {
+ if (xvel > minVelocity) close();
+ else if (xvel < -minVelocity) open();
+ else {
+ float openPercent = 1f * (-getSurfaceView().getLeft()) / mDragDistance;
+ if (openPercent > willOpenPercent) open();
else close();
}
- if(yvel < 0){
- if(mDragEdge == DragEdge.Top) close();
- else open();
- }
- }
- }
-
- /**
- * process bottom (PullOut mode) hand release event.
- * @param xvel
- * @param yvel
- */
- private void processBottomPullOutRelease(float xvel, float yvel){
-
- if(xvel == 0 && getOpenStatus() == Status.Middle)
- close();
-
- if(mDragEdge == DragEdge.Left || mDragEdge == DragEdge.Right){
- if(xvel > 0){
- if(mDragEdge == DragEdge.Left) open();
+ } else if (currentDragEdge == DragEdge.Top) {
+ if (yvel > minVelocity) open();
+ else if (yvel < -minVelocity) close();
+ else {
+ float openPercent = 1f * getSurfaceView().getTop() / mDragDistance;
+ if (openPercent > willOpenPercent) open();
else close();
}
- if(xvel < 0){
- if(mDragEdge == DragEdge.Left) close();
- else open();
- }
- }else{
- if(yvel > 0) {
- if (mDragEdge == DragEdge.Top) open();
+ } else if (currentDragEdge == DragEdge.Bottom) {
+ if (yvel > minVelocity) close();
+ else if (yvel < -minVelocity) open();
+ else {
+ float openPercent = 1f * (-getSurfaceView().getTop()) / mDragDistance;
+ if (openPercent > willOpenPercent) open();
else close();
}
-
- if(yvel < 0){
- if(mDragEdge == DragEdge.Top) close();
- else open();
- }
}
}
- /**
- * process bottom (LayDown mode) hand release event.
- * @param xvel
- * @param yvel
- */
- private void processBottomLayDownMode(float xvel, float yvel){
-
- if(xvel == 0 && getOpenStatus() == Status.Middle)
- close();
-
- int l = getPaddingLeft(), t = getPaddingTop();
-
- if(xvel < 0 && mDragEdge == DragEdge.Right) l -= mDragDistance;
- if(xvel > 0 && mDragEdge == DragEdge.Left) l += mDragDistance;
-
- if(yvel > 0 && mDragEdge == DragEdge.Top) t += mDragDistance;
- if(yvel < 0 && mDragEdge == DragEdge.Bottom) t -= mDragDistance;
-
- mDragHelper.smoothSlideViewTo(getSurfaceView(), l, t);
- invalidate();
- }
-
/**
* smoothly open surface.
*/
- public void open(){
+ public void open() {
open(true, true);
}
- public void open(boolean smooth){
+ public void open(boolean smooth) {
open(smooth, true);
}
- public void open(boolean smooth, boolean notify){
- ViewGroup surface = getSurfaceView(), bottom = getBottomView();
- int dx,dy;
- Rect rect = computeSurfaceLayoutArea(true);
- if(smooth) {
- mDragHelper.smoothSlideViewTo(getSurfaceView(), rect.left, rect.top);
+ public void open(boolean smooth, boolean notify) {
+ View surface = getSurfaceView(), bottom = getCurrentBottomView();
+ if (surface == null) {
+ return;
}
- else{
+ int dx, dy;
+ Rect rect = computeSurfaceLayoutArea(true);
+ if (smooth) {
+ mDragHelper.smoothSlideViewTo(surface, rect.left, rect.top);
+ } else {
dx = rect.left - surface.getLeft();
dy = rect.top - surface.getTop();
surface.layout(rect.left, rect.top, rect.right, rect.bottom);
- if(getShowMode() == ShowMode.PullOut){
+ if (getShowMode() == ShowMode.PullOut) {
Rect bRect = computeBottomLayoutAreaViaSurface(ShowMode.PullOut, rect);
- bottom.layout(bRect.left, bRect.top, bRect.right, bRect.bottom);
+ if (bottom != null) {
+ bottom.layout(bRect.left, bRect.top, bRect.right, bRect.bottom);
+ }
}
- if(notify) {
+ if (notify) {
dispatchRevealEvent(rect.left, rect.top, rect.right, rect.bottom);
dispatchSwipeEvent(rect.left, rect.top, dx, dy);
- }else{
+ } else {
safeBottomView();
}
}
invalidate();
}
+ public void open(DragEdge edge) {
+ setCurrentDragEdge(edge);
+ open(true, true);
+ }
+
+ public void open(boolean smooth, DragEdge edge) {
+ setCurrentDragEdge(edge);
+ open(smooth, true);
+ }
+
+ public void open(boolean smooth, boolean notify, DragEdge edge) {
+ setCurrentDragEdge(edge);
+ open(smooth, notify);
+ }
+
/**
* smoothly close surface.
*/
- public void close(){
+ public void close() {
close(true, true);
}
- public void close(boolean smooth){
+ public void close(boolean smooth) {
close(smooth, true);
}
/**
* close surface
+ *
* @param smooth smoothly or not.
* @param notify if notify all the listeners.
*/
- public void close(boolean smooth, boolean notify){
- ViewGroup surface = getSurfaceView();
+ public void close(boolean smooth, boolean notify) {
+ View surface = getSurfaceView();
+ if (surface == null) {
+ return;
+ }
int dx, dy;
- if(smooth)
+ if (smooth)
mDragHelper.smoothSlideViewTo(getSurfaceView(), getPaddingLeft(), getPaddingTop());
else {
Rect rect = computeSurfaceLayoutArea(false);
dx = rect.left - surface.getLeft();
dy = rect.top - surface.getTop();
surface.layout(rect.left, rect.top, rect.right, rect.bottom);
- if(notify) {
+ if (notify) {
dispatchRevealEvent(rect.left, rect.top, rect.right, rect.bottom);
dispatchSwipeEvent(rect.left, rect.top, dx, dy);
- }else{
+ } else {
safeBottomView();
}
}
invalidate();
}
- public void toggle(){
+ public void toggle() {
toggle(true);
}
- public void toggle(boolean smooth){
- if(getOpenStatus() == Status.Open)
+ public void toggle(boolean smooth) {
+ if (getOpenStatus() == Status.Open)
close(smooth);
- else if(getOpenStatus() == Status.Close)
- open(smooth);
+ else if (getOpenStatus() == Status.Close) open(smooth);
}
+
/**
* a helper function to compute the Rect area that surface will hold in.
+ *
* @param open open status or close status.
- * @return
*/
- private Rect computeSurfaceLayoutArea(boolean open){
+ private Rect computeSurfaceLayoutArea(boolean open) {
int l = getPaddingLeft(), t = getPaddingTop();
- if(open){
- if(mDragEdge == DragEdge.Left) l = getPaddingLeft() + mDragDistance;
- else if(mDragEdge == DragEdge.Right) l = getPaddingLeft() - mDragDistance;
- else if(mDragEdge == DragEdge.Top) t = getPaddingTop() + mDragDistance;
- else t = getPaddingTop() - mDragDistance;
+ if (open) {
+ if (mCurrentDragEdge == DragEdge.Left)
+ l = getPaddingLeft() + mDragDistance;
+ else if (mCurrentDragEdge == DragEdge.Right)
+ l = getPaddingLeft() - mDragDistance;
+ else if (mCurrentDragEdge == DragEdge.Top)
+ t = getPaddingTop() + mDragDistance;
+ else t = getPaddingTop() - mDragDistance;
}
return new Rect(l, t, l + getMeasuredWidth(), t + getMeasuredHeight());
}
-
- private Rect computeBottomLayoutAreaViaSurface(ShowMode mode, Rect surfaceArea){
+ private Rect computeBottomLayoutAreaViaSurface(ShowMode mode, Rect surfaceArea) {
Rect rect = surfaceArea;
+ View bottomView = getCurrentBottomView();
int bl = rect.left, bt = rect.top, br = rect.right, bb = rect.bottom;
- if(mode == ShowMode.PullOut){
- if (mDragEdge == DragEdge.Left) bl = rect.left - mDragDistance;
- else if (mDragEdge == DragEdge.Right) bl = rect.right;
- else if (mDragEdge == DragEdge.Top) bt = rect.top - mDragDistance;
- else bt = rect.bottom;
-
- if (mDragEdge == DragEdge.Left || mDragEdge == DragEdge.Right) {
+ if (mode == ShowMode.PullOut) {
+ if (mCurrentDragEdge == DragEdge.Left)
+ bl = rect.left - mDragDistance;
+ else if (mCurrentDragEdge == DragEdge.Right)
+ bl = rect.right;
+ else if (mCurrentDragEdge == DragEdge.Top)
+ bt = rect.top - mDragDistance;
+ else bt = rect.bottom;
+
+ if (mCurrentDragEdge == DragEdge.Left || mCurrentDragEdge == DragEdge.Right) {
bb = rect.bottom;
- br = bl + getBottomView().getMeasuredWidth();
+ br = bl + (bottomView == null ? 0 : bottomView.getMeasuredWidth());
} else {
- bb = bt + getBottomView().getMeasuredHeight();
+ bb = bt + (bottomView == null ? 0 : bottomView.getMeasuredHeight());
br = rect.right;
}
- }else if(mode == ShowMode.LayDown){
- if(mDragEdge == DragEdge.Left) br = bl + mDragDistance;
- else if(mDragEdge == DragEdge.Right) bl = br - mDragDistance;
- else if(mDragEdge == DragEdge.Top) bb = bt + mDragDistance;
- else bt = bb - mDragDistance;
+ } else if (mode == ShowMode.LayDown) {
+ if (mCurrentDragEdge == DragEdge.Left)
+ br = bl + mDragDistance;
+ else if (mCurrentDragEdge == DragEdge.Right)
+ bl = br - mDragDistance;
+ else if (mCurrentDragEdge == DragEdge.Top)
+ bb = bt + mDragDistance;
+ else bt = bb - mDragDistance;
}
return new Rect(bl, bt, br, bb);
-
}
- private Rect computeBottomLayDown(DragEdge dragEdge){
+ private Rect computeBottomLayDown(DragEdge dragEdge) {
int bl = getPaddingLeft(), bt = getPaddingTop();
int br, bb;
- if(dragEdge == DragEdge.Right){
+ if (dragEdge == DragEdge.Right) {
bl = getMeasuredWidth() - mDragDistance;
- }else if(dragEdge == DragEdge.Bottom){
+ } else if (dragEdge == DragEdge.Bottom) {
bt = getMeasuredHeight() - mDragDistance;
}
- if(dragEdge == DragEdge.Left || dragEdge == DragEdge.Right){
+ if (dragEdge == DragEdge.Left || dragEdge == DragEdge.Right) {
br = bl + mDragDistance;
bb = bt + getMeasuredHeight();
- }else{
+ } else {
br = bl + getMeasuredWidth();
bb = bt + mDragDistance;
}
return new Rect(bl, bt, br, bb);
}
- public void setOnDoubleClickListener(DoubleClickListener doubleClickListener){
+ public void setOnDoubleClickListener(DoubleClickListener doubleClickListener) {
mDoubleClickListener = doubleClickListener;
}
public interface DoubleClickListener {
- public void onDoubleClick(SwipeLayout layout, boolean surface);
+ void onDoubleClick(SwipeLayout layout, boolean surface);
}
- private int dp2px(float dp){
+ private int dp2px(float dp) {
return (int) (dp * getContext().getResources().getDisplayMetrics().density + 0.5f);
}
+
+
+ /**
+ * Deprecated, use {@link #setDrag(DragEdge, View)}
+ */
+ @Deprecated
+ public void setDragEdge(DragEdge dragEdge) {
+ clearDragEdge();
+ if (getChildCount() >= 2) {
+ mDragEdges.put(dragEdge, getChildAt(getChildCount() - 2));
+ }
+ setCurrentDragEdge(dragEdge);
+ }
+
+ public void onViewRemoved(View child) {
+ for (Map.Entry entry : new HashMap(mDragEdges).entrySet()) {
+ if (entry.getValue() == child) {
+ mDragEdges.remove(entry.getKey());
+ }
+ }
+ }
+
+ public Map getDragEdgeMap() {
+ return mDragEdges;
+ }
+
+ /**
+ * Deprecated, use {@link #getDragEdgeMap()}
+ */
+ @Deprecated
+ public List getDragEdges() {
+ return new ArrayList(mDragEdges.keySet());
+ }
+
+ /**
+ * Deprecated, use {@link #setDrag(DragEdge, View)}
+ */
+ @Deprecated
+ public void setDragEdges(List dragEdges) {
+ clearDragEdge();
+ for (int i = 0, size = Math.min(dragEdges.size(), getChildCount() - 1); i < size; i++) {
+ DragEdge dragEdge = dragEdges.get(i);
+ mDragEdges.put(dragEdge, getChildAt(i));
+ }
+ if (dragEdges.size() == 0 || dragEdges.contains(DefaultDragEdge)) {
+ setCurrentDragEdge(DefaultDragEdge);
+ } else {
+ setCurrentDragEdge(dragEdges.get(0));
+ }
+ }
+
+ /**
+ * Deprecated, use {@link #addDrag(DragEdge, View)}
+ */
+ @Deprecated
+ public void setDragEdges(DragEdge... mDragEdges) {
+ clearDragEdge();
+ setDragEdges(Arrays.asList(mDragEdges));
+ }
+
+ /**
+ * Deprecated, use {@link #addDrag(DragEdge, View)}
+ * When using multiple drag edges it's a good idea to pass the ids of the views that
+ * you're using for the left, right, top bottom views (-1 if you're not using a particular view)
+ */
+ @Deprecated
+ public void setBottomViewIds(int leftId, int rightId, int topId, int bottomId) {
+ addDrag(DragEdge.Left, findViewById(leftId));
+ addDrag(DragEdge.Right, findViewById(rightId));
+ addDrag(DragEdge.Top, findViewById(topId));
+ addDrag(DragEdge.Bottom, findViewById(bottomId));
+ }
+
+ private float getCurrentOffset() {
+ if (mCurrentDragEdge == null) return 0;
+ return mEdgeSwipesOffset[mCurrentDragEdge.ordinal()];
+ }
+
+ private void setCurrentDragEdge(DragEdge dragEdge) {
+ mCurrentDragEdge = dragEdge;
+ updateBottomViews();
+ }
+
+ private void updateBottomViews() {
+ View currentBottomView = getCurrentBottomView();
+ if (currentBottomView != null) {
+ if (mCurrentDragEdge == DragEdge.Left || mCurrentDragEdge == DragEdge.Right) {
+ mDragDistance = currentBottomView.getMeasuredWidth() - dp2px(getCurrentOffset());
+ } else {
+ mDragDistance = currentBottomView.getMeasuredHeight() - dp2px(getCurrentOffset());
+ }
+ }
+
+ if (mShowMode == ShowMode.PullOut) {
+ layoutPullOut();
+ } else if (mShowMode == ShowMode.LayDown) {
+ layoutLayDown();
+ }
+
+ safeBottomView();
+ }
}
diff --git a/library/src/main/java/com/daimajia/swipe/adapters/ArraySwipeAdapter.java b/library/src/main/java/com/daimajia/swipe/adapters/ArraySwipeAdapter.java
index 461b38d3..9475ff59 100644
--- a/library/src/main/java/com/daimajia/swipe/adapters/ArraySwipeAdapter.java
+++ b/library/src/main/java/com/daimajia/swipe/adapters/ArraySwipeAdapter.java
@@ -9,10 +9,11 @@
import com.daimajia.swipe.implments.SwipeItemMangerImpl;
import com.daimajia.swipe.interfaces.SwipeAdapterInterface;
import com.daimajia.swipe.interfaces.SwipeItemMangerInterface;
+import com.daimajia.swipe.util.Attributes;
import java.util.List;
-public abstract class ArraySwipeAdapter extends ArrayAdapter implements SwipeItemMangerInterface,SwipeAdapterInterface {
+public abstract class ArraySwipeAdapter extends ArrayAdapter implements SwipeItemMangerInterface, SwipeAdapterInterface {
private SwipeItemMangerImpl mItemManger = new SwipeItemMangerImpl(this);
{}
@@ -40,15 +41,15 @@ public ArraySwipeAdapter(Context context, int resource, int textViewResourceId,
super(context, resource, textViewResourceId, objects);
}
+ @Override
+ public void notifyDatasetChanged() {
+ super.notifyDataSetChanged();
+ }
+
@Override
public View getView(int position, View convertView, ViewGroup parent) {
- boolean convertViewIsNull = convertView == null;
View v = super.getView(position, convertView, parent);
- if(convertViewIsNull){
- mItemManger.initialize(v, position);
- }else{
- mItemManger.updateConvertView(v, position);
- }
+ mItemManger.bind(v, position);
return v;
}
@@ -67,6 +68,11 @@ public void closeAllExcept(SwipeLayout layout) {
mItemManger.closeAllExcept(layout);
}
+ @Override
+ public void closeAllItems() {
+ mItemManger.closeAllItems();
+ }
+
@Override
public List getOpenItems() {
return mItemManger.getOpenItems();
@@ -88,12 +94,12 @@ public boolean isOpen(int position) {
}
@Override
- public SwipeItemMangerImpl.Mode getMode() {
+ public Attributes.Mode getMode() {
return mItemManger.getMode();
}
@Override
- public void setMode(SwipeItemMangerImpl.Mode mode) {
+ public void setMode(Attributes.Mode mode) {
mItemManger.setMode(mode);
}
}
diff --git a/library/src/main/java/com/daimajia/swipe/adapters/BaseSwipeAdapter.java b/library/src/main/java/com/daimajia/swipe/adapters/BaseSwipeAdapter.java
index f78d414a..bf72c9a9 100644
--- a/library/src/main/java/com/daimajia/swipe/adapters/BaseSwipeAdapter.java
+++ b/library/src/main/java/com/daimajia/swipe/adapters/BaseSwipeAdapter.java
@@ -5,9 +5,10 @@
import android.widget.BaseAdapter;
import com.daimajia.swipe.SwipeLayout;
-import com.daimajia.swipe.interfaces.SwipeAdapterInterface;
import com.daimajia.swipe.implments.SwipeItemMangerImpl;
+import com.daimajia.swipe.interfaces.SwipeAdapterInterface;
import com.daimajia.swipe.interfaces.SwipeItemMangerInterface;
+import com.daimajia.swipe.util.Attributes;
import java.util.List;
@@ -40,16 +41,19 @@ public abstract class BaseSwipeAdapter extends BaseAdapter implements SwipeItemM
*/
public abstract void fillValues(int position, View convertView);
+ @Override
+ public void notifyDatasetChanged() {
+ super.notifyDataSetChanged();
+ }
+
@Override
public final View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if(v == null){
v = generateView(position, parent);
- mItemManger.initialize(v, position);
- }else{
- mItemManger.updateConvertView(v, position);
}
+ mItemManger.bind(v, position);
fillValues(position, v);
return v;
}
@@ -69,6 +73,11 @@ public void closeAllExcept(SwipeLayout layout) {
mItemManger.closeAllExcept(layout);
}
+ @Override
+ public void closeAllItems() {
+ mItemManger.closeAllItems();
+ }
+
@Override
public List getOpenItems() {
return mItemManger.getOpenItems();
@@ -90,12 +99,12 @@ public boolean isOpen(int position) {
}
@Override
- public SwipeItemMangerImpl.Mode getMode() {
+ public Attributes.Mode getMode() {
return mItemManger.getMode();
}
@Override
- public void setMode(SwipeItemMangerImpl.Mode mode) {
+ public void setMode(Attributes.Mode mode) {
mItemManger.setMode(mode);
}
}
diff --git a/library/src/main/java/com/daimajia/swipe/adapters/CursorSwipeAdapter.java b/library/src/main/java/com/daimajia/swipe/adapters/CursorSwipeAdapter.java
index fd55eac6..3e6a62c7 100644
--- a/library/src/main/java/com/daimajia/swipe/adapters/CursorSwipeAdapter.java
+++ b/library/src/main/java/com/daimajia/swipe/adapters/CursorSwipeAdapter.java
@@ -7,9 +7,10 @@
import android.view.ViewGroup;
import com.daimajia.swipe.SwipeLayout;
-import com.daimajia.swipe.interfaces.SwipeAdapterInterface;
import com.daimajia.swipe.implments.SwipeItemMangerImpl;
+import com.daimajia.swipe.interfaces.SwipeAdapterInterface;
import com.daimajia.swipe.interfaces.SwipeItemMangerInterface;
+import com.daimajia.swipe.util.Attributes;
import java.util.List;
@@ -27,13 +28,8 @@ protected CursorSwipeAdapter(Context context, Cursor c, int flags) {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
- boolean convertViewIsNull = convertView == null;
View v = super.getView(position, convertView, parent);
- if(convertViewIsNull){
- mItemManger.initialize(v, position);
- }else{
- mItemManger.updateConvertView(v, position);
- }
+ mItemManger.bind(v, position);
return v;
}
@@ -52,6 +48,11 @@ public void closeAllExcept(SwipeLayout layout) {
mItemManger.closeAllExcept(layout);
}
+ @Override
+ public void closeAllItems() {
+ mItemManger.closeAllItems();
+ }
+
@Override
public List getOpenItems() {
return mItemManger.getOpenItems();
@@ -73,12 +74,12 @@ public boolean isOpen(int position) {
}
@Override
- public SwipeItemMangerImpl.Mode getMode() {
+ public Attributes.Mode getMode() {
return mItemManger.getMode();
}
@Override
- public void setMode(SwipeItemMangerImpl.Mode mode) {
+ public void setMode(Attributes.Mode mode) {
mItemManger.setMode(mode);
}
}
diff --git a/library/src/main/java/com/daimajia/swipe/adapters/RecyclerSwipeAdapter.java b/library/src/main/java/com/daimajia/swipe/adapters/RecyclerSwipeAdapter.java
new file mode 100644
index 00000000..f6e9aed3
--- /dev/null
+++ b/library/src/main/java/com/daimajia/swipe/adapters/RecyclerSwipeAdapter.java
@@ -0,0 +1,78 @@
+package com.daimajia.swipe.adapters;
+
+import android.support.v7.widget.RecyclerView;
+import android.view.ViewGroup;
+
+import com.daimajia.swipe.SwipeLayout;
+import com.daimajia.swipe.implments.SwipeItemMangerImpl;
+import com.daimajia.swipe.interfaces.SwipeAdapterInterface;
+import com.daimajia.swipe.interfaces.SwipeItemMangerInterface;
+import com.daimajia.swipe.util.Attributes;
+
+import java.util.List;
+
+public abstract class RecyclerSwipeAdapter extends RecyclerView.Adapter implements SwipeItemMangerInterface, SwipeAdapterInterface {
+
+ public SwipeItemMangerImpl mItemManger = new SwipeItemMangerImpl(this);
+
+ @Override
+ public abstract VH onCreateViewHolder(ViewGroup parent, int viewType);
+
+ @Override
+ public abstract void onBindViewHolder(VH viewHolder, final int position);
+
+ @Override
+ public void notifyDatasetChanged() {
+ super.notifyDataSetChanged();
+ }
+
+ @Override
+ public void openItem(int position) {
+ mItemManger.openItem(position);
+ }
+
+ @Override
+ public void closeItem(int position) {
+ mItemManger.closeItem(position);
+ }
+
+ @Override
+ public void closeAllExcept(SwipeLayout layout) {
+ mItemManger.closeAllExcept(layout);
+ }
+
+ @Override
+ public void closeAllItems() {
+ mItemManger.closeAllItems();
+ }
+
+ @Override
+ public List getOpenItems() {
+ return mItemManger.getOpenItems();
+ }
+
+ @Override
+ public List getOpenLayouts() {
+ return mItemManger.getOpenLayouts();
+ }
+
+ @Override
+ public void removeShownLayouts(SwipeLayout layout) {
+ mItemManger.removeShownLayouts(layout);
+ }
+
+ @Override
+ public boolean isOpen(int position) {
+ return mItemManger.isOpen(position);
+ }
+
+ @Override
+ public Attributes.Mode getMode() {
+ return mItemManger.getMode();
+ }
+
+ @Override
+ public void setMode(Attributes.Mode mode) {
+ mItemManger.setMode(mode);
+ }
+}
diff --git a/library/src/main/java/com/daimajia/swipe/adapters/SimpleCursorSwipeAdapter.java b/library/src/main/java/com/daimajia/swipe/adapters/SimpleCursorSwipeAdapter.java
index 6a0883a4..19b04ad2 100644
--- a/library/src/main/java/com/daimajia/swipe/adapters/SimpleCursorSwipeAdapter.java
+++ b/library/src/main/java/com/daimajia/swipe/adapters/SimpleCursorSwipeAdapter.java
@@ -10,6 +10,7 @@
import com.daimajia.swipe.implments.SwipeItemMangerImpl;
import com.daimajia.swipe.interfaces.SwipeAdapterInterface;
import com.daimajia.swipe.interfaces.SwipeItemMangerInterface;
+import com.daimajia.swipe.util.Attributes;
import java.util.List;
@@ -27,13 +28,8 @@ protected SimpleCursorSwipeAdapter(Context context, int layout, Cursor c, String
@Override
public View getView(int position, View convertView, ViewGroup parent) {
- boolean convertViewIsNull = convertView == null;
View v = super.getView(position, convertView, parent);
- if(convertViewIsNull){
- mItemManger.initialize(v, position);
- }else{
- mItemManger.updateConvertView(v, position);
- }
+ mItemManger.bind(v, position);
return v;
}
@@ -73,12 +69,12 @@ public boolean isOpen(int position) {
}
@Override
- public SwipeItemMangerImpl.Mode getMode() {
+ public Attributes.Mode getMode() {
return mItemManger.getMode();
}
@Override
- public void setMode(SwipeItemMangerImpl.Mode mode) {
+ public void setMode(Attributes.Mode mode) {
mItemManger.setMode(mode);
}
}
diff --git a/library/src/main/java/com/daimajia/swipe/implments/SwipeItemMangerImpl.java b/library/src/main/java/com/daimajia/swipe/implments/SwipeItemMangerImpl.java
index fdb20f8e..989849c1 100644
--- a/library/src/main/java/com/daimajia/swipe/implments/SwipeItemMangerImpl.java
+++ b/library/src/main/java/com/daimajia/swipe/implments/SwipeItemMangerImpl.java
@@ -1,15 +1,15 @@
package com.daimajia.swipe.implments;
import android.view.View;
-import android.widget.BaseAdapter;
import com.daimajia.swipe.SimpleSwipeListener;
import com.daimajia.swipe.SwipeLayout;
import com.daimajia.swipe.interfaces.SwipeAdapterInterface;
import com.daimajia.swipe.interfaces.SwipeItemMangerInterface;
+import com.daimajia.swipe.util.Attributes;
import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -19,7 +19,7 @@
*/
public class SwipeItemMangerImpl implements SwipeItemMangerInterface {
- private Mode mode = Mode.Single;
+ private Attributes.Mode mode = Attributes.Mode.Single;
public final int INVALID_POSITION = -1;
protected int mOpenPosition = INVALID_POSITION;
@@ -27,96 +27,89 @@ public class SwipeItemMangerImpl implements SwipeItemMangerInterface {
protected Set mOpenPositions = new HashSet();
protected Set mShownLayouts = new HashSet();
- protected BaseAdapter mAdapter;
+ protected SwipeAdapterInterface swipeAdapterInterface;
- public SwipeItemMangerImpl(BaseAdapter adapter) {
- if(adapter == null)
- throw new IllegalArgumentException("Adapter can not be null");
+ public SwipeItemMangerImpl(SwipeAdapterInterface swipeAdapterInterface) {
+ if (swipeAdapterInterface == null)
+ throw new IllegalArgumentException("SwipeAdapterInterface can not be null");
- if(!(adapter instanceof SwipeItemMangerInterface))
- throw new IllegalArgumentException("adapter should implement the SwipeAdapterInterface");
-
- this.mAdapter = adapter;
+ this.swipeAdapterInterface = swipeAdapterInterface;
}
- public enum Mode{
- Single, Multiple
- };
-
- public Mode getMode(){
+ public Attributes.Mode getMode() {
return mode;
}
- public void setMode(Mode mode){
+ public void setMode(Attributes.Mode mode) {
this.mode = mode;
mOpenPositions.clear();
mShownLayouts.clear();
mOpenPosition = INVALID_POSITION;
}
- public void initialize(View target, int position) {
- int resId = getSwipeLayoutId(position);
-
- OnLayoutListener onLayoutListener = new OnLayoutListener(position);
- SwipeLayout swipeLayout = (SwipeLayout)target.findViewById(resId);
- if(swipeLayout == null)
- throw new IllegalStateException("can not find SwipeLayout in target view");
-
- SwipeMemory swipeMemory = new SwipeMemory(position);
- swipeLayout.addSwipeListener(swipeMemory);
- swipeLayout.addOnLayoutListener(onLayoutListener);
- swipeLayout.setTag(resId, new ValueBox(position, swipeMemory, onLayoutListener));
-
- mShownLayouts.add(swipeLayout);
- }
-
- public void updateConvertView(View target, int position) {
- int resId = getSwipeLayoutId(position);
-
- SwipeLayout swipeLayout = (SwipeLayout)target.findViewById(resId);
- if(swipeLayout == null)
+ public void bind(View view, int position) {
+ int resId = swipeAdapterInterface.getSwipeLayoutResourceId(position);
+ SwipeLayout swipeLayout = (SwipeLayout) view.findViewById(resId);
+ if (swipeLayout == null)
throw new IllegalStateException("can not find SwipeLayout in target view");
- ValueBox valueBox = (ValueBox)swipeLayout.getTag(resId);
- valueBox.swipeMemory.setPosition(position);
- valueBox.onLayoutListener.setPosition(position);
- valueBox.position = position;
- }
-
- private int getSwipeLayoutId(int position){
- return ((SwipeAdapterInterface)(mAdapter)).getSwipeLayoutResourceId(position);
+ if (swipeLayout.getTag(resId) == null) {
+ OnLayoutListener onLayoutListener = new OnLayoutListener(position);
+ SwipeMemory swipeMemory = new SwipeMemory(position);
+ swipeLayout.addSwipeListener(swipeMemory);
+ swipeLayout.addOnLayoutListener(onLayoutListener);
+ swipeLayout.setTag(resId, new ValueBox(position, swipeMemory, onLayoutListener));
+ mShownLayouts.add(swipeLayout);
+ } else {
+ ValueBox valueBox = (ValueBox) swipeLayout.getTag(resId);
+ valueBox.swipeMemory.setPosition(position);
+ valueBox.onLayoutListener.setPosition(position);
+ valueBox.position = position;
+ }
}
@Override
public void openItem(int position) {
- if(mode == Mode.Multiple){
- if(!mOpenPositions.contains(position))
+ if (mode == Attributes.Mode.Multiple) {
+ if (!mOpenPositions.contains(position))
mOpenPositions.add(position);
- }else{
+ } else {
mOpenPosition = position;
}
- mAdapter.notifyDataSetChanged();
+ swipeAdapterInterface.notifyDatasetChanged();
}
@Override
public void closeItem(int position) {
- if(mode == Mode.Multiple){
+ if (mode == Attributes.Mode.Multiple) {
mOpenPositions.remove(position);
- }else{
- if(mOpenPosition == position)
+ } else {
+ if (mOpenPosition == position)
mOpenPosition = INVALID_POSITION;
}
- mAdapter.notifyDataSetChanged();
+ swipeAdapterInterface.notifyDatasetChanged();
}
@Override
public void closeAllExcept(SwipeLayout layout) {
- for(SwipeLayout s : mShownLayouts){
- if(s != layout)
+ for (SwipeLayout s : mShownLayouts) {
+ if (s != layout)
s.close();
}
}
+ @Override
+ public void closeAllItems() {
+ if (mode == Attributes.Mode.Multiple) {
+ mOpenPositions.clear();
+ } else {
+ mOpenPosition = INVALID_POSITION;
+ }
+ for (SwipeLayout s : mShownLayouts) {
+ s.close();
+ }
+ }
+
@Override
public void removeShownLayouts(SwipeLayout layout) {
mShownLayouts.remove(layout);
@@ -124,10 +117,10 @@ public void removeShownLayouts(SwipeLayout layout) {
@Override
public List getOpenItems() {
- if(mode == Mode.Multiple){
+ if (mode == Attributes.Mode.Multiple) {
return new ArrayList(mOpenPositions);
- }else{
- return Arrays.asList(mOpenPosition);
+ } else {
+ return Collections.singletonList(mOpenPosition);
}
}
@@ -138,9 +131,9 @@ public List getOpenLayouts() {
@Override
public boolean isOpen(int position) {
- if(mode == Mode.Multiple){
+ if (mode == Attributes.Mode.Multiple) {
return mOpenPositions.contains(position);
- }else{
+ } else {
return mOpenPosition == position;
}
}
@@ -157,7 +150,7 @@ class ValueBox {
}
}
- class OnLayoutListener implements SwipeLayout.OnLayout{
+ class OnLayoutListener implements SwipeLayout.OnLayout {
private int position;
@@ -165,15 +158,15 @@ class OnLayoutListener implements SwipeLayout.OnLayout{
this.position = position;
}
- public void setPosition(int position){
+ public void setPosition(int position) {
this.position = position;
}
@Override
public void onLayout(SwipeLayout v) {
- if(isOpen(position)){
+ if (isOpen(position)) {
v.open(false, false);
- }else{
+ } else {
v.close(false, false);
}
}
@@ -190,23 +183,23 @@ class SwipeMemory extends SimpleSwipeListener {
@Override
public void onClose(SwipeLayout layout) {
- if(mode == Mode.Multiple){
+ if (mode == Attributes.Mode.Multiple) {
mOpenPositions.remove(position);
- }else{
+ } else {
mOpenPosition = INVALID_POSITION;
}
}
@Override
public void onStartOpen(SwipeLayout layout) {
- if(mode == Mode.Single) {
+ if (mode == Attributes.Mode.Single) {
closeAllExcept(layout);
}
}
@Override
public void onOpen(SwipeLayout layout) {
- if (mode == Mode.Multiple)
+ if (mode == Attributes.Mode.Multiple)
mOpenPositions.add(position);
else {
closeAllExcept(layout);
@@ -214,7 +207,7 @@ public void onOpen(SwipeLayout layout) {
}
}
- public void setPosition(int position){
+ public void setPosition(int position) {
this.position = position;
}
}
diff --git a/library/src/main/java/com/daimajia/swipe/interfaces/SwipeAdapterInterface.java b/library/src/main/java/com/daimajia/swipe/interfaces/SwipeAdapterInterface.java
index 4b47fa20..9d0a7701 100644
--- a/library/src/main/java/com/daimajia/swipe/interfaces/SwipeAdapterInterface.java
+++ b/library/src/main/java/com/daimajia/swipe/interfaces/SwipeAdapterInterface.java
@@ -1,5 +1,9 @@
package com.daimajia.swipe.interfaces;
public interface SwipeAdapterInterface {
- public int getSwipeLayoutResourceId(int position);
+
+ int getSwipeLayoutResourceId(int position);
+
+ void notifyDatasetChanged();
+
}
diff --git a/library/src/main/java/com/daimajia/swipe/interfaces/SwipeItemMangerInterface.java b/library/src/main/java/com/daimajia/swipe/interfaces/SwipeItemMangerInterface.java
index 1a5e4098..b9dd337b 100644
--- a/library/src/main/java/com/daimajia/swipe/interfaces/SwipeItemMangerInterface.java
+++ b/library/src/main/java/com/daimajia/swipe/interfaces/SwipeItemMangerInterface.java
@@ -1,27 +1,29 @@
package com.daimajia.swipe.interfaces;
import com.daimajia.swipe.SwipeLayout;
-import com.daimajia.swipe.implments.SwipeItemMangerImpl;
+import com.daimajia.swipe.util.Attributes;
import java.util.List;
public interface SwipeItemMangerInterface {
- public void openItem(int position);
+ void openItem(int position);
- public void closeItem(int position);
+ void closeItem(int position);
- public void closeAllExcept(SwipeLayout layout);
+ void closeAllExcept(SwipeLayout layout);
+
+ void closeAllItems();
- public List getOpenItems();
+ List getOpenItems();
- public List getOpenLayouts();
+ List getOpenLayouts();
- public void removeShownLayouts(SwipeLayout layout);
+ void removeShownLayouts(SwipeLayout layout);
- public boolean isOpen(int position);
+ boolean isOpen(int position);
- public SwipeItemMangerImpl.Mode getMode();
+ Attributes.Mode getMode();
- public void setMode(SwipeItemMangerImpl.Mode mode);
+ void setMode(Attributes.Mode mode);
}
diff --git a/library/src/main/java/com/daimajia/swipe/util/Attributes.java b/library/src/main/java/com/daimajia/swipe/util/Attributes.java
new file mode 100644
index 00000000..697c64ad
--- /dev/null
+++ b/library/src/main/java/com/daimajia/swipe/util/Attributes.java
@@ -0,0 +1,9 @@
+package com.daimajia.swipe.util;
+
+
+public class Attributes {
+
+ public enum Mode {
+ Single, Multiple
+ }
+}
diff --git a/library/src/main/res/values/attrs.xml b/library/src/main/res/values/attrs.xml
index c574ff77..a671fc5f 100644
--- a/library/src/main/res/values/attrs.xml
+++ b/library/src/main/res/values/attrs.xml
@@ -1,15 +1,20 @@
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
+
+
+
\ No newline at end of file