├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── build.gradle
├── demo
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── daimajia
│ │ └── swipedemo
│ │ ├── GridViewExample.java
│ │ ├── ListViewExample.java
│ │ ├── MyActivity.java
│ │ ├── NestedExample.java
│ │ ├── RecyclerViewExample.java
│ │ └── adapter
│ │ ├── ArraySwipeAdapterSample.java
│ │ ├── GridViewAdapter.java
│ │ ├── ListViewAdapter.java
│ │ ├── RecyclerViewAdapter.java
│ │ └── util
│ │ ├── DividerItemDecoration.java
│ │ └── RecyclerItemClickListener.java
│ └── res
│ ├── drawable-hdpi
│ ├── bird.png
│ ├── hand.png
│ ├── ic_launcher.png
│ ├── magnifier.png
│ ├── star.png
│ └── trash.png
│ ├── drawable-mdpi
│ └── ic_launcher.png
│ ├── drawable-xhdpi
│ └── ic_launcher.png
│ ├── drawable-xxhdpi
│ └── ic_launcher.png
│ ├── drawable
│ ├── dark_gray.xml
│ ├── divider.xml
│ ├── item_selector.xml
│ ├── red.xml
│ └── white.xml
│ ├── layout
│ ├── complicate_layout.xml
│ ├── grid_item.xml
│ ├── gridview.xml
│ ├── listview.xml
│ ├── listview_item.xml
│ ├── main.xml
│ ├── recyclerview.xml
│ ├── recyclerview_item.xml
│ ├── sampe_nested_edittext.xml
│ ├── sampe_nested_scrollview.xml
│ ├── sampe_nested_seekbar.xml
│ ├── sample1.xml
│ ├── sample2.xml
│ ├── sample3.xml
│ ├── sample_nested_parent.xml
│ └── sample_together.xml
│ ├── menu
│ └── my.xml
│ ├── values-w820dp
│ └── dimens.xml
│ └── values
│ ├── colors.xml
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── library
├── .gitignore
├── build.gradle
├── gradle-mvn-push.gradle
├── gradle.properties
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── daimajia
│ │ └── swipe
│ │ ├── SimpleSwipeListener.java
│ │ ├── SwipeLayout.java
│ │ ├── adapters
│ │ ├── ArraySwipeAdapter.java
│ │ ├── BaseSwipeAdapter.java
│ │ ├── CursorSwipeAdapter.java
│ │ ├── RecyclerSwipeAdapter.java
│ │ └── SimpleCursorSwipeAdapter.java
│ │ ├── implments
│ │ └── SwipeItemMangerImpl.java
│ │ ├── interfaces
│ │ ├── SwipeAdapterInterface.java
│ │ └── SwipeItemMangerInterface.java
│ │ └── util
│ │ └── Attributes.java
│ └── res
│ └── values
│ └── attrs.xml
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | /local.properties
3 | /.idea/workspace.xml
4 | .DS_Store
5 | /build
6 | # built application files
7 | *.apk
8 | *.ap_
9 |
10 | # files for the dex VM
11 | *.dex
12 |
13 | # Java class files
14 | *.class
15 | .DS_Store
16 |
17 | # generated files
18 | bin/
19 | gen/
20 | Wiki/
21 |
22 | # Local configuration file (sdk path, etc)
23 | local.properties
24 |
25 | # Eclipse project files
26 | .classpath
27 | .project
28 | .settings/
29 |
30 | # Proguard folder generated by Eclipse
31 | proguard/
32 |
33 | #Android Studio
34 | build/
35 |
36 | # Intellij project files
37 | *.iml
38 | *.ipr
39 | *.iws
40 | .idea/
41 |
42 | #gradle
43 | .gradle/
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: android
2 | android:
3 | components:
4 | - tools
5 | - platform-tools
6 | - build-tools-25.0.2
7 | - android-25
8 | - extra-android-support
9 | - extra
10 | - extra-android-m2repository
11 | script:
12 | - ./gradlew assembleDebug
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 代码家
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Android Swipe Layout [](https://travis-ci.org/daimajia/AndroidSwipeLayout)
2 |
3 | [](https://gitter.im/daimajia/AndroidSwipeLayout?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
4 |
5 | [](https://insight.io/github.com/daimajia/AndroidSwipeLayout)
6 |
7 | This is the brother of [AndroidViewHover](https://github.com/daimajia/AndroidViewHover).
8 |
9 | One year ago, I started to make an app named [EverMemo](https://play.google.com/store/apps/details?id=com.zhan_dui.evermemo) with my good friends. The designer gave me a design picture, the design like this:
10 |
11 | 
12 |
13 | I found it was pretty hard to achieve this effect, cause you had to be very familiar with the Android Touch System. It was beyond my ability that moment, and I also noticed that there was no such a concept library...
14 |
15 | Time passed, finally...as you see right now.
16 |
17 | ## Demo
18 |
19 | 
20 |
21 | [Download Demo](https://github.com/daimajia/AndroidSwipeLayout/releases/download/v1.1.8/AndroidSwipeLayout-v1.1.8.apk)
22 |
23 | 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.
24 |
25 | But it only works in `ListView`, and it has too many issues that they never care. What a pity!
26 |
27 | When I start to make this library, I set some goals:
28 |
29 | - Can be easily integrated in anywhere, ListView, GridView, ViewGroup etc.
30 | - Can receive `onOpen`,`onClose`,`onUpdate` callbacks.
31 | - Can notifiy the hidden children how much they have shown.
32 | - Can be nested each other.
33 | - Can handle complicate situation, just like [this](https://camo.githubusercontent.com/d145d9a9508b3d204b70882c05bc3d9bd433883c/687474703a2f2f7777312e73696e61696d672e636e2f6c617267652f3631306463303334677731656b686f6a7379326172673230386530366e6774312e676966).
34 |
35 |
36 | ## Usage
37 |
38 | ### Step 1
39 | #### Gradle
40 |
41 | ```groovy
42 | dependencies {
43 | compile 'com.android.support:recyclerview-v7:21.0.0'
44 | compile 'com.android.support:support-v4:20.+'
45 | compile "com.daimajia.swipelayout:library:1.2.0@aar"
46 | }
47 | ```
48 |
49 | #### Maven
50 |
51 | ```xml
52 |
53 | com.google.android
54 | support-v4
55 | r6
56 |
57 |
58 | com.google.android
59 | recyclerview-v7
60 | 21.0.0
61 |
62 |
63 | com.daimajia.swipelayout
64 | library
65 | 1.2.0
66 | apklib
67 |
68 | ```
69 |
70 | #### Eclipse
71 |
72 | [AndroidSwipeLayout-v1.1.8.jar](https://github.com/daimajia/AndroidSwipeLayout/releases/download/v1.1.8/AndroidSwipeLayout-v1.1.8.jar)
73 |
74 | ### Step 2
75 |
76 | **Make sure to use the internal adapter instead of your own!**
77 |
78 | [Wiki Usage](https://github.com/daimajia/AndroidSwipeLayout/wiki/usage)
79 |
80 | ## Wiki
81 |
82 | [Go to Wiki](https://github.com/daimajia/AndroidSwipeLayout/wiki)
83 |
84 | ## About me
85 |
86 | A student in mainland China.
87 |
88 | Welcome to [offer me an internship](mailto:daimajia@gmail.com). If you have any new idea about this project, feel free to [contact me](mailto:daimajia@gmail.com). :smiley:
89 |
90 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | maven {
7 | url "https://jitpack.io"
8 | }
9 | }
10 | dependencies {
11 | classpath 'com.android.tools.build:gradle:2.3.0'
12 | classpath 'com.github.dcendents:android-maven-plugin:1.2'
13 |
14 | // NOTE: Do not place your application dependencies here; they belong
15 | // in the individual module build.gradle files
16 | }
17 | }
18 |
19 | allprojects {
20 | repositories {
21 | jcenter()
22 | maven {
23 | url "https://jitpack.io"
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/demo/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/demo/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | repositories {
4 | jcenter()
5 | }
6 |
7 | android {
8 | compileSdkVersion Integer.parseInt(project.ANDROID_BUILD_SDK_VERSION)
9 | buildToolsVersion project.ANDROID_BUILD_TOOLS_VERSION
10 | defaultConfig {
11 | minSdkVersion Integer.parseInt(project.ANDROID_BUILD_MIN_SDK_VERSION)
12 | targetSdkVersion Integer.parseInt(project.ANDROID_BUILD_TARGET_SDK_VERSION)
13 | versionName project.VERSION_NAME
14 | versionCode Integer.parseInt(project.VERSION_CODE)
15 | }
16 | buildTypes {
17 | release {
18 | minifyEnabled false
19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
20 | }
21 | }
22 | lintOptions {
23 | abortOnError false
24 | }
25 | }
26 |
27 | dependencies {
28 | compile project(":library")
29 | compile 'com.android.support:recyclerview-v7:25.1.1'
30 | compile 'com.daimajia.easing:library:1.0.0@aar'
31 | compile 'com.daimajia.androidanimations:library:1.1.2@aar'
32 | compile 'com.nineoldandroids:library:2.4.0'
33 | // This dude gave a shoutout to you (daimajia) on his github page:
34 | compile 'jp.wasabeef:recyclerview-animators:1.0.3@aar'
35 | }
36 |
--------------------------------------------------------------------------------
/demo/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Applications/Android Studio.app/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/demo/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
13 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/daimajia/swipedemo/GridViewExample.java:
--------------------------------------------------------------------------------
1 | package com.daimajia.swipedemo;
2 |
3 | import android.app.Activity;
4 | import android.os.Bundle;
5 | import android.util.Log;
6 | import android.view.View;
7 | import android.widget.AdapterView;
8 | import android.widget.GridView;
9 |
10 | import com.daimajia.swipe.util.Attributes;
11 | import com.daimajia.swipedemo.adapter.GridViewAdapter;
12 |
13 | public class GridViewExample extends Activity{
14 |
15 | @Override
16 | protected void onCreate(Bundle savedInstanceState) {
17 | super.onCreate(savedInstanceState);
18 | setContentView(R.layout.gridview);
19 | final GridView gridView = (GridView)findViewById(R.id.gridview);
20 | final GridViewAdapter adapter = new GridViewAdapter(this);
21 | adapter.setMode(Attributes.Mode.Multiple);
22 | gridView.setAdapter(adapter);
23 | gridView.setSelected(false);
24 | gridView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
25 | @Override
26 | public boolean onItemLongClick(AdapterView> parent, View view, int position, long id) {
27 | Log.e("onItemLongClick","onItemLongClick:" + position);
28 | return false;
29 | }
30 | });
31 | gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
32 | @Override
33 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
34 | Log.e("onItemClick","onItemClick:" + position);
35 | }
36 | });
37 |
38 |
39 | gridView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
40 | @Override
41 | public void onItemSelected(AdapterView> parent, View view, int position, long id) {
42 | Log.e("onItemSelected","onItemSelected:" + position);
43 | }
44 |
45 | @Override
46 | public void onNothingSelected(AdapterView> parent) {
47 |
48 | }
49 | });
50 |
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/daimajia/swipedemo/ListViewExample.java:
--------------------------------------------------------------------------------
1 | package com.daimajia.swipedemo;
2 |
3 | import android.app.ActionBar;
4 | import android.app.Activity;
5 | import android.content.Context;
6 | import android.content.Intent;
7 | import android.os.Build;
8 | import android.os.Bundle;
9 | import android.util.Log;
10 | import android.view.Menu;
11 | import android.view.MenuItem;
12 | import android.view.MotionEvent;
13 | import android.view.View;
14 | import android.widget.AbsListView;
15 | import android.widget.AdapterView;
16 | import android.widget.ListView;
17 | import android.widget.Toast;
18 |
19 | import com.daimajia.swipe.SwipeLayout;
20 | import com.daimajia.swipe.util.Attributes;
21 | import com.daimajia.swipedemo.adapter.ListViewAdapter;
22 |
23 | public class ListViewExample extends Activity {
24 |
25 | private ListView mListView;
26 | private ListViewAdapter mAdapter;
27 | private Context mContext = this;
28 |
29 | @Override
30 | protected void onCreate(Bundle savedInstanceState) {
31 | super.onCreate(savedInstanceState);
32 | setContentView(R.layout.listview);
33 | mListView = (ListView) findViewById(R.id.listview);
34 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
35 | ActionBar actionBar = getActionBar();
36 | if (actionBar != null) {
37 | actionBar.setTitle("ListView");
38 | }
39 | }
40 |
41 | /**
42 | * The following comment is the sample usage of ArraySwipeAdapter.
43 | */
44 | // String[] adapterData = new String[]{"Activity", "Service", "Content Provider", "Intent", "BroadcastReceiver", "ADT", "Sqlite3", "HttpClient",
45 | // "DDMS", "Android Studio", "Fragment", "Loader", "Activity", "Service", "Content Provider", "Intent",
46 | // "BroadcastReceiver", "ADT", "Sqlite3", "HttpClient", "Activity", "Service", "Content Provider", "Intent",
47 | // "BroadcastReceiver", "ADT", "Sqlite3", "HttpClient"};
48 | // mListView.setAdapter(new ArraySwipeAdapterSample(this, R.layout.listview_item, R.id.position, adapterData));
49 |
50 | mAdapter = new ListViewAdapter(this);
51 | mListView.setAdapter(mAdapter);
52 | mAdapter.setMode(Attributes.Mode.Single);
53 | mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
54 | @Override
55 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
56 | ((SwipeLayout)(mListView.getChildAt(position - mListView.getFirstVisiblePosition()))).open(true);
57 | }
58 | });
59 | mListView.setOnTouchListener(new View.OnTouchListener() {
60 | @Override
61 | public boolean onTouch(View v, MotionEvent event) {
62 | Log.e("ListView", "OnTouch");
63 | return false;
64 | }
65 | });
66 | mListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
67 | @Override
68 | public boolean onItemLongClick(AdapterView> parent, View view, int position, long id) {
69 | Toast.makeText(mContext, "OnItemLongClickListener", Toast.LENGTH_SHORT).show();
70 | return true;
71 | }
72 | });
73 | mListView.setOnScrollListener(new AbsListView.OnScrollListener() {
74 | @Override
75 | public void onScrollStateChanged(AbsListView view, int scrollState) {
76 | Log.e("ListView", "onScrollStateChanged");
77 | }
78 |
79 | @Override
80 | public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
81 |
82 | }
83 | });
84 |
85 | mListView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
86 | @Override
87 | public void onItemSelected(AdapterView> parent, View view, int position, long id) {
88 | Log.e("ListView", "onItemSelected:" + position);
89 | }
90 |
91 | @Override
92 | public void onNothingSelected(AdapterView> parent) {
93 | Log.e("ListView", "onNothingSelected:");
94 | }
95 | });
96 |
97 | }
98 |
99 |
100 | @Override
101 | public boolean onCreateOptionsMenu(Menu menu) {
102 | // Inflate the menu; this adds items to the action bar if it is present.
103 | getMenuInflater().inflate(R.menu.my, menu);
104 | return true;
105 | }
106 |
107 | @Override
108 | public boolean onOptionsItemSelected(MenuItem item) {
109 | // Handle action bar item clicks here. The action bar will
110 | // automatically handle clicks on the Home/Up button, so long
111 | // as you specify a parent activity in AndroidManifest.xml.
112 | int id = item.getItemId();
113 | if (id == R.id.action_listview) {
114 | startActivity(new Intent(this, ListViewExample.class));
115 | finish();
116 | return true;
117 | } else if (id == R.id.action_gridview) {
118 | startActivity(new Intent(this, GridViewExample.class));
119 | finish();
120 | return true;
121 | } else if (id == R.id.action_recycler) {
122 | startActivity(new Intent(this, RecyclerViewExample.class));
123 | finish();
124 | return true;
125 | }
126 | return super.onOptionsItemSelected(item);
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/daimajia/swipedemo/MyActivity.java:
--------------------------------------------------------------------------------
1 | package com.daimajia.swipedemo;
2 |
3 | import android.app.Activity;
4 | import android.content.Intent;
5 | import android.graphics.Color;
6 | import android.os.Bundle;
7 | import android.util.Log;
8 | import android.view.Menu;
9 | import android.view.MenuItem;
10 | import android.view.View;
11 | import android.widget.Toast;
12 |
13 | import com.daimajia.swipe.SwipeLayout;
14 | import com.nineoldandroids.view.ViewHelper;
15 |
16 | public class MyActivity extends Activity {
17 |
18 | private SwipeLayout sample1, sample2, sample3;
19 |
20 | @Override
21 | protected void onCreate(Bundle savedInstanceState) {
22 | super.onCreate(savedInstanceState);
23 | setContentView(R.layout.main);
24 |
25 | // SwipeLayout swipeLayout = (SwipeLayout)findViewById(R.id.godfather);
26 | // swipeLayout.setDragEdge(SwipeLayout.DragEdge.Bottom); // Set in XML
27 |
28 | //sample1
29 |
30 | sample1 = (SwipeLayout) findViewById(R.id.sample1);
31 | sample1.setShowMode(SwipeLayout.ShowMode.PullOut);
32 | View starBottView = sample1.findViewById(R.id.starbott);
33 | sample1.addDrag(SwipeLayout.DragEdge.Left, sample1.findViewById(R.id.bottom_wrapper));
34 | sample1.addDrag(SwipeLayout.DragEdge.Right, sample1.findViewById(R.id.bottom_wrapper_2));
35 | sample1.addDrag(SwipeLayout.DragEdge.Top, starBottView);
36 | sample1.addDrag(SwipeLayout.DragEdge.Bottom, starBottView);
37 | sample1.addRevealListener(R.id.delete, new SwipeLayout.OnRevealListener() {
38 | @Override
39 | public void onReveal(View child, SwipeLayout.DragEdge edge, float fraction, int distance) {
40 |
41 | }
42 | });
43 |
44 | sample1.getSurfaceView().setOnClickListener(new View.OnClickListener() {
45 | @Override
46 | public void onClick(View v) {
47 | Toast.makeText(MyActivity.this, "Click on surface", Toast.LENGTH_SHORT).show();
48 | Log.d(MyActivity.class.getName(), "click on surface");
49 | }
50 | });
51 | sample1.getSurfaceView().setOnLongClickListener(new View.OnLongClickListener() {
52 | @Override
53 | public boolean onLongClick(View v) {
54 | Toast.makeText(MyActivity.this, "longClick on surface", Toast.LENGTH_SHORT).show();
55 | Log.d(MyActivity.class.getName(), "longClick on surface");
56 | return true;
57 | }
58 | });
59 | sample1.findViewById(R.id.star2).setOnClickListener(new View.OnClickListener() {
60 | @Override
61 | public void onClick(View v) {
62 | Toast.makeText(MyActivity.this, "Star", Toast.LENGTH_SHORT).show();
63 | }
64 | });
65 |
66 | sample1.findViewById(R.id.trash2).setOnClickListener(new View.OnClickListener() {
67 | @Override
68 | public void onClick(View v) {
69 | Toast.makeText(MyActivity.this, "Trash Bin", Toast.LENGTH_SHORT).show();
70 | }
71 | });
72 |
73 | sample1.findViewById(R.id.magnifier2).setOnClickListener(new View.OnClickListener() {
74 | @Override
75 | public void onClick(View v) {
76 | Toast.makeText(MyActivity.this, "Magnifier", Toast.LENGTH_SHORT).show();
77 | }
78 | });
79 |
80 | sample1.addRevealListener(R.id.starbott, new SwipeLayout.OnRevealListener() {
81 | @Override
82 | public void onReveal(View child, SwipeLayout.DragEdge edge, float fraction, int distance) {
83 | View star = child.findViewById(R.id.star);
84 | float d = child.getHeight() / 2 - star.getHeight() / 2;
85 | ViewHelper.setTranslationY(star, d * fraction);
86 | ViewHelper.setScaleX(star, fraction + 0.6f);
87 | ViewHelper.setScaleY(star, fraction + 0.6f);
88 | }
89 | });
90 |
91 | //sample2
92 |
93 | sample2 = (SwipeLayout) findViewById(R.id.sample2);
94 | sample2.setShowMode(SwipeLayout.ShowMode.LayDown);
95 | sample2.addDrag(SwipeLayout.DragEdge.Right, sample2.findViewWithTag("Bottom2"));
96 | // sample2.setShowMode(SwipeLayout.ShowMode.PullOut);
97 | sample2.findViewById(R.id.star).setOnClickListener(new View.OnClickListener() {
98 | @Override
99 | public void onClick(View v) {
100 | Toast.makeText(MyActivity.this, "Star", Toast.LENGTH_SHORT).show();
101 | }
102 | });
103 |
104 | sample2.findViewById(R.id.trash).setOnClickListener(new View.OnClickListener() {
105 | @Override
106 | public void onClick(View v) {
107 | Toast.makeText(MyActivity.this, "Trash Bin", Toast.LENGTH_SHORT).show();
108 | }
109 | });
110 |
111 | sample2.findViewById(R.id.magnifier).setOnClickListener(new View.OnClickListener() {
112 | @Override
113 | public void onClick(View v) {
114 | Toast.makeText(MyActivity.this, "Magnifier", Toast.LENGTH_SHORT).show();
115 | }
116 | });
117 |
118 | sample2.findViewById(R.id.click).setOnClickListener(new View.OnClickListener() {
119 | @Override
120 | public void onClick(View v) {
121 | Toast.makeText(MyActivity.this, "Yo", Toast.LENGTH_SHORT).show();
122 | }
123 | });
124 | sample2.getSurfaceView().setOnClickListener(new View.OnClickListener() {
125 | @Override
126 | public void onClick(View v) {
127 | Toast.makeText(MyActivity.this, "Click on surface", Toast.LENGTH_SHORT).show();
128 | }
129 | });
130 |
131 | //sample3
132 |
133 | sample3 = (SwipeLayout) findViewById(R.id.sample3);
134 | sample3.addDrag(SwipeLayout.DragEdge.Top, sample3.findViewWithTag("Bottom3"));
135 | sample3.addRevealListener(R.id.bottom_wrapper_child1, new SwipeLayout.OnRevealListener() {
136 | @Override
137 | public void onReveal(View child, SwipeLayout.DragEdge edge, float fraction, int distance) {
138 | View star = child.findViewById(R.id.star);
139 | float d = child.getHeight() / 2 - star.getHeight() / 2;
140 | ViewHelper.setTranslationY(star, d * fraction);
141 | ViewHelper.setScaleX(star, fraction + 0.6f);
142 | ViewHelper.setScaleY(star, fraction + 0.6f);
143 | int c = (Integer) evaluate(fraction, Color.parseColor("#dddddd"), Color.parseColor("#4C535B"));
144 | child.setBackgroundColor(c);
145 | }
146 | });
147 | sample3.findViewById(R.id.bottom_wrapper_child1).setOnClickListener(new View.OnClickListener() {
148 | @Override
149 | public void onClick(View v) {
150 | Toast.makeText(MyActivity.this, "Yo!", Toast.LENGTH_SHORT).show();
151 | }
152 | });
153 | sample3.getSurfaceView().setOnClickListener(new View.OnClickListener() {
154 | @Override
155 | public void onClick(View v) {
156 | Toast.makeText(MyActivity.this, "Click on surface", Toast.LENGTH_SHORT).show();
157 | }
158 | });
159 |
160 | }
161 |
162 | @Override
163 | public boolean onCreateOptionsMenu(Menu menu) {
164 | // Inflate the menu; this adds items to the action bar if it is present.
165 | getMenuInflater().inflate(R.menu.my, menu);
166 | return true;
167 | }
168 |
169 | @Override
170 | public boolean onOptionsItemSelected(MenuItem item) {
171 | // Handle action bar item clicks here. The action bar will
172 | // automatically handle clicks on the Home/Up button, so long
173 | // as you specify a parent activity in AndroidManifest.xml.
174 | int id = item.getItemId();
175 | if (id == R.id.action_listview) {
176 | startActivity(new Intent(this, ListViewExample.class));
177 | return true;
178 | } else if (id == R.id.action_gridview) {
179 | startActivity(new Intent(this, GridViewExample.class));
180 | return true;
181 | } else if (id == R.id.action_nested) {
182 | startActivity(new Intent(this, NestedExample.class));
183 | return true;
184 | } else if (id == R.id.action_recycler) {
185 | startActivity(new Intent(this, RecyclerViewExample.class));
186 | }
187 | return super.onOptionsItemSelected(item);
188 | }
189 |
190 | /*
191 | Color transition method.
192 | */
193 | public Object evaluate(float fraction, Object startValue, Object endValue) {
194 | int startInt = (Integer) startValue;
195 | int startA = (startInt >> 24) & 0xff;
196 | int startR = (startInt >> 16) & 0xff;
197 | int startG = (startInt >> 8) & 0xff;
198 | int startB = startInt & 0xff;
199 |
200 | int endInt = (Integer) endValue;
201 | int endA = (endInt >> 24) & 0xff;
202 | int endR = (endInt >> 16) & 0xff;
203 | int endG = (endInt >> 8) & 0xff;
204 | int endB = endInt & 0xff;
205 |
206 | return (int) ((startA + (int) (fraction * (endA - startA))) << 24) |
207 | (int) ((startR + (int) (fraction * (endR - startR))) << 16) |
208 | (int) ((startG + (int) (fraction * (endG - startG))) << 8) |
209 | (int) ((startB + (int) (fraction * (endB - startB))));
210 | }
211 | }
212 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/daimajia/swipedemo/NestedExample.java:
--------------------------------------------------------------------------------
1 | package com.daimajia.swipedemo;
2 |
3 | import android.app.Activity;
4 | import android.os.Bundle;
5 | import android.view.View;
6 | import android.widget.Toast;
7 |
8 | import com.daimajia.swipe.SwipeLayout;
9 |
10 | public class NestedExample extends Activity{
11 |
12 | @Override
13 | protected void onCreate(Bundle savedInstanceState) {
14 | super.onCreate(savedInstanceState);
15 | setContentView(R.layout.complicate_layout);
16 | SwipeLayout swipeLayout = (SwipeLayout)findViewById(R.id.test_swipe_swipe);
17 | swipeLayout.setOnDoubleClickListener(new SwipeLayout.DoubleClickListener() {
18 | @Override
19 | public void onDoubleClick(SwipeLayout layout, boolean surface) {
20 | Toast.makeText(getApplicationContext(), "DoubleClick", Toast.LENGTH_SHORT).show();
21 | }
22 | });
23 | swipeLayout.findViewById(R.id.trash).setOnClickListener(new View.OnClickListener() {
24 | @Override
25 | public void onClick(View v) {
26 | Toast.makeText(getApplicationContext(), "Click", Toast.LENGTH_SHORT).show();
27 | }
28 | });
29 | }
30 |
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/daimajia/swipedemo/RecyclerViewExample.java:
--------------------------------------------------------------------------------
1 | package com.daimajia.swipedemo;
2 |
3 | import android.app.ActionBar;
4 | import android.app.Activity;
5 | import android.content.Intent;
6 | import android.os.Build;
7 | import android.os.Bundle;
8 | import android.support.v7.widget.LinearLayoutManager;
9 | import android.support.v7.widget.RecyclerView;
10 | import android.util.Log;
11 | import android.view.Menu;
12 | import android.view.MenuItem;
13 |
14 | import com.daimajia.swipe.util.Attributes;
15 | import com.daimajia.swipedemo.adapter.RecyclerViewAdapter;
16 | import com.daimajia.swipedemo.adapter.util.DividerItemDecoration;
17 |
18 | import java.util.ArrayList;
19 | import java.util.Arrays;
20 |
21 | import jp.wasabeef.recyclerview.animators.FadeInLeftAnimator;
22 |
23 | public class RecyclerViewExample extends Activity {
24 |
25 | /**
26 | * RecyclerView: The new recycler view replaces the list view. Its more modular and therefore we
27 | * must implement some of the functionality ourselves and attach it to our recyclerview.
28 | *
29 | * 1) Position items on the screen: This is done with LayoutManagers
30 | * 2) Animate & Decorate views: This is done with ItemAnimators & ItemDecorators
31 | * 3) Handle any touch events apart from scrolling: This is now done in our adapter's ViewHolder
32 | */
33 |
34 | private RecyclerView recyclerView;
35 | private RecyclerView.Adapter mAdapter;
36 |
37 | private ArrayList mDataSet;
38 |
39 | @Override
40 | protected void onCreate(Bundle savedInstanceState) {
41 | super.onCreate(savedInstanceState);
42 | setContentView(R.layout.recyclerview);
43 | recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
44 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
45 | ActionBar actionBar = getActionBar();
46 | if (actionBar != null) {
47 | actionBar.setTitle("RecyclerView");
48 | }
49 | }
50 |
51 | // Layout Managers:
52 | recyclerView.setLayoutManager(new LinearLayoutManager(this));
53 |
54 | // Item Decorator:
55 | recyclerView.addItemDecoration(new DividerItemDecoration(getResources().getDrawable(R.drawable.divider)));
56 | recyclerView.setItemAnimator(new FadeInLeftAnimator());
57 |
58 | // Adapter:
59 | 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"};
60 | mDataSet = new ArrayList(Arrays.asList(adapterData));
61 | mAdapter = new RecyclerViewAdapter(this, mDataSet);
62 | ((RecyclerViewAdapter) mAdapter).setMode(Attributes.Mode.Single);
63 | recyclerView.setAdapter(mAdapter);
64 |
65 | /* Listeners */
66 | recyclerView.setOnScrollListener(onScrollListener);
67 | }
68 |
69 | /**
70 | * Substitute for our onScrollListener for RecyclerView
71 | */
72 | RecyclerView.OnScrollListener onScrollListener = new RecyclerView.OnScrollListener() {
73 | @Override
74 | public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
75 | super.onScrollStateChanged(recyclerView, newState);
76 | Log.e("ListView", "onScrollStateChanged");
77 | }
78 |
79 | @Override
80 | public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
81 | super.onScrolled(recyclerView, dx, dy);
82 | // Could hide open views here if you wanted. //
83 | }
84 | };
85 |
86 |
87 | @Override
88 | public boolean onCreateOptionsMenu(Menu menu) {
89 | // Inflate the menu; this adds items to the action bar if it is present.
90 | getMenuInflater().inflate(R.menu.my, menu);
91 | return true;
92 | }
93 |
94 | @Override
95 | public boolean onOptionsItemSelected(MenuItem item) {
96 | // Handle action bar item clicks here. The action bar will
97 | // automatically handle clicks on the Home/Up button, so long
98 | // as you specify a parent activity in AndroidManifest.xml.
99 | int id = item.getItemId();
100 | if (id == R.id.action_listview) {
101 | startActivity(new Intent(this, ListViewExample.class));
102 | finish();
103 | return true;
104 | } else if (id == R.id.action_gridview) {
105 | startActivity(new Intent(this, GridViewExample.class));
106 | finish();
107 | return true;
108 | }
109 | return super.onOptionsItemSelected(item);
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/daimajia/swipedemo/adapter/ArraySwipeAdapterSample.java:
--------------------------------------------------------------------------------
1 | package com.daimajia.swipedemo.adapter;
2 |
3 | import android.content.Context;
4 |
5 | import com.daimajia.swipe.adapters.ArraySwipeAdapter;
6 | import com.daimajia.swipedemo.R;
7 |
8 | import java.util.List;
9 |
10 | /**
11 | * Sample usage of ArraySwipeAdapter.
12 | * @param
13 | */
14 | public class ArraySwipeAdapterSample extends ArraySwipeAdapter {
15 | public ArraySwipeAdapterSample(Context context, int resource) {
16 | super(context, resource);
17 | }
18 |
19 | public ArraySwipeAdapterSample(Context context, int resource, int textViewResourceId) {
20 | super(context, resource, textViewResourceId);
21 | }
22 |
23 | public ArraySwipeAdapterSample(Context context, int resource, Object[] objects) {
24 | super(context, resource, objects);
25 | }
26 |
27 | public ArraySwipeAdapterSample(Context context, int resource, int textViewResourceId, Object[] objects) {
28 | super(context, resource, textViewResourceId, objects);
29 | }
30 |
31 | public ArraySwipeAdapterSample(Context context, int resource, List objects) {
32 | super(context, resource, objects);
33 | }
34 |
35 | public ArraySwipeAdapterSample(Context context, int resource, int textViewResourceId, List objects) {
36 | super(context, resource, textViewResourceId, objects);
37 | }
38 |
39 | @Override
40 | public int getSwipeLayoutResourceId(int position) {
41 | return R.id.swipe;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/daimajia/swipedemo/adapter/GridViewAdapter.java:
--------------------------------------------------------------------------------
1 | package com.daimajia.swipedemo.adapter;
2 |
3 | import android.content.Context;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.TextView;
8 |
9 | import com.daimajia.swipe.adapters.BaseSwipeAdapter;
10 | import com.daimajia.swipedemo.R;
11 |
12 | public class GridViewAdapter extends BaseSwipeAdapter {
13 |
14 | private Context mContext;
15 |
16 | public GridViewAdapter(Context mContext) {
17 | this.mContext = mContext;
18 | }
19 |
20 | @Override
21 | public int getSwipeLayoutResourceId(int position) {
22 | return R.id.swipe;
23 | }
24 |
25 | @Override
26 | public View generateView(int position, ViewGroup parent) {
27 | return LayoutInflater.from(mContext).inflate(R.layout.grid_item, null);
28 | }
29 |
30 | @Override
31 | public void fillValues(int position, View convertView) {
32 | TextView t = (TextView)convertView.findViewById(R.id.position);
33 | t.setText((position + 1 )+".");
34 | }
35 |
36 | @Override
37 | public int getCount() {
38 | return 50;
39 | }
40 |
41 | @Override
42 | public Object getItem(int position) {
43 | return null;
44 | }
45 |
46 | @Override
47 | public long getItemId(int position) {
48 | return position;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/daimajia/swipedemo/adapter/ListViewAdapter.java:
--------------------------------------------------------------------------------
1 | package com.daimajia.swipedemo.adapter;
2 |
3 | import android.content.Context;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.TextView;
8 | import android.widget.Toast;
9 |
10 | import com.daimajia.androidanimations.library.Techniques;
11 | import com.daimajia.androidanimations.library.YoYo;
12 | import com.daimajia.swipe.SimpleSwipeListener;
13 | import com.daimajia.swipe.SwipeLayout;
14 | import com.daimajia.swipe.adapters.BaseSwipeAdapter;
15 | import com.daimajia.swipedemo.R;
16 |
17 | public class ListViewAdapter extends BaseSwipeAdapter {
18 |
19 | private Context mContext;
20 |
21 | public ListViewAdapter(Context mContext) {
22 | this.mContext = mContext;
23 | }
24 |
25 | @Override
26 | public int getSwipeLayoutResourceId(int position) {
27 | return R.id.swipe;
28 | }
29 |
30 | @Override
31 | public View generateView(int position, ViewGroup parent) {
32 | View v = LayoutInflater.from(mContext).inflate(R.layout.listview_item, null);
33 | SwipeLayout swipeLayout = (SwipeLayout)v.findViewById(getSwipeLayoutResourceId(position));
34 | swipeLayout.addSwipeListener(new SimpleSwipeListener() {
35 | @Override
36 | public void onOpen(SwipeLayout layout) {
37 | YoYo.with(Techniques.Tada).duration(500).delay(100).playOn(layout.findViewById(R.id.trash));
38 | }
39 | });
40 | swipeLayout.setOnDoubleClickListener(new SwipeLayout.DoubleClickListener() {
41 | @Override
42 | public void onDoubleClick(SwipeLayout layout, boolean surface) {
43 | Toast.makeText(mContext, "DoubleClick", Toast.LENGTH_SHORT).show();
44 | }
45 | });
46 | v.findViewById(R.id.delete).setOnClickListener(new View.OnClickListener() {
47 | @Override
48 | public void onClick(View view) {
49 | Toast.makeText(mContext, "click delete", Toast.LENGTH_SHORT).show();
50 | }
51 | });
52 | return v;
53 | }
54 |
55 | @Override
56 | public void fillValues(int position, View convertView) {
57 | TextView t = (TextView)convertView.findViewById(R.id.position);
58 | t.setText((position + 1) + ".");
59 | }
60 |
61 | @Override
62 | public int getCount() {
63 | return 50;
64 | }
65 |
66 | @Override
67 | public Object getItem(int position) {
68 | return null;
69 | }
70 |
71 | @Override
72 | public long getItemId(int position) {
73 | return position;
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/daimajia/swipedemo/adapter/RecyclerViewAdapter.java:
--------------------------------------------------------------------------------
1 | package com.daimajia.swipedemo.adapter;
2 |
3 | import android.content.Context;
4 | import android.support.v7.widget.RecyclerView;
5 | import android.util.Log;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import android.widget.Button;
10 | import android.widget.TextView;
11 | import android.widget.Toast;
12 |
13 | import com.daimajia.androidanimations.library.Techniques;
14 | import com.daimajia.androidanimations.library.YoYo;
15 | import com.daimajia.swipe.SimpleSwipeListener;
16 | import com.daimajia.swipe.SwipeLayout;
17 | import com.daimajia.swipe.adapters.RecyclerSwipeAdapter;
18 | import com.daimajia.swipedemo.R;
19 |
20 | import java.util.ArrayList;
21 |
22 | public class RecyclerViewAdapter extends RecyclerSwipeAdapter {
23 |
24 | public static class SimpleViewHolder extends RecyclerView.ViewHolder {
25 | SwipeLayout swipeLayout;
26 | TextView textViewPos;
27 | TextView textViewData;
28 | Button buttonDelete;
29 |
30 | public SimpleViewHolder(View itemView) {
31 | super(itemView);
32 | swipeLayout = (SwipeLayout) itemView.findViewById(R.id.swipe);
33 | textViewPos = (TextView) itemView.findViewById(R.id.position);
34 | textViewData = (TextView) itemView.findViewById(R.id.text_data);
35 | buttonDelete = (Button) itemView.findViewById(R.id.delete);
36 |
37 | itemView.setOnClickListener(new View.OnClickListener() {
38 | @Override
39 | public void onClick(View view) {
40 | Log.d(getClass().getSimpleName(), "onItemSelected: " + textViewData.getText().toString());
41 | Toast.makeText(view.getContext(), "onItemSelected: " + textViewData.getText().toString(), Toast.LENGTH_SHORT).show();
42 | }
43 | });
44 | }
45 | }
46 |
47 | private Context mContext;
48 | private ArrayList mDataset;
49 |
50 | //protected SwipeItemRecyclerMangerImpl mItemManger = new SwipeItemRecyclerMangerImpl(this);
51 |
52 | public RecyclerViewAdapter(Context context, ArrayList objects) {
53 | this.mContext = context;
54 | this.mDataset = objects;
55 | }
56 |
57 | @Override
58 | public SimpleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
59 | View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_item, parent, false);
60 | return new SimpleViewHolder(view);
61 | }
62 |
63 | @Override
64 | public void onBindViewHolder(final SimpleViewHolder viewHolder, final int position) {
65 | String item = mDataset.get(position);
66 | viewHolder.swipeLayout.setShowMode(SwipeLayout.ShowMode.LayDown);
67 | viewHolder.swipeLayout.addSwipeListener(new SimpleSwipeListener() {
68 | @Override
69 | public void onOpen(SwipeLayout layout) {
70 | YoYo.with(Techniques.Tada).duration(500).delay(100).playOn(layout.findViewById(R.id.trash));
71 | }
72 | });
73 | viewHolder.swipeLayout.setOnDoubleClickListener(new SwipeLayout.DoubleClickListener() {
74 | @Override
75 | public void onDoubleClick(SwipeLayout layout, boolean surface) {
76 | Toast.makeText(mContext, "DoubleClick", Toast.LENGTH_SHORT).show();
77 | }
78 | });
79 | viewHolder.buttonDelete.setOnClickListener(new View.OnClickListener() {
80 | @Override
81 | public void onClick(View view) {
82 | mItemManger.removeShownLayouts(viewHolder.swipeLayout);
83 | mDataset.remove(position);
84 | notifyItemRemoved(position);
85 | notifyItemRangeChanged(position, mDataset.size());
86 | mItemManger.closeAllItems();
87 | Toast.makeText(view.getContext(), "Deleted " + viewHolder.textViewData.getText().toString() + "!", Toast.LENGTH_SHORT).show();
88 | }
89 | });
90 | viewHolder.textViewPos.setText((position + 1) + ".");
91 | viewHolder.textViewData.setText(item);
92 | mItemManger.bind(viewHolder.itemView, position);
93 | }
94 |
95 | @Override
96 | public int getItemCount() {
97 | return mDataset.size();
98 | }
99 |
100 | @Override
101 | public int getSwipeLayoutResourceId(int position) {
102 | return R.id.swipe;
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/daimajia/swipedemo/adapter/util/DividerItemDecoration.java:
--------------------------------------------------------------------------------
1 | package com.daimajia.swipedemo.adapter.util;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.graphics.Canvas;
6 | import android.graphics.Rect;
7 | import android.graphics.drawable.Drawable;
8 | import android.support.v7.widget.LinearLayoutManager;
9 | import android.support.v7.widget.RecyclerView;
10 | import android.util.AttributeSet;
11 | import android.view.View;
12 |
13 | public class DividerItemDecoration extends RecyclerView.ItemDecoration {
14 |
15 | private Drawable mDivider;
16 | private boolean mShowFirstDivider = false;
17 | private boolean mShowLastDivider = false;
18 |
19 |
20 | public DividerItemDecoration(Context context, AttributeSet attrs) {
21 | final TypedArray a = context
22 | .obtainStyledAttributes(attrs, new int[]{android.R.attr.listDivider});
23 | mDivider = a.getDrawable(0);
24 | a.recycle();
25 | }
26 |
27 | public DividerItemDecoration(Context context, AttributeSet attrs, boolean showFirstDivider,
28 | boolean showLastDivider) {
29 | this(context, attrs);
30 | mShowFirstDivider = showFirstDivider;
31 | mShowLastDivider = showLastDivider;
32 | }
33 |
34 | public DividerItemDecoration(Drawable divider) {
35 | mDivider = divider;
36 | }
37 |
38 | public DividerItemDecoration(Drawable divider, boolean showFirstDivider,
39 | boolean showLastDivider) {
40 | this(divider);
41 | mShowFirstDivider = showFirstDivider;
42 | mShowLastDivider = showLastDivider;
43 | }
44 |
45 | @Override
46 | public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
47 | RecyclerView.State state) {
48 | super.getItemOffsets(outRect, view, parent, state);
49 | if (mDivider == null) {
50 | return;
51 | }
52 | if (parent.getChildPosition(view) < 1) {
53 | return;
54 | }
55 |
56 | if (getOrientation(parent) == LinearLayoutManager.VERTICAL) {
57 | outRect.top = mDivider.getIntrinsicHeight();
58 | } else {
59 | outRect.left = mDivider.getIntrinsicWidth();
60 | }
61 | }
62 |
63 | @Override
64 | public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
65 | if (mDivider == null) {
66 | super.onDrawOver(c, parent, state);
67 | return;
68 | }
69 |
70 | // Initialization needed to avoid compiler warning
71 | int left = 0, right = 0, top = 0, bottom = 0, size;
72 | int orientation = getOrientation(parent);
73 | int childCount = parent.getChildCount();
74 |
75 | if (orientation == LinearLayoutManager.VERTICAL) {
76 | size = mDivider.getIntrinsicHeight();
77 | left = parent.getPaddingLeft();
78 | right = parent.getWidth() - parent.getPaddingRight();
79 | } else { //horizontal
80 | size = mDivider.getIntrinsicWidth();
81 | top = parent.getPaddingTop();
82 | bottom = parent.getHeight() - parent.getPaddingBottom();
83 | }
84 |
85 | for (int i = mShowFirstDivider ? 0 : 1; i < childCount; i++) {
86 | View child = parent.getChildAt(i);
87 | RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
88 |
89 | if (orientation == LinearLayoutManager.VERTICAL) {
90 | top = child.getTop() - params.topMargin;
91 | bottom = top + size;
92 | } else { //horizontal
93 | left = child.getLeft() - params.leftMargin;
94 | right = left + size;
95 | }
96 | mDivider.setBounds(left, top, right, bottom);
97 | mDivider.draw(c);
98 | }
99 |
100 | // show last divider
101 | if (mShowLastDivider && childCount > 0) {
102 | View child = parent.getChildAt(childCount - 1);
103 | RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
104 | if (orientation == LinearLayoutManager.VERTICAL) {
105 | top = child.getBottom() + params.bottomMargin;
106 | bottom = top + size;
107 | } else { // horizontal
108 | left = child.getRight() + params.rightMargin;
109 | right = left + size;
110 | }
111 | mDivider.setBounds(left, top, right, bottom);
112 | mDivider.draw(c);
113 | }
114 | }
115 |
116 | private int getOrientation(RecyclerView parent) {
117 | if (parent.getLayoutManager() instanceof LinearLayoutManager) {
118 | LinearLayoutManager layoutManager = (LinearLayoutManager) parent.getLayoutManager();
119 | return layoutManager.getOrientation();
120 | } else {
121 | throw new IllegalStateException(
122 | "DividerItemDecoration can only be used with a LinearLayoutManager.");
123 | }
124 | }
125 | }
--------------------------------------------------------------------------------
/demo/src/main/java/com/daimajia/swipedemo/adapter/util/RecyclerItemClickListener.java:
--------------------------------------------------------------------------------
1 | package com.daimajia.swipedemo.adapter.util;
2 |
3 | import android.content.Context;
4 | import android.support.v7.widget.RecyclerView;
5 | import android.view.GestureDetector;
6 | import android.view.MotionEvent;
7 | import android.view.View;
8 |
9 | public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
10 | private OnItemClickListener mListener;
11 |
12 | public interface OnItemClickListener {
13 | public void onItemClick(View view, int position);
14 | }
15 |
16 | GestureDetector mGestureDetector;
17 |
18 | public RecyclerItemClickListener(Context context, OnItemClickListener listener) {
19 | mListener = listener;
20 | mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
21 | @Override
22 | public boolean onSingleTapUp(MotionEvent e) {
23 | return true;
24 | }
25 | });
26 | }
27 |
28 | @Override
29 | public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) {
30 | View childView = view.findChildViewUnder(e.getX(), e.getY());
31 | if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
32 | mListener.onItemClick(childView, view.getChildPosition(childView));
33 | }
34 | return false;
35 | }
36 |
37 | @Override
38 | public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) {
39 | }
40 |
41 | @Override
42 | public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
43 |
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/demo/src/main/res/drawable-hdpi/bird.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/daimajia/AndroidSwipeLayout/5f8678b04751fb8510a88586b22e07ccf64bca99/demo/src/main/res/drawable-hdpi/bird.png
--------------------------------------------------------------------------------
/demo/src/main/res/drawable-hdpi/hand.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/daimajia/AndroidSwipeLayout/5f8678b04751fb8510a88586b22e07ccf64bca99/demo/src/main/res/drawable-hdpi/hand.png
--------------------------------------------------------------------------------
/demo/src/main/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/daimajia/AndroidSwipeLayout/5f8678b04751fb8510a88586b22e07ccf64bca99/demo/src/main/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/src/main/res/drawable-hdpi/magnifier.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/daimajia/AndroidSwipeLayout/5f8678b04751fb8510a88586b22e07ccf64bca99/demo/src/main/res/drawable-hdpi/magnifier.png
--------------------------------------------------------------------------------
/demo/src/main/res/drawable-hdpi/star.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/daimajia/AndroidSwipeLayout/5f8678b04751fb8510a88586b22e07ccf64bca99/demo/src/main/res/drawable-hdpi/star.png
--------------------------------------------------------------------------------
/demo/src/main/res/drawable-hdpi/trash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/daimajia/AndroidSwipeLayout/5f8678b04751fb8510a88586b22e07ccf64bca99/demo/src/main/res/drawable-hdpi/trash.png
--------------------------------------------------------------------------------
/demo/src/main/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/daimajia/AndroidSwipeLayout/5f8678b04751fb8510a88586b22e07ccf64bca99/demo/src/main/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/src/main/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/daimajia/AndroidSwipeLayout/5f8678b04751fb8510a88586b22e07ccf64bca99/demo/src/main/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/src/main/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/daimajia/AndroidSwipeLayout/5f8678b04751fb8510a88586b22e07ccf64bca99/demo/src/main/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/src/main/res/drawable/dark_gray.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/demo/src/main/res/drawable/divider.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
19 |
20 |
21 |
23 |
24 |
--------------------------------------------------------------------------------
/demo/src/main/res/drawable/item_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/demo/src/main/res/drawable/red.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/demo/src/main/res/drawable/white.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/complicate_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/grid_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
13 |
18 |
19 |
20 |
25 |
29 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/gridview.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/listview.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/listview_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
18 |
19 |
25 |
26 |
33 |
34 |
42 |
43 |
44 |
49 |
50 |
54 |
55 |
61 |
62 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
12 |
18 |
22 |
23 |
26 |
27 |
34 |
35 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/recyclerview.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/recyclerview_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
12 |
13 |
20 |
21 |
27 |
28 |
35 |
36 |
44 |
45 |
46 |
52 |
53 |
57 |
58 |
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/sampe_nested_edittext.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
8 |
16 |
17 |
18 |
23 |
27 |
31 |
32 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/sampe_nested_scrollview.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
8 |
12 |
17 |
18 |
19 |
20 |
25 |
29 |
34 |
38 |
43 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/sampe_nested_seekbar.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
8 |
16 |
17 |
18 |
23 |
27 |
31 |
32 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/sample1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
17 |
18 |
28 |
29 |
37 |
38 |
39 |
44 |
45 |
53 |
54 |
62 |
63 |
71 |
72 |
73 |
78 |
84 |
91 |
92 |
93 |
94 |
101 |
102 |
103 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/sample2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
9 |
17 |
25 |
33 |
34 |
35 |
41 |
46 |
52 |
53 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/sample3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
10 |
15 |
22 |
23 |
24 |
25 |
32 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/sample_nested_parent.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
9 |
17 |
18 |
19 |
24 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/sample_together.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
10 |
11 |
12 |
15 |
16 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/demo/src/main/res/menu/my.xml:
--------------------------------------------------------------------------------
1 |
20 |
--------------------------------------------------------------------------------
/demo/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/demo/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #E8E8E0
4 | #DBDBD3
5 | #FF3B00
6 | #990000
7 | #4C535B
8 | #ff7e8a97
9 |
--------------------------------------------------------------------------------
/demo/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/demo/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | AndroidSwipeLayout
5 | Hello world!
6 | Settings
7 |
8 |
9 |
--------------------------------------------------------------------------------
/demo/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Settings specified in this file will override any Gradle settings
5 | # configured through the IDE.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 |
20 |
21 | VERSION_NAME=1.2.0
22 | VERSION_CODE=22
23 | GROUP=com.daimajia.swipelayout
24 |
25 | ANDROID_BUILD_MIN_SDK_VERSION=9
26 | ANDROID_BUILD_TARGET_SDK_VERSION=25
27 | ANDROID_BUILD_SDK_VERSION=25
28 | ANDROID_BUILD_TOOLS_VERSION=25.0.2
29 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/daimajia/AndroidSwipeLayout/5f8678b04751fb8510a88586b22e07ccf64bca99/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Thu Mar 09 16:07:03 CST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/library/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/library/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion Integer.parseInt(project.ANDROID_BUILD_SDK_VERSION)
5 | buildToolsVersion project.ANDROID_BUILD_TOOLS_VERSION
6 |
7 | defaultConfig {
8 | minSdkVersion 9
9 | targetSdkVersion Integer.parseInt(project.ANDROID_BUILD_TARGET_SDK_VERSION)
10 | }
11 | }
12 |
13 | dependencies {
14 | compile 'com.android.support:recyclerview-v7:25.2.0'
15 | compile 'com.android.support:support-v4:25.2.0'
16 | }
17 | apply from: './gradle-mvn-push.gradle'
18 |
19 | // build a jar with source files
20 | task sourcesJar(type: Jar) {
21 | from android.sourceSets.main.java.srcDirs
22 | classifier = 'sources'
23 | }
24 | artifacts {
25 | archives sourcesJar
26 | }
27 |
--------------------------------------------------------------------------------
/library/gradle-mvn-push.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Chris Banes
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | apply plugin: 'maven'
18 | apply plugin: 'signing'
19 |
20 | def isReleaseBuild() {
21 | return VERSION_NAME.contains("SNAPSHOT") == false
22 | }
23 |
24 | def getReleaseRepositoryUrl() {
25 | return hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL
26 | : "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
27 | }
28 |
29 | def getSnapshotRepositoryUrl() {
30 | return hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL
31 | : "https://oss.sonatype.org/content/repositories/snapshots/"
32 | }
33 |
34 | def getRepositoryUsername() {
35 | return hasProperty('NEXUS_USERNAME') ? NEXUS_USERNAME : ""
36 | }
37 |
38 | def getRepositoryPassword() {
39 | return hasProperty('NEXUS_PASSWORD') ? NEXUS_PASSWORD : ""
40 | }
41 |
42 | afterEvaluate { project ->
43 | uploadArchives {
44 | repositories {
45 | mavenDeployer {
46 | beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
47 |
48 | pom.groupId = GROUP
49 | pom.artifactId = POM_ARTIFACT_ID
50 | pom.version = VERSION_NAME
51 |
52 | repository(url: getReleaseRepositoryUrl()) {
53 | authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())
54 | }
55 | snapshotRepository(url: getSnapshotRepositoryUrl()) {
56 | authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())
57 | }
58 |
59 | pom.project {
60 | name POM_NAME
61 | packaging POM_PACKAGING
62 | description POM_DESCRIPTION
63 | url POM_URL
64 |
65 | scm {
66 | url POM_SCM_URL
67 | connection POM_SCM_CONNECTION
68 | developerConnection POM_SCM_DEV_CONNECTION
69 | }
70 |
71 | licenses {
72 | license {
73 | name POM_LICENCE_NAME
74 | url POM_LICENCE_URL
75 | distribution POM_LICENCE_DIST
76 | }
77 | }
78 |
79 | developers {
80 | developer {
81 | id POM_DEVELOPER_ID
82 | name POM_DEVELOPER_NAME
83 | }
84 | }
85 | }
86 | }
87 | }
88 | }
89 |
90 | signing {
91 | required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") }
92 | sign configurations.archives
93 | }
94 |
95 | task apklib(type: Zip){
96 | appendix = extension = 'apklib'
97 |
98 | from 'AndroidManifest.xml'
99 | into('res') {
100 | from 'res'
101 | }
102 | into('src') {
103 | from 'src'
104 | }
105 | }
106 |
107 | task androidJavadocs(type: Javadoc) {
108 | source = android.sourceSets.main.java.srcDirs
109 | classpath += project.files(android.getBootClasspath() .join(File.pathSeparator))
110 | }
111 |
112 | task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {
113 | classifier = 'javadoc'
114 | from androidJavadocs.destinationDir
115 | }
116 |
117 | task androidSourcesJar(type: Jar) {
118 | classifier = 'sources'
119 | from android.sourceSets.main.java.srcDirs
120 | }
121 |
122 | artifacts {
123 | archives androidSourcesJar
124 | archives androidJavadocsJar
125 | archives apklib
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/library/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Settings specified in this file will override any Gradle settings
5 | # configured through the IDE.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 |
20 | POM_NAME=Android SwipeLayout Library
21 | POM_ARTIFACT_ID=library
22 | POM_PACKAGING=aar
23 |
24 | POM_DESCRIPTION=Android Swipe Layout
25 | POM_URL=https://github.com/daimajia/AndroidSwipeLayout
26 | POM_SCM_URL=https://github.com/daimajia/AndroidSwipeLayout
27 | POM_SCM_CONNECTION=scm:https://github.com/daimajia/AndroidSwipeLayout.git
28 | POM_SCM_DEV_CONNECTION=scm:https://github.com/daimajia/AndroidSwipeLayout.git
29 | POM_LICENCE_NAME=MIT
30 | POM_LICENCE_URL=http://opensource.org/licenses/MIT
31 | POM_LICENCE_DIST=repo
32 | POM_DEVELOPER_ID=daimajia
33 | POM_DEVELOPER_NAME=daimajia
--------------------------------------------------------------------------------
/library/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Applications/Android Studio.app/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/library/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/library/src/main/java/com/daimajia/swipe/SimpleSwipeListener.java:
--------------------------------------------------------------------------------
1 | package com.daimajia.swipe;
2 |
3 | public class SimpleSwipeListener implements SwipeLayout.SwipeListener {
4 |
5 | @Override
6 | public void onStartOpen(SwipeLayout layout) {
7 | }
8 |
9 | @Override
10 | public void onOpen(SwipeLayout layout) {
11 | }
12 |
13 | @Override
14 | public void onStartClose(SwipeLayout layout) {
15 | }
16 |
17 | @Override
18 | public void onClose(SwipeLayout layout) {
19 | }
20 |
21 | @Override
22 | public void onUpdate(SwipeLayout layout, int leftOffset, int topOffset) {
23 | }
24 |
25 | @Override
26 | public void onHandRelease(SwipeLayout layout, float xvel, float yvel) {
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/library/src/main/java/com/daimajia/swipe/SwipeLayout.java:
--------------------------------------------------------------------------------
1 | package com.daimajia.swipe;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.graphics.Rect;
6 | import android.support.v4.view.GravityCompat;
7 | import android.support.v4.view.ViewCompat;
8 | import android.support.v4.widget.ViewDragHelper;
9 | import android.util.AttributeSet;
10 | import android.view.GestureDetector;
11 | import android.view.Gravity;
12 | import android.view.HapticFeedbackConstants;
13 | import android.view.MotionEvent;
14 | import android.view.View;
15 | import android.view.ViewConfiguration;
16 | import android.view.ViewGroup;
17 | import android.view.ViewParent;
18 | import android.widget.AbsListView;
19 | import android.widget.AdapterView;
20 | import android.widget.FrameLayout;
21 |
22 | import java.lang.reflect.Method;
23 | import java.util.ArrayList;
24 | import java.util.Arrays;
25 | import java.util.HashMap;
26 | import java.util.LinkedHashMap;
27 | import java.util.List;
28 | import java.util.Map;
29 |
30 | public class SwipeLayout extends FrameLayout {
31 | @Deprecated
32 | public static final int EMPTY_LAYOUT = -1;
33 | private static final int DRAG_LEFT = 1;
34 | private static final int DRAG_RIGHT = 2;
35 | private static final int DRAG_TOP = 4;
36 | private static final int DRAG_BOTTOM = 8;
37 | private static final DragEdge DefaultDragEdge = DragEdge.Right;
38 |
39 | private int mTouchSlop;
40 |
41 | private DragEdge mCurrentDragEdge = DefaultDragEdge;
42 | private ViewDragHelper mDragHelper;
43 |
44 | private int mDragDistance = 0;
45 | private LinkedHashMap mDragEdges = new LinkedHashMap<>();
46 | private ShowMode mShowMode;
47 |
48 | private float[] mEdgeSwipesOffset = new float[4];
49 |
50 | private List mSwipeListeners = new ArrayList<>();
51 | private List mSwipeDeniers = new ArrayList<>();
52 | private Map> mRevealListeners = new HashMap<>();
53 | private Map mShowEntirely = new HashMap<>();
54 | private Map mViewBoundCache = new HashMap<>();//save all children's bound, restore in onLayout
55 |
56 | private DoubleClickListener mDoubleClickListener;
57 |
58 | private boolean mSwipeEnabled = true;
59 | private boolean[] mSwipesEnabled = new boolean[]{true, true, true, true};
60 | private boolean mClickToClose = false;
61 | private float mWillOpenPercentAfterOpen = 0.75f;
62 | private float mWillOpenPercentAfterClose = 0.25f;
63 |
64 | public enum DragEdge {
65 | Left,
66 | Top,
67 | Right,
68 | Bottom
69 | }
70 |
71 | public enum ShowMode {
72 | LayDown,
73 | PullOut
74 | }
75 |
76 | public SwipeLayout(Context context) {
77 | this(context, null);
78 | }
79 |
80 | public SwipeLayout(Context context, AttributeSet attrs) {
81 | this(context, attrs, 0);
82 | }
83 |
84 | public SwipeLayout(Context context, AttributeSet attrs, int defStyle) {
85 | super(context, attrs, defStyle);
86 | mDragHelper = ViewDragHelper.create(this, mDragHelperCallback);
87 | mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
88 |
89 | TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SwipeLayout);
90 | int dragEdgeChoices = a.getInt(R.styleable.SwipeLayout_drag_edge, DRAG_RIGHT);
91 | mEdgeSwipesOffset[DragEdge.Left.ordinal()] = a.getDimension(R.styleable.SwipeLayout_leftEdgeSwipeOffset, 0);
92 | mEdgeSwipesOffset[DragEdge.Right.ordinal()] = a.getDimension(R.styleable.SwipeLayout_rightEdgeSwipeOffset, 0);
93 | mEdgeSwipesOffset[DragEdge.Top.ordinal()] = a.getDimension(R.styleable.SwipeLayout_topEdgeSwipeOffset, 0);
94 | mEdgeSwipesOffset[DragEdge.Bottom.ordinal()] = a.getDimension(R.styleable.SwipeLayout_bottomEdgeSwipeOffset, 0);
95 | setClickToClose(a.getBoolean(R.styleable.SwipeLayout_clickToClose, mClickToClose));
96 |
97 | if ((dragEdgeChoices & DRAG_LEFT) == DRAG_LEFT) {
98 | mDragEdges.put(DragEdge.Left, null);
99 | }
100 | if ((dragEdgeChoices & DRAG_TOP) == DRAG_TOP) {
101 | mDragEdges.put(DragEdge.Top, null);
102 | }
103 | if ((dragEdgeChoices & DRAG_RIGHT) == DRAG_RIGHT) {
104 | mDragEdges.put(DragEdge.Right, null);
105 | }
106 | if ((dragEdgeChoices & DRAG_BOTTOM) == DRAG_BOTTOM) {
107 | mDragEdges.put(DragEdge.Bottom, null);
108 | }
109 | int ordinal = a.getInt(R.styleable.SwipeLayout_show_mode, ShowMode.PullOut.ordinal());
110 | mShowMode = ShowMode.values()[ordinal];
111 | a.recycle();
112 |
113 | }
114 |
115 | public interface SwipeListener {
116 | void onStartOpen(SwipeLayout layout);
117 |
118 | void onOpen(SwipeLayout layout);
119 |
120 | void onStartClose(SwipeLayout layout);
121 |
122 | void onClose(SwipeLayout layout);
123 |
124 | void onUpdate(SwipeLayout layout, int leftOffset, int topOffset);
125 |
126 | void onHandRelease(SwipeLayout layout, float xvel, float yvel);
127 | }
128 |
129 | public void addSwipeListener(SwipeListener l) {
130 | mSwipeListeners.add(l);
131 | }
132 |
133 | public void removeSwipeListener(SwipeListener l) {
134 | mSwipeListeners.remove(l);
135 | }
136 |
137 | public void removeAllSwipeListener() {
138 | mSwipeListeners.clear();
139 | }
140 |
141 | public interface SwipeDenier {
142 | /*
143 | * Called in onInterceptTouchEvent Determines if this swipe event should
144 | * be denied Implement this interface if you are using views with swipe
145 | * gestures As a child of SwipeLayout
146 | *
147 | * @return true deny false allow
148 | */
149 | boolean shouldDenySwipe(MotionEvent ev);
150 | }
151 |
152 | public void addSwipeDenier(SwipeDenier denier) {
153 | mSwipeDeniers.add(denier);
154 | }
155 |
156 | public void removeSwipeDenier(SwipeDenier denier) {
157 | mSwipeDeniers.remove(denier);
158 | }
159 |
160 | public void removeAllSwipeDeniers() {
161 | mSwipeDeniers.clear();
162 | }
163 |
164 | public interface OnRevealListener {
165 | void onReveal(View child, DragEdge edge, float fraction, int distance);
166 | }
167 |
168 | /**
169 | * bind a view with a specific
170 | * {@link com.daimajia.swipe.SwipeLayout.OnRevealListener}
171 | *
172 | * @param childId the view id.
173 | * @param l the target
174 | * {@link com.daimajia.swipe.SwipeLayout.OnRevealListener}
175 | */
176 | public void addRevealListener(int childId, OnRevealListener l) {
177 | View child = findViewById(childId);
178 | if (child == null) {
179 | throw new IllegalArgumentException("Child does not belong to SwipeListener.");
180 | }
181 |
182 | if (!mShowEntirely.containsKey(child)) {
183 | mShowEntirely.put(child, false);
184 | }
185 | if (mRevealListeners.get(child) == null)
186 | mRevealListeners.put(child, new ArrayList());
187 |
188 | mRevealListeners.get(child).add(l);
189 | }
190 |
191 | /**
192 | * bind multiple views with an
193 | * {@link com.daimajia.swipe.SwipeLayout.OnRevealListener}.
194 | *
195 | * @param childIds the view id.
196 | * @param l the {@link com.daimajia.swipe.SwipeLayout.OnRevealListener}
197 | */
198 | public void addRevealListener(int[] childIds, OnRevealListener l) {
199 | for (int i : childIds)
200 | addRevealListener(i, l);
201 | }
202 |
203 | public void removeRevealListener(int childId, OnRevealListener l) {
204 | View child = findViewById(childId);
205 |
206 | if (child == null) return;
207 |
208 | mShowEntirely.remove(child);
209 | if (mRevealListeners.containsKey(child)) mRevealListeners.get(child).remove(l);
210 | }
211 |
212 | public void removeAllRevealListeners(int childId) {
213 | View child = findViewById(childId);
214 | if (child != null) {
215 | mRevealListeners.remove(child);
216 | mShowEntirely.remove(child);
217 | }
218 | }
219 |
220 | private ViewDragHelper.Callback mDragHelperCallback = new ViewDragHelper.Callback() {
221 |
222 | @Override
223 | public int clampViewPositionHorizontal(View child, int left, int dx) {
224 | if (child == getSurfaceView()) {
225 | switch (mCurrentDragEdge) {
226 | case Top:
227 | case Bottom:
228 | return getPaddingLeft();
229 | case Left:
230 | if (left < getPaddingLeft()) return getPaddingLeft();
231 | if (left > getPaddingLeft() + mDragDistance)
232 | return getPaddingLeft() + mDragDistance;
233 | break;
234 | case Right:
235 | if (left > getPaddingLeft()) return getPaddingLeft();
236 | if (left < getPaddingLeft() - mDragDistance)
237 | return getPaddingLeft() - mDragDistance;
238 | break;
239 | }
240 | } else if (getCurrentBottomView() == child) {
241 |
242 | switch (mCurrentDragEdge) {
243 | case Top:
244 | case Bottom:
245 | return getPaddingLeft();
246 | case Left:
247 | if (mShowMode == ShowMode.PullOut) {
248 | if (left > getPaddingLeft()) return getPaddingLeft();
249 | }
250 | break;
251 | case Right:
252 | if (mShowMode == ShowMode.PullOut) {
253 | if (left < getMeasuredWidth() - mDragDistance) {
254 | return getMeasuredWidth() - mDragDistance;
255 | }
256 | }
257 | break;
258 | }
259 | }
260 | return left;
261 | }
262 |
263 | @Override
264 | public int clampViewPositionVertical(View child, int top, int dy) {
265 | if (child == getSurfaceView()) {
266 | switch (mCurrentDragEdge) {
267 | case Left:
268 | case Right:
269 | return getPaddingTop();
270 | case Top:
271 | if (top < getPaddingTop()) return getPaddingTop();
272 | if (top > getPaddingTop() + mDragDistance)
273 | return getPaddingTop() + mDragDistance;
274 | break;
275 | case Bottom:
276 | if (top < getPaddingTop() - mDragDistance) {
277 | return getPaddingTop() - mDragDistance;
278 | }
279 | if (top > getPaddingTop()) {
280 | return getPaddingTop();
281 | }
282 | }
283 | } else {
284 | View surfaceView = getSurfaceView();
285 | int surfaceViewTop = surfaceView == null ? 0 : surfaceView.getTop();
286 | switch (mCurrentDragEdge) {
287 | case Left:
288 | case Right:
289 | return getPaddingTop();
290 | case Top:
291 | if (mShowMode == ShowMode.PullOut) {
292 | if (top > getPaddingTop()) return getPaddingTop();
293 | } else {
294 | if (surfaceViewTop + dy < getPaddingTop())
295 | return getPaddingTop();
296 | if (surfaceViewTop + dy > getPaddingTop() + mDragDistance)
297 | return getPaddingTop() + mDragDistance;
298 | }
299 | break;
300 | case Bottom:
301 | if (mShowMode == ShowMode.PullOut) {
302 | if (top < getMeasuredHeight() - mDragDistance)
303 | return getMeasuredHeight() - mDragDistance;
304 | } else {
305 | if (surfaceViewTop + dy >= getPaddingTop())
306 | return getPaddingTop();
307 | if (surfaceViewTop + dy <= getPaddingTop() - mDragDistance)
308 | return getPaddingTop() - mDragDistance;
309 | }
310 | }
311 | }
312 | return top;
313 | }
314 |
315 | @Override
316 | public boolean tryCaptureView(View child, int pointerId) {
317 | boolean result = child == getSurfaceView() || getBottomViews().contains(child);
318 | if (result) {
319 | isCloseBeforeDrag = getOpenStatus() == Status.Close;
320 | }
321 | return result;
322 | }
323 |
324 | @Override
325 | public int getViewHorizontalDragRange(View child) {
326 | return mDragDistance;
327 | }
328 |
329 | @Override
330 | public int getViewVerticalDragRange(View child) {
331 | return mDragDistance;
332 | }
333 |
334 | boolean isCloseBeforeDrag = true;
335 |
336 | @Override
337 | public void onViewReleased(View releasedChild, float xvel, float yvel) {
338 | super.onViewReleased(releasedChild, xvel, yvel);
339 | processHandRelease(xvel, yvel, isCloseBeforeDrag);
340 | for (SwipeListener l : mSwipeListeners) {
341 | l.onHandRelease(SwipeLayout.this, xvel, yvel);
342 | }
343 |
344 | invalidate();
345 | }
346 |
347 | @Override
348 | public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
349 | View surfaceView = getSurfaceView();
350 | if (surfaceView == null) return;
351 | View currentBottomView = getCurrentBottomView();
352 | int evLeft = surfaceView.getLeft(),
353 | evRight = surfaceView.getRight(),
354 | evTop = surfaceView.getTop(),
355 | evBottom = surfaceView.getBottom();
356 | if (changedView == surfaceView) {
357 |
358 | if (mShowMode == ShowMode.PullOut && currentBottomView != null) {
359 | if (mCurrentDragEdge == DragEdge.Left || mCurrentDragEdge == DragEdge.Right) {
360 | currentBottomView.offsetLeftAndRight(dx);
361 | } else {
362 | currentBottomView.offsetTopAndBottom(dy);
363 | }
364 | }
365 |
366 | } else if (getBottomViews().contains(changedView)) {
367 |
368 | if (mShowMode == ShowMode.PullOut) {
369 | surfaceView.offsetLeftAndRight(dx);
370 | surfaceView.offsetTopAndBottom(dy);
371 | } else {
372 | Rect rect = computeBottomLayDown(mCurrentDragEdge);
373 | if (currentBottomView != null) {
374 | currentBottomView.layout(rect.left, rect.top, rect.right, rect.bottom);
375 | }
376 |
377 | int newLeft = surfaceView.getLeft() + dx, newTop = surfaceView.getTop() + dy;
378 |
379 | if (mCurrentDragEdge == DragEdge.Left && newLeft < getPaddingLeft())
380 | newLeft = getPaddingLeft();
381 | else if (mCurrentDragEdge == DragEdge.Right && newLeft > getPaddingLeft())
382 | newLeft = getPaddingLeft();
383 | else if (mCurrentDragEdge == DragEdge.Top && newTop < getPaddingTop())
384 | newTop = getPaddingTop();
385 | else if (mCurrentDragEdge == DragEdge.Bottom && newTop > getPaddingTop())
386 | newTop = getPaddingTop();
387 |
388 | surfaceView.layout(newLeft, newTop, newLeft + getMeasuredWidth(), newTop + getMeasuredHeight());
389 | }
390 | }
391 |
392 | dispatchRevealEvent(evLeft, evTop, evRight, evBottom);
393 |
394 | dispatchSwipeEvent(evLeft, evTop, dx, dy);
395 |
396 | invalidate();
397 |
398 | captureChildrenBound();
399 | }
400 | };
401 |
402 | /**
403 | * save children's bounds, so they can restore the bound in {@link #onLayout(boolean, int, int, int, int)}
404 | */
405 | private void captureChildrenBound() {
406 | View currentBottomView = getCurrentBottomView();
407 | if (getOpenStatus() == Status.Close) {
408 | mViewBoundCache.remove(currentBottomView);
409 | return;
410 | }
411 |
412 | View[] views = new View[]{getSurfaceView(), currentBottomView};
413 | for (View child : views) {
414 | Rect rect = mViewBoundCache.get(child);
415 | if (rect == null) {
416 | rect = new Rect();
417 | mViewBoundCache.put(child, rect);
418 | }
419 | rect.left = child.getLeft();
420 | rect.top = child.getTop();
421 | rect.right = child.getRight();
422 | rect.bottom = child.getBottom();
423 | }
424 | }
425 |
426 | /**
427 | * the dispatchRevealEvent method may not always get accurate position, it
428 | * makes the view may not always get the event when the view is totally
429 | * show( fraction = 1), so , we need to calculate every time.
430 | */
431 | protected boolean isViewTotallyFirstShowed(View child, Rect relativePosition, DragEdge edge, int surfaceLeft,
432 | int surfaceTop, int surfaceRight, int surfaceBottom) {
433 | if (mShowEntirely.get(child)) return false;
434 | int childLeft = relativePosition.left;
435 | int childRight = relativePosition.right;
436 | int childTop = relativePosition.top;
437 | int childBottom = relativePosition.bottom;
438 | boolean r = false;
439 | if (getShowMode() == ShowMode.LayDown) {
440 | if ((edge == DragEdge.Right && surfaceRight <= childLeft)
441 | || (edge == DragEdge.Left && surfaceLeft >= childRight)
442 | || (edge == DragEdge.Top && surfaceTop >= childBottom)
443 | || (edge == DragEdge.Bottom && surfaceBottom <= childTop)) r = true;
444 | } else if (getShowMode() == ShowMode.PullOut) {
445 | if ((edge == DragEdge.Right && childRight <= getWidth())
446 | || (edge == DragEdge.Left && childLeft >= getPaddingLeft())
447 | || (edge == DragEdge.Top && childTop >= getPaddingTop())
448 | || (edge == DragEdge.Bottom && childBottom <= getHeight())) r = true;
449 | }
450 | return r;
451 | }
452 |
453 | protected boolean isViewShowing(View child, Rect relativePosition, DragEdge availableEdge, int surfaceLeft,
454 | int surfaceTop, int surfaceRight, int surfaceBottom) {
455 | int childLeft = relativePosition.left;
456 | int childRight = relativePosition.right;
457 | int childTop = relativePosition.top;
458 | int childBottom = relativePosition.bottom;
459 | if (getShowMode() == ShowMode.LayDown) {
460 | switch (availableEdge) {
461 | case Right:
462 | if (surfaceRight > childLeft && surfaceRight <= childRight) {
463 | return true;
464 | }
465 | break;
466 | case Left:
467 | if (surfaceLeft < childRight && surfaceLeft >= childLeft) {
468 | return true;
469 | }
470 | break;
471 | case Top:
472 | if (surfaceTop >= childTop && surfaceTop < childBottom) {
473 | return true;
474 | }
475 | break;
476 | case Bottom:
477 | if (surfaceBottom > childTop && surfaceBottom <= childBottom) {
478 | return true;
479 | }
480 | break;
481 | }
482 | } else if (getShowMode() == ShowMode.PullOut) {
483 | switch (availableEdge) {
484 | case Right:
485 | if (childLeft <= getWidth() && childRight > getWidth()) return true;
486 | break;
487 | case Left:
488 | if (childRight >= getPaddingLeft() && childLeft < getPaddingLeft()) return true;
489 | break;
490 | case Top:
491 | if (childTop < getPaddingTop() && childBottom >= getPaddingTop()) return true;
492 | break;
493 | case Bottom:
494 | if (childTop < getHeight() && childTop >= getPaddingTop()) return true;
495 | break;
496 | }
497 | }
498 | return false;
499 | }
500 |
501 | protected Rect getRelativePosition(View child) {
502 | View t = child;
503 | Rect r = new Rect(t.getLeft(), t.getTop(), 0, 0);
504 | while (t.getParent() != null && t != getRootView()) {
505 | t = (View) t.getParent();
506 | if (t == this) break;
507 | r.left += t.getLeft();
508 | r.top += t.getTop();
509 | }
510 | r.right = r.left + child.getMeasuredWidth();
511 | r.bottom = r.top + child.getMeasuredHeight();
512 | return r;
513 | }
514 |
515 | private int mEventCounter = 0;
516 |
517 | protected void dispatchSwipeEvent(int surfaceLeft, int surfaceTop, int dx, int dy) {
518 | DragEdge edge = getDragEdge();
519 | boolean open = true;
520 | if (edge == DragEdge.Left) {
521 | if (dx < 0) open = false;
522 | } else if (edge == DragEdge.Right) {
523 | if (dx > 0) open = false;
524 | } else if (edge == DragEdge.Top) {
525 | if (dy < 0) open = false;
526 | } else if (edge == DragEdge.Bottom) {
527 | if (dy > 0) open = false;
528 | }
529 |
530 | dispatchSwipeEvent(surfaceLeft, surfaceTop, open);
531 | }
532 |
533 | protected void dispatchSwipeEvent(int surfaceLeft, int surfaceTop, boolean open) {
534 | safeBottomView();
535 | Status status = getOpenStatus();
536 |
537 | if (!mSwipeListeners.isEmpty()) {
538 | mEventCounter++;
539 | for (SwipeListener l : mSwipeListeners) {
540 | if (mEventCounter == 1) {
541 | if (open) {
542 | l.onStartOpen(this);
543 | } else {
544 | l.onStartClose(this);
545 | }
546 | }
547 | l.onUpdate(SwipeLayout.this, surfaceLeft - getPaddingLeft(), surfaceTop - getPaddingTop());
548 | }
549 |
550 | if (status == Status.Close) {
551 | for (SwipeListener l : mSwipeListeners) {
552 | l.onClose(SwipeLayout.this);
553 | }
554 | mEventCounter = 0;
555 | }
556 |
557 | if (status == Status.Open) {
558 | View currentBottomView = getCurrentBottomView();
559 | if (currentBottomView != null) {
560 | currentBottomView.setEnabled(true);
561 | }
562 | for (SwipeListener l : mSwipeListeners) {
563 | l.onOpen(SwipeLayout.this);
564 | }
565 | mEventCounter = 0;
566 | }
567 | }
568 | }
569 |
570 | /**
571 | * prevent bottom view get any touch event. Especially in LayDown mode.
572 | */
573 | private void safeBottomView() {
574 | Status status = getOpenStatus();
575 | List bottoms = getBottomViews();
576 |
577 | if (status == Status.Close) {
578 | for (View bottom : bottoms) {
579 | if (bottom != null && bottom.getVisibility() != INVISIBLE) {
580 | bottom.setVisibility(INVISIBLE);
581 | }
582 | }
583 | } else {
584 | View currentBottomView = getCurrentBottomView();
585 | if (currentBottomView != null && currentBottomView.getVisibility() != VISIBLE) {
586 | currentBottomView.setVisibility(VISIBLE);
587 | }
588 | }
589 | }
590 |
591 | protected void dispatchRevealEvent(final int surfaceLeft, final int surfaceTop, final int surfaceRight,
592 | final int surfaceBottom) {
593 | if (mRevealListeners.isEmpty()) return;
594 | for (Map.Entry> entry : mRevealListeners.entrySet()) {
595 | View child = entry.getKey();
596 | Rect rect = getRelativePosition(child);
597 | if (isViewShowing(child, rect, mCurrentDragEdge, surfaceLeft, surfaceTop,
598 | surfaceRight, surfaceBottom)) {
599 | mShowEntirely.put(child, false);
600 | int distance = 0;
601 | float fraction = 0f;
602 | if (getShowMode() == ShowMode.LayDown) {
603 | switch (mCurrentDragEdge) {
604 | case Left:
605 | distance = rect.left - surfaceLeft;
606 | fraction = distance / (float) child.getWidth();
607 | break;
608 | case Right:
609 | distance = rect.right - surfaceRight;
610 | fraction = distance / (float) child.getWidth();
611 | break;
612 | case Top:
613 | distance = rect.top - surfaceTop;
614 | fraction = distance / (float) child.getHeight();
615 | break;
616 | case Bottom:
617 | distance = rect.bottom - surfaceBottom;
618 | fraction = distance / (float) child.getHeight();
619 | break;
620 | }
621 | } else if (getShowMode() == ShowMode.PullOut) {
622 | switch (mCurrentDragEdge) {
623 | case Left:
624 | distance = rect.right - getPaddingLeft();
625 | fraction = distance / (float) child.getWidth();
626 | break;
627 | case Right:
628 | distance = rect.left - getWidth();
629 | fraction = distance / (float) child.getWidth();
630 | break;
631 | case Top:
632 | distance = rect.bottom - getPaddingTop();
633 | fraction = distance / (float) child.getHeight();
634 | break;
635 | case Bottom:
636 | distance = rect.top - getHeight();
637 | fraction = distance / (float) child.getHeight();
638 | break;
639 | }
640 | }
641 |
642 | for (OnRevealListener l : entry.getValue()) {
643 | l.onReveal(child, mCurrentDragEdge, Math.abs(fraction), distance);
644 | if (Math.abs(fraction) == 1) {
645 | mShowEntirely.put(child, true);
646 | }
647 | }
648 | }
649 |
650 | if (isViewTotallyFirstShowed(child, rect, mCurrentDragEdge, surfaceLeft, surfaceTop,
651 | surfaceRight, surfaceBottom)) {
652 | mShowEntirely.put(child, true);
653 | for (OnRevealListener l : entry.getValue()) {
654 | if (mCurrentDragEdge == DragEdge.Left
655 | || mCurrentDragEdge == DragEdge.Right)
656 | l.onReveal(child, mCurrentDragEdge, 1, child.getWidth());
657 | else
658 | l.onReveal(child, mCurrentDragEdge, 1, child.getHeight());
659 | }
660 | }
661 |
662 | }
663 | }
664 |
665 | @Override
666 | public void computeScroll() {
667 | super.computeScroll();
668 | if (mDragHelper.continueSettling(true)) {
669 | ViewCompat.postInvalidateOnAnimation(this);
670 | }
671 | }
672 |
673 | /**
674 | * {@link android.view.View.OnLayoutChangeListener} added in API 11. I need
675 | * to support it from API 8.
676 | */
677 | public interface OnLayout {
678 | void onLayout(SwipeLayout v);
679 | }
680 |
681 | private List mOnLayoutListeners;
682 |
683 | public void addOnLayoutListener(OnLayout l) {
684 | if (mOnLayoutListeners == null) mOnLayoutListeners = new ArrayList();
685 | mOnLayoutListeners.add(l);
686 | }
687 |
688 | public void removeOnLayoutListener(OnLayout l) {
689 | if (mOnLayoutListeners != null) mOnLayoutListeners.remove(l);
690 | }
691 |
692 | public void clearDragEdge() {
693 | mDragEdges.clear();
694 | }
695 |
696 | public void setDrag(DragEdge dragEdge, int childId) {
697 | clearDragEdge();
698 | addDrag(dragEdge, childId);
699 | }
700 |
701 | public void setDrag(DragEdge dragEdge, View child) {
702 | clearDragEdge();
703 | addDrag(dragEdge, child);
704 | }
705 |
706 | public void addDrag(DragEdge dragEdge, int childId) {
707 | addDrag(dragEdge, findViewById(childId), null);
708 | }
709 |
710 | public void addDrag(DragEdge dragEdge, View child) {
711 | addDrag(dragEdge, child, null);
712 | }
713 |
714 | public void addDrag(DragEdge dragEdge, View child, ViewGroup.LayoutParams params) {
715 | if (child == null) return;
716 |
717 | if (params == null) {
718 | params = generateDefaultLayoutParams();
719 | }
720 | if (!checkLayoutParams(params)) {
721 | params = generateLayoutParams(params);
722 | }
723 | int gravity = -1;
724 | switch (dragEdge) {
725 | case Left:
726 | gravity = Gravity.LEFT;
727 | break;
728 | case Right:
729 | gravity = Gravity.RIGHT;
730 | break;
731 | case Top:
732 | gravity = Gravity.TOP;
733 | break;
734 | case Bottom:
735 | gravity = Gravity.BOTTOM;
736 | break;
737 | }
738 | if (params instanceof FrameLayout.LayoutParams) {
739 | ((LayoutParams) params).gravity = gravity;
740 | }
741 | addView(child, 0, params);
742 | }
743 |
744 | @Override
745 | public void addView(View child, int index, ViewGroup.LayoutParams params) {
746 | if (child == null) return;
747 | int gravity = Gravity.NO_GRAVITY;
748 | try {
749 | gravity = (Integer) params.getClass().getField("gravity").get(params);
750 | } catch (Exception e) {
751 | e.printStackTrace();
752 | }
753 |
754 | if (gravity > 0) {
755 | gravity = GravityCompat.getAbsoluteGravity(gravity, ViewCompat.getLayoutDirection(this));
756 |
757 | if ((gravity & Gravity.LEFT) == Gravity.LEFT) {
758 | mDragEdges.put(DragEdge.Left, child);
759 | }
760 | if ((gravity & Gravity.RIGHT) == Gravity.RIGHT) {
761 | mDragEdges.put(DragEdge.Right, child);
762 | }
763 | if ((gravity & Gravity.TOP) == Gravity.TOP) {
764 | mDragEdges.put(DragEdge.Top, child);
765 | }
766 | if ((gravity & Gravity.BOTTOM) == Gravity.BOTTOM) {
767 | mDragEdges.put(DragEdge.Bottom, child);
768 | }
769 | } else {
770 | for (Map.Entry entry : mDragEdges.entrySet()) {
771 | if (entry.getValue() == null) {
772 | //means used the drag_edge attr, the no gravity child should be use set
773 | mDragEdges.put(entry.getKey(), child);
774 | break;
775 | }
776 | }
777 | }
778 | if (child.getParent() == this) {
779 | return;
780 | }
781 | super.addView(child, index, params);
782 | }
783 |
784 | @Override
785 | protected void onLayout(boolean changed, int l, int t, int r, int b) {
786 | updateBottomViews();
787 |
788 | if (mOnLayoutListeners != null) for (int i = 0; i < mOnLayoutListeners.size(); i++) {
789 | mOnLayoutListeners.get(i).onLayout(this);
790 | }
791 | }
792 |
793 | void layoutPullOut() {
794 | View surfaceView = getSurfaceView();
795 | Rect surfaceRect = mViewBoundCache.get(surfaceView);
796 | if (surfaceRect == null) surfaceRect = computeSurfaceLayoutArea(false);
797 | if (surfaceView != null) {
798 | surfaceView.layout(surfaceRect.left, surfaceRect.top, surfaceRect.right, surfaceRect.bottom);
799 | bringChildToFront(surfaceView);
800 | }
801 | View currentBottomView = getCurrentBottomView();
802 | Rect bottomViewRect = mViewBoundCache.get(currentBottomView);
803 | if (bottomViewRect == null)
804 | bottomViewRect = computeBottomLayoutAreaViaSurface(ShowMode.PullOut, surfaceRect);
805 | if (currentBottomView != null) {
806 | currentBottomView.layout(bottomViewRect.left, bottomViewRect.top, bottomViewRect.right, bottomViewRect.bottom);
807 | }
808 | }
809 |
810 | void layoutLayDown() {
811 | View surfaceView = getSurfaceView();
812 | Rect surfaceRect = mViewBoundCache.get(surfaceView);
813 | if (surfaceRect == null) surfaceRect = computeSurfaceLayoutArea(false);
814 | if (surfaceView != null) {
815 | surfaceView.layout(surfaceRect.left, surfaceRect.top, surfaceRect.right, surfaceRect.bottom);
816 | bringChildToFront(surfaceView);
817 | }
818 | View currentBottomView = getCurrentBottomView();
819 | Rect bottomViewRect = mViewBoundCache.get(currentBottomView);
820 | if (bottomViewRect == null)
821 | bottomViewRect = computeBottomLayoutAreaViaSurface(ShowMode.LayDown, surfaceRect);
822 | if (currentBottomView != null) {
823 | currentBottomView.layout(bottomViewRect.left, bottomViewRect.top, bottomViewRect.right, bottomViewRect.bottom);
824 | }
825 | }
826 |
827 | private boolean mIsBeingDragged;
828 |
829 | private void checkCanDrag(MotionEvent ev) {
830 | if (mIsBeingDragged) return;
831 | if (getOpenStatus() == Status.Middle) {
832 | mIsBeingDragged = true;
833 | return;
834 | }
835 | Status status = getOpenStatus();
836 | float distanceX = ev.getRawX() - sX;
837 | float distanceY = ev.getRawY() - sY;
838 | float angle = Math.abs(distanceY / distanceX);
839 | angle = (float) Math.toDegrees(Math.atan(angle));
840 | if (getOpenStatus() == Status.Close) {
841 | DragEdge dragEdge;
842 | if (angle < 45) {
843 | if (distanceX > 0 && isLeftSwipeEnabled()) {
844 | dragEdge = DragEdge.Left;
845 | } else if (distanceX < 0 && isRightSwipeEnabled()) {
846 | dragEdge = DragEdge.Right;
847 | } else return;
848 |
849 | } else {
850 | if (distanceY > 0 && isTopSwipeEnabled()) {
851 | dragEdge = DragEdge.Top;
852 | } else if (distanceY < 0 && isBottomSwipeEnabled()) {
853 | dragEdge = DragEdge.Bottom;
854 | } else return;
855 | }
856 | setCurrentDragEdge(dragEdge);
857 | }
858 |
859 | boolean doNothing = false;
860 | if (mCurrentDragEdge == DragEdge.Right) {
861 | boolean suitable = (status == Status.Open && distanceX > mTouchSlop)
862 | || (status == Status.Close && distanceX < -mTouchSlop);
863 | suitable = suitable || (status == Status.Middle);
864 |
865 | if (angle > 30 || !suitable) {
866 | doNothing = true;
867 | }
868 | }
869 |
870 | if (mCurrentDragEdge == DragEdge.Left) {
871 | boolean suitable = (status == Status.Open && distanceX < -mTouchSlop)
872 | || (status == Status.Close && distanceX > mTouchSlop);
873 | suitable = suitable || status == Status.Middle;
874 |
875 | if (angle > 30 || !suitable) {
876 | doNothing = true;
877 | }
878 | }
879 |
880 | if (mCurrentDragEdge == DragEdge.Top) {
881 | boolean suitable = (status == Status.Open && distanceY < -mTouchSlop)
882 | || (status == Status.Close && distanceY > mTouchSlop);
883 | suitable = suitable || status == Status.Middle;
884 |
885 | if (angle < 60 || !suitable) {
886 | doNothing = true;
887 | }
888 | }
889 |
890 | if (mCurrentDragEdge == DragEdge.Bottom) {
891 | boolean suitable = (status == Status.Open && distanceY > mTouchSlop)
892 | || (status == Status.Close && distanceY < -mTouchSlop);
893 | suitable = suitable || status == Status.Middle;
894 |
895 | if (angle < 60 || !suitable) {
896 | doNothing = true;
897 | }
898 | }
899 | mIsBeingDragged = !doNothing;
900 | }
901 |
902 | @Override
903 | public boolean onInterceptTouchEvent(MotionEvent ev) {
904 | if (!isSwipeEnabled()) {
905 | return false;
906 | }
907 | if (mClickToClose && getOpenStatus() == Status.Open && isTouchOnSurface(ev)) {
908 | return true;
909 | }
910 | for (SwipeDenier denier : mSwipeDeniers) {
911 | if (denier != null && denier.shouldDenySwipe(ev)) {
912 | return false;
913 | }
914 | }
915 |
916 | switch (ev.getAction()) {
917 | case MotionEvent.ACTION_DOWN:
918 | mDragHelper.processTouchEvent(ev);
919 | mIsBeingDragged = false;
920 | sX = ev.getRawX();
921 | sY = ev.getRawY();
922 | //if the swipe is in middle state(scrolling), should intercept the touch
923 | if (getOpenStatus() == Status.Middle) {
924 | mIsBeingDragged = true;
925 | }
926 | break;
927 | case MotionEvent.ACTION_MOVE:
928 | boolean beforeCheck = mIsBeingDragged;
929 | checkCanDrag(ev);
930 | if (mIsBeingDragged) {
931 | ViewParent parent = getParent();
932 | if (parent != null) {
933 | parent.requestDisallowInterceptTouchEvent(true);
934 | }
935 | }
936 | if (!beforeCheck && mIsBeingDragged) {
937 | //let children has one chance to catch the touch, and request the swipe not intercept
938 | //useful when swipeLayout wrap a swipeLayout or other gestural layout
939 | return false;
940 | }
941 | break;
942 |
943 | case MotionEvent.ACTION_CANCEL:
944 | case MotionEvent.ACTION_UP:
945 | mIsBeingDragged = false;
946 | mDragHelper.processTouchEvent(ev);
947 | break;
948 | default://handle other action, such as ACTION_POINTER_DOWN/UP
949 | mDragHelper.processTouchEvent(ev);
950 | }
951 | return mIsBeingDragged;
952 | }
953 |
954 | private float sX = -1, sY = -1;
955 |
956 | @Override
957 | public boolean onTouchEvent(MotionEvent event) {
958 | if (!isSwipeEnabled()) return super.onTouchEvent(event);
959 |
960 | int action = event.getActionMasked();
961 | gestureDetector.onTouchEvent(event);
962 |
963 | switch (action) {
964 | case MotionEvent.ACTION_DOWN:
965 | mDragHelper.processTouchEvent(event);
966 | sX = event.getRawX();
967 | sY = event.getRawY();
968 |
969 |
970 | case MotionEvent.ACTION_MOVE: {
971 | //the drag state and the direction are already judged at onInterceptTouchEvent
972 | checkCanDrag(event);
973 | if (mIsBeingDragged) {
974 | getParent().requestDisallowInterceptTouchEvent(true);
975 | mDragHelper.processTouchEvent(event);
976 | }
977 | break;
978 | }
979 | case MotionEvent.ACTION_UP:
980 | case MotionEvent.ACTION_CANCEL:
981 | mIsBeingDragged = false;
982 | mDragHelper.processTouchEvent(event);
983 | break;
984 |
985 | default://handle other action, such as ACTION_POINTER_DOWN/UP
986 | mDragHelper.processTouchEvent(event);
987 | }
988 |
989 | return super.onTouchEvent(event) || mIsBeingDragged || action == MotionEvent.ACTION_DOWN;
990 | }
991 |
992 | public boolean isClickToClose() {
993 | return mClickToClose;
994 | }
995 |
996 | public void setClickToClose(boolean mClickToClose) {
997 | this.mClickToClose = mClickToClose;
998 | }
999 |
1000 | public void setSwipeEnabled(boolean enabled) {
1001 | mSwipeEnabled = enabled;
1002 | }
1003 |
1004 | public boolean isSwipeEnabled() {
1005 | return mSwipeEnabled;
1006 | }
1007 |
1008 | public boolean isLeftSwipeEnabled() {
1009 | View bottomView = mDragEdges.get(DragEdge.Left);
1010 | return bottomView != null && bottomView.getParent() == this
1011 | && bottomView != getSurfaceView() && mSwipesEnabled[DragEdge.Left.ordinal()];
1012 | }
1013 |
1014 | public void setLeftSwipeEnabled(boolean leftSwipeEnabled) {
1015 | this.mSwipesEnabled[DragEdge.Left.ordinal()] = leftSwipeEnabled;
1016 | }
1017 |
1018 | public boolean isRightSwipeEnabled() {
1019 | View bottomView = mDragEdges.get(DragEdge.Right);
1020 | return bottomView != null && bottomView.getParent() == this
1021 | && bottomView != getSurfaceView() && mSwipesEnabled[DragEdge.Right.ordinal()];
1022 | }
1023 |
1024 | public void setRightSwipeEnabled(boolean rightSwipeEnabled) {
1025 | this.mSwipesEnabled[DragEdge.Right.ordinal()] = rightSwipeEnabled;
1026 | }
1027 |
1028 | public boolean isTopSwipeEnabled() {
1029 | View bottomView = mDragEdges.get(DragEdge.Top);
1030 | return bottomView != null && bottomView.getParent() == this
1031 | && bottomView != getSurfaceView() && mSwipesEnabled[DragEdge.Top.ordinal()];
1032 | }
1033 |
1034 | public void setTopSwipeEnabled(boolean topSwipeEnabled) {
1035 | this.mSwipesEnabled[DragEdge.Top.ordinal()] = topSwipeEnabled;
1036 | }
1037 |
1038 | public boolean isBottomSwipeEnabled() {
1039 | View bottomView = mDragEdges.get(DragEdge.Bottom);
1040 | return bottomView != null && bottomView.getParent() == this
1041 | && bottomView != getSurfaceView() && mSwipesEnabled[DragEdge.Bottom.ordinal()];
1042 | }
1043 |
1044 | public void setBottomSwipeEnabled(boolean bottomSwipeEnabled) {
1045 | this.mSwipesEnabled[DragEdge.Bottom.ordinal()] = bottomSwipeEnabled;
1046 | }
1047 |
1048 | /***
1049 | * Returns the percentage of revealing at which the view below should the view finish opening
1050 | * if it was already open before dragging
1051 | *
1052 | * @returns The percentage of view revealed to trigger, default value is 0.25
1053 | */
1054 | public float getWillOpenPercentAfterOpen() {
1055 | return mWillOpenPercentAfterOpen;
1056 | }
1057 |
1058 | /***
1059 | * Allows to stablish at what percentage of revealing the view below should the view finish opening
1060 | * if it was already open before dragging
1061 | *
1062 | * @param willOpenPercentAfterOpen The percentage of view revealed to trigger, default value is 0.25
1063 | */
1064 | public void setWillOpenPercentAfterOpen(float willOpenPercentAfterOpen) {
1065 | this.mWillOpenPercentAfterOpen = willOpenPercentAfterOpen;
1066 | }
1067 |
1068 | /***
1069 | * Returns the percentage of revealing at which the view below should the view finish opening
1070 | * if it was already closed before dragging
1071 | *
1072 | * @returns The percentage of view revealed to trigger, default value is 0.25
1073 | */
1074 | public float getWillOpenPercentAfterClose() {
1075 | return mWillOpenPercentAfterClose;
1076 | }
1077 |
1078 | /***
1079 | * Allows to stablish at what percentage of revealing the view below should the view finish opening
1080 | * if it was already closed before dragging
1081 | *
1082 | * @param willOpenPercentAfterClose The percentage of view revealed to trigger, default value is 0.75
1083 | */
1084 | public void setWillOpenPercentAfterClose(float willOpenPercentAfterClose) {
1085 | this.mWillOpenPercentAfterClose = willOpenPercentAfterClose;
1086 | }
1087 |
1088 | private boolean insideAdapterView() {
1089 | return getAdapterView() != null;
1090 | }
1091 |
1092 | private AdapterView getAdapterView() {
1093 | ViewParent t = getParent();
1094 | if (t instanceof AdapterView) {
1095 | return (AdapterView) t;
1096 | }
1097 | return null;
1098 | }
1099 |
1100 | private void performAdapterViewItemClick() {
1101 | if (getOpenStatus() != Status.Close) return;
1102 | ViewParent t = getParent();
1103 | if (t instanceof AdapterView) {
1104 | AdapterView view = (AdapterView) t;
1105 | int p = view.getPositionForView(SwipeLayout.this);
1106 | if (p != AdapterView.INVALID_POSITION) {
1107 | view.performItemClick(view.getChildAt(p - view.getFirstVisiblePosition()), p, view
1108 | .getAdapter().getItemId(p));
1109 | }
1110 | }
1111 | }
1112 |
1113 | private boolean performAdapterViewItemLongClick() {
1114 | if (getOpenStatus() != Status.Close) return false;
1115 | ViewParent t = getParent();
1116 | if (t instanceof AdapterView) {
1117 | AdapterView view = (AdapterView) t;
1118 | int p = view.getPositionForView(SwipeLayout.this);
1119 | if (p == AdapterView.INVALID_POSITION) return false;
1120 | long vId = view.getItemIdAtPosition(p);
1121 | boolean handled = false;
1122 | try {
1123 | Method m = AbsListView.class.getDeclaredMethod("performLongPress", View.class, int.class, long.class);
1124 | m.setAccessible(true);
1125 | handled = (boolean) m.invoke(view, SwipeLayout.this, p, vId);
1126 |
1127 | } catch (Exception e) {
1128 | e.printStackTrace();
1129 |
1130 | if (view.getOnItemLongClickListener() != null) {
1131 | handled = view.getOnItemLongClickListener().onItemLongClick(view, SwipeLayout.this, p, vId);
1132 | }
1133 | if (handled) {
1134 | view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
1135 | }
1136 | }
1137 | return handled;
1138 | }
1139 | return false;
1140 | }
1141 |
1142 | @Override
1143 | protected void onAttachedToWindow() {
1144 | super.onAttachedToWindow();
1145 | if (insideAdapterView()) {
1146 | if (clickListener == null) {
1147 | setOnClickListener(new OnClickListener() {
1148 | @Override
1149 | public void onClick(View v) {
1150 | performAdapterViewItemClick();
1151 | }
1152 | });
1153 | }
1154 | if (longClickListener == null) {
1155 | setOnLongClickListener(new OnLongClickListener() {
1156 | @Override
1157 | public boolean onLongClick(View v) {
1158 | performAdapterViewItemLongClick();
1159 | return true;
1160 | }
1161 | });
1162 | }
1163 | }
1164 | }
1165 |
1166 | OnClickListener clickListener;
1167 |
1168 | @Override
1169 | public void setOnClickListener(OnClickListener l) {
1170 | super.setOnClickListener(l);
1171 | clickListener = l;
1172 | }
1173 |
1174 | OnLongClickListener longClickListener;
1175 |
1176 | @Override
1177 | public void setOnLongClickListener(OnLongClickListener l) {
1178 | super.setOnLongClickListener(l);
1179 | longClickListener = l;
1180 | }
1181 |
1182 | private Rect hitSurfaceRect;
1183 |
1184 | private boolean isTouchOnSurface(MotionEvent ev) {
1185 | View surfaceView = getSurfaceView();
1186 | if (surfaceView == null) {
1187 | return false;
1188 | }
1189 | if (hitSurfaceRect == null) {
1190 | hitSurfaceRect = new Rect();
1191 | }
1192 | surfaceView.getHitRect(hitSurfaceRect);
1193 | return hitSurfaceRect.contains((int) ev.getX(), (int) ev.getY());
1194 | }
1195 |
1196 | private GestureDetector gestureDetector = new GestureDetector(getContext(), new SwipeDetector());
1197 |
1198 | class SwipeDetector extends GestureDetector.SimpleOnGestureListener {
1199 | @Override
1200 | public boolean onSingleTapUp(MotionEvent e) {
1201 | if (mClickToClose && isTouchOnSurface(e)) {
1202 | close();
1203 | }
1204 | return super.onSingleTapUp(e);
1205 | }
1206 |
1207 | @Override
1208 | public boolean onDoubleTap(MotionEvent e) {
1209 | if (mDoubleClickListener != null) {
1210 | View target;
1211 | View bottom = getCurrentBottomView();
1212 | View surface = getSurfaceView();
1213 | if (bottom != null && e.getX() > bottom.getLeft() && e.getX() < bottom.getRight()
1214 | && e.getY() > bottom.getTop() && e.getY() < bottom.getBottom()) {
1215 | target = bottom;
1216 | } else {
1217 | target = surface;
1218 | }
1219 | mDoubleClickListener.onDoubleClick(SwipeLayout.this, target == surface);
1220 | }
1221 | return true;
1222 | }
1223 | }
1224 |
1225 | /**
1226 | * set the drag distance, it will force set the bottom view's width or
1227 | * height via this value.
1228 | *
1229 | * @param max max distance in dp unit
1230 | */
1231 | public void setDragDistance(int max) {
1232 | if (max < 0) max = 0;
1233 | mDragDistance = dp2px(max);
1234 | requestLayout();
1235 | }
1236 |
1237 | /**
1238 | * There are 2 diffirent show mode.
1239 | * {@link com.daimajia.swipe.SwipeLayout.ShowMode}.PullOut and
1240 | * {@link com.daimajia.swipe.SwipeLayout.ShowMode}.LayDown.
1241 | *
1242 | * @param mode
1243 | */
1244 | public void setShowMode(ShowMode mode) {
1245 | mShowMode = mode;
1246 | requestLayout();
1247 | }
1248 |
1249 | public DragEdge getDragEdge() {
1250 | return mCurrentDragEdge;
1251 | }
1252 |
1253 | public int getDragDistance() {
1254 | return mDragDistance;
1255 | }
1256 |
1257 | public ShowMode getShowMode() {
1258 | return mShowMode;
1259 | }
1260 |
1261 | /**
1262 | * return null if there is no surface view(no children)
1263 | */
1264 | public View getSurfaceView() {
1265 | if (getChildCount() == 0) return null;
1266 | return getChildAt(getChildCount() - 1);
1267 | }
1268 |
1269 | /**
1270 | * return null if there is no bottom view
1271 | */
1272 | public View getCurrentBottomView() {
1273 | List bottoms = getBottomViews();
1274 | if (mCurrentDragEdge.ordinal() < bottoms.size()) {
1275 | return bottoms.get(mCurrentDragEdge.ordinal());
1276 | }
1277 | return null;
1278 | }
1279 |
1280 | /**
1281 | * @return all bottomViews: left, top, right, bottom (may null if the edge is not set)
1282 | */
1283 | public List getBottomViews() {
1284 | ArrayList bottoms = new ArrayList();
1285 | for (DragEdge dragEdge : DragEdge.values()) {
1286 | bottoms.add(mDragEdges.get(dragEdge));
1287 | }
1288 | return bottoms;
1289 | }
1290 |
1291 | public enum Status {
1292 | Middle,
1293 | Open,
1294 | Close
1295 | }
1296 |
1297 | /**
1298 | * get the open status.
1299 | *
1300 | * @return {@link com.daimajia.swipe.SwipeLayout.Status} Open , Close or
1301 | * Middle.
1302 | */
1303 | public Status getOpenStatus() {
1304 | View surfaceView = getSurfaceView();
1305 | if (surfaceView == null) {
1306 | return Status.Close;
1307 | }
1308 | int surfaceLeft = surfaceView.getLeft();
1309 | int surfaceTop = surfaceView.getTop();
1310 | if (surfaceLeft == getPaddingLeft() && surfaceTop == getPaddingTop()) return Status.Close;
1311 |
1312 | if (surfaceLeft == (getPaddingLeft() - mDragDistance) || surfaceLeft == (getPaddingLeft() + mDragDistance)
1313 | || surfaceTop == (getPaddingTop() - mDragDistance) || surfaceTop == (getPaddingTop() + mDragDistance))
1314 | return Status.Open;
1315 |
1316 | return Status.Middle;
1317 | }
1318 |
1319 |
1320 | /**
1321 | * Process the surface release event.
1322 | *
1323 | * @param xvel xVelocity
1324 | * @param yvel yVelocity
1325 | * @param isCloseBeforeDragged the open state before drag
1326 | */
1327 | protected void processHandRelease(float xvel, float yvel, boolean isCloseBeforeDragged) {
1328 | float minVelocity = mDragHelper.getMinVelocity();
1329 | View surfaceView = getSurfaceView();
1330 | DragEdge currentDragEdge = mCurrentDragEdge;
1331 | if (currentDragEdge == null || surfaceView == null) {
1332 | return;
1333 | }
1334 | float willOpenPercent = (isCloseBeforeDragged ? mWillOpenPercentAfterClose : mWillOpenPercentAfterOpen);
1335 | if (currentDragEdge == DragEdge.Left) {
1336 | if (xvel > minVelocity) open();
1337 | else if (xvel < -minVelocity) close();
1338 | else {
1339 | float openPercent = 1f * getSurfaceView().getLeft() / mDragDistance;
1340 | if (openPercent > willOpenPercent) open();
1341 | else close();
1342 | }
1343 | } else if (currentDragEdge == DragEdge.Right) {
1344 | if (xvel > minVelocity) close();
1345 | else if (xvel < -minVelocity) open();
1346 | else {
1347 | float openPercent = 1f * (-getSurfaceView().getLeft()) / mDragDistance;
1348 | if (openPercent > willOpenPercent) open();
1349 | else close();
1350 | }
1351 | } else if (currentDragEdge == DragEdge.Top) {
1352 | if (yvel > minVelocity) open();
1353 | else if (yvel < -minVelocity) close();
1354 | else {
1355 | float openPercent = 1f * getSurfaceView().getTop() / mDragDistance;
1356 | if (openPercent > willOpenPercent) open();
1357 | else close();
1358 | }
1359 | } else if (currentDragEdge == DragEdge.Bottom) {
1360 | if (yvel > minVelocity) close();
1361 | else if (yvel < -minVelocity) open();
1362 | else {
1363 | float openPercent = 1f * (-getSurfaceView().getTop()) / mDragDistance;
1364 | if (openPercent > willOpenPercent) open();
1365 | else close();
1366 | }
1367 | }
1368 | }
1369 |
1370 | /**
1371 | * smoothly open surface.
1372 | */
1373 | public void open() {
1374 | open(true, true);
1375 | }
1376 |
1377 | public void open(boolean smooth) {
1378 | open(smooth, true);
1379 | }
1380 |
1381 | public void open(boolean smooth, boolean notify) {
1382 | View surface = getSurfaceView(), bottom = getCurrentBottomView();
1383 | if (surface == null) {
1384 | return;
1385 | }
1386 | int dx, dy;
1387 | Rect rect = computeSurfaceLayoutArea(true);
1388 | if (smooth) {
1389 | mDragHelper.smoothSlideViewTo(surface, rect.left, rect.top);
1390 | } else {
1391 | dx = rect.left - surface.getLeft();
1392 | dy = rect.top - surface.getTop();
1393 | surface.layout(rect.left, rect.top, rect.right, rect.bottom);
1394 | if (getShowMode() == ShowMode.PullOut) {
1395 | Rect bRect = computeBottomLayoutAreaViaSurface(ShowMode.PullOut, rect);
1396 | if (bottom != null) {
1397 | bottom.layout(bRect.left, bRect.top, bRect.right, bRect.bottom);
1398 | }
1399 | }
1400 | if (notify) {
1401 | dispatchRevealEvent(rect.left, rect.top, rect.right, rect.bottom);
1402 | dispatchSwipeEvent(rect.left, rect.top, dx, dy);
1403 | } else {
1404 | safeBottomView();
1405 | }
1406 | }
1407 | invalidate();
1408 | }
1409 |
1410 | public void open(DragEdge edge) {
1411 | setCurrentDragEdge(edge);
1412 | open(true, true);
1413 | }
1414 |
1415 | public void open(boolean smooth, DragEdge edge) {
1416 | setCurrentDragEdge(edge);
1417 | open(smooth, true);
1418 | }
1419 |
1420 | public void open(boolean smooth, boolean notify, DragEdge edge) {
1421 | setCurrentDragEdge(edge);
1422 | open(smooth, notify);
1423 | }
1424 |
1425 | /**
1426 | * smoothly close surface.
1427 | */
1428 | public void close() {
1429 | close(true, true);
1430 | }
1431 |
1432 | public void close(boolean smooth) {
1433 | close(smooth, true);
1434 | }
1435 |
1436 | /**
1437 | * close surface
1438 | *
1439 | * @param smooth smoothly or not.
1440 | * @param notify if notify all the listeners.
1441 | */
1442 | public void close(boolean smooth, boolean notify) {
1443 | View surface = getSurfaceView();
1444 | if (surface == null) {
1445 | return;
1446 | }
1447 | int dx, dy;
1448 | if (smooth)
1449 | mDragHelper.smoothSlideViewTo(getSurfaceView(), getPaddingLeft(), getPaddingTop());
1450 | else {
1451 | Rect rect = computeSurfaceLayoutArea(false);
1452 | dx = rect.left - surface.getLeft();
1453 | dy = rect.top - surface.getTop();
1454 | surface.layout(rect.left, rect.top, rect.right, rect.bottom);
1455 | if (notify) {
1456 | dispatchRevealEvent(rect.left, rect.top, rect.right, rect.bottom);
1457 | dispatchSwipeEvent(rect.left, rect.top, dx, dy);
1458 | } else {
1459 | safeBottomView();
1460 | }
1461 | }
1462 | invalidate();
1463 | }
1464 |
1465 | public void toggle() {
1466 | toggle(true);
1467 | }
1468 |
1469 | public void toggle(boolean smooth) {
1470 | if (getOpenStatus() == Status.Open)
1471 | close(smooth);
1472 | else if (getOpenStatus() == Status.Close) open(smooth);
1473 | }
1474 |
1475 |
1476 | /**
1477 | * a helper function to compute the Rect area that surface will hold in.
1478 | *
1479 | * @param open open status or close status.
1480 | */
1481 | private Rect computeSurfaceLayoutArea(boolean open) {
1482 | int l = getPaddingLeft(), t = getPaddingTop();
1483 | if (open) {
1484 | if (mCurrentDragEdge == DragEdge.Left)
1485 | l = getPaddingLeft() + mDragDistance;
1486 | else if (mCurrentDragEdge == DragEdge.Right)
1487 | l = getPaddingLeft() - mDragDistance;
1488 | else if (mCurrentDragEdge == DragEdge.Top)
1489 | t = getPaddingTop() + mDragDistance;
1490 | else t = getPaddingTop() - mDragDistance;
1491 | }
1492 | return new Rect(l, t, l + getMeasuredWidth(), t + getMeasuredHeight());
1493 | }
1494 |
1495 | private Rect computeBottomLayoutAreaViaSurface(ShowMode mode, Rect surfaceArea) {
1496 | Rect rect = surfaceArea;
1497 | View bottomView = getCurrentBottomView();
1498 |
1499 | int bl = rect.left, bt = rect.top, br = rect.right, bb = rect.bottom;
1500 | if (mode == ShowMode.PullOut) {
1501 | if (mCurrentDragEdge == DragEdge.Left)
1502 | bl = rect.left - mDragDistance;
1503 | else if (mCurrentDragEdge == DragEdge.Right)
1504 | bl = rect.right;
1505 | else if (mCurrentDragEdge == DragEdge.Top)
1506 | bt = rect.top - mDragDistance;
1507 | else bt = rect.bottom;
1508 |
1509 | if (mCurrentDragEdge == DragEdge.Left || mCurrentDragEdge == DragEdge.Right) {
1510 | bb = rect.bottom;
1511 | br = bl + (bottomView == null ? 0 : bottomView.getMeasuredWidth());
1512 | } else {
1513 | bb = bt + (bottomView == null ? 0 : bottomView.getMeasuredHeight());
1514 | br = rect.right;
1515 | }
1516 | } else if (mode == ShowMode.LayDown) {
1517 | if (mCurrentDragEdge == DragEdge.Left)
1518 | br = bl + mDragDistance;
1519 | else if (mCurrentDragEdge == DragEdge.Right)
1520 | bl = br - mDragDistance;
1521 | else if (mCurrentDragEdge == DragEdge.Top)
1522 | bb = bt + mDragDistance;
1523 | else bt = bb - mDragDistance;
1524 |
1525 | }
1526 | return new Rect(bl, bt, br, bb);
1527 |
1528 | }
1529 |
1530 | private Rect computeBottomLayDown(DragEdge dragEdge) {
1531 | int bl = getPaddingLeft(), bt = getPaddingTop();
1532 | int br, bb;
1533 | if (dragEdge == DragEdge.Right) {
1534 | bl = getMeasuredWidth() - mDragDistance;
1535 | } else if (dragEdge == DragEdge.Bottom) {
1536 | bt = getMeasuredHeight() - mDragDistance;
1537 | }
1538 | if (dragEdge == DragEdge.Left || dragEdge == DragEdge.Right) {
1539 | br = bl + mDragDistance;
1540 | bb = bt + getMeasuredHeight();
1541 | } else {
1542 | br = bl + getMeasuredWidth();
1543 | bb = bt + mDragDistance;
1544 | }
1545 | return new Rect(bl, bt, br, bb);
1546 | }
1547 |
1548 | public void setOnDoubleClickListener(DoubleClickListener doubleClickListener) {
1549 | mDoubleClickListener = doubleClickListener;
1550 | }
1551 |
1552 | public interface DoubleClickListener {
1553 | void onDoubleClick(SwipeLayout layout, boolean surface);
1554 | }
1555 |
1556 | private int dp2px(float dp) {
1557 | return (int) (dp * getContext().getResources().getDisplayMetrics().density + 0.5f);
1558 | }
1559 |
1560 |
1561 | /**
1562 | * Deprecated, use {@link #setDrag(DragEdge, View)}
1563 | */
1564 | @Deprecated
1565 | public void setDragEdge(DragEdge dragEdge) {
1566 | clearDragEdge();
1567 | if (getChildCount() >= 2) {
1568 | mDragEdges.put(dragEdge, getChildAt(getChildCount() - 2));
1569 | }
1570 | setCurrentDragEdge(dragEdge);
1571 | }
1572 |
1573 | public void onViewRemoved(View child) {
1574 | for (Map.Entry entry : new HashMap(mDragEdges).entrySet()) {
1575 | if (entry.getValue() == child) {
1576 | mDragEdges.remove(entry.getKey());
1577 | }
1578 | }
1579 | }
1580 |
1581 | public Map getDragEdgeMap() {
1582 | return mDragEdges;
1583 | }
1584 |
1585 | /**
1586 | * Deprecated, use {@link #getDragEdgeMap()}
1587 | */
1588 | @Deprecated
1589 | public List getDragEdges() {
1590 | return new ArrayList(mDragEdges.keySet());
1591 | }
1592 |
1593 | /**
1594 | * Deprecated, use {@link #setDrag(DragEdge, View)}
1595 | */
1596 | @Deprecated
1597 | public void setDragEdges(List dragEdges) {
1598 | clearDragEdge();
1599 | for (int i = 0, size = Math.min(dragEdges.size(), getChildCount() - 1); i < size; i++) {
1600 | DragEdge dragEdge = dragEdges.get(i);
1601 | mDragEdges.put(dragEdge, getChildAt(i));
1602 | }
1603 | if (dragEdges.size() == 0 || dragEdges.contains(DefaultDragEdge)) {
1604 | setCurrentDragEdge(DefaultDragEdge);
1605 | } else {
1606 | setCurrentDragEdge(dragEdges.get(0));
1607 | }
1608 | }
1609 |
1610 | /**
1611 | * Deprecated, use {@link #addDrag(DragEdge, View)}
1612 | */
1613 | @Deprecated
1614 | public void setDragEdges(DragEdge... mDragEdges) {
1615 | clearDragEdge();
1616 | setDragEdges(Arrays.asList(mDragEdges));
1617 | }
1618 |
1619 | /**
1620 | * Deprecated, use {@link #addDrag(DragEdge, View)}
1621 | * When using multiple drag edges it's a good idea to pass the ids of the views that
1622 | * you're using for the left, right, top bottom views (-1 if you're not using a particular view)
1623 | */
1624 | @Deprecated
1625 | public void setBottomViewIds(int leftId, int rightId, int topId, int bottomId) {
1626 | addDrag(DragEdge.Left, findViewById(leftId));
1627 | addDrag(DragEdge.Right, findViewById(rightId));
1628 | addDrag(DragEdge.Top, findViewById(topId));
1629 | addDrag(DragEdge.Bottom, findViewById(bottomId));
1630 | }
1631 |
1632 | private float getCurrentOffset() {
1633 | if (mCurrentDragEdge == null) return 0;
1634 | return mEdgeSwipesOffset[mCurrentDragEdge.ordinal()];
1635 | }
1636 |
1637 | private void setCurrentDragEdge(DragEdge dragEdge) {
1638 | mCurrentDragEdge = dragEdge;
1639 | updateBottomViews();
1640 | }
1641 |
1642 | private void updateBottomViews() {
1643 | View currentBottomView = getCurrentBottomView();
1644 | if (currentBottomView != null) {
1645 | if (mCurrentDragEdge == DragEdge.Left || mCurrentDragEdge == DragEdge.Right) {
1646 | mDragDistance = currentBottomView.getMeasuredWidth() - dp2px(getCurrentOffset());
1647 | } else {
1648 | mDragDistance = currentBottomView.getMeasuredHeight() - dp2px(getCurrentOffset());
1649 | }
1650 | }
1651 |
1652 | if (mShowMode == ShowMode.PullOut) {
1653 | layoutPullOut();
1654 | } else if (mShowMode == ShowMode.LayDown) {
1655 | layoutLayDown();
1656 | }
1657 |
1658 | safeBottomView();
1659 | }
1660 | }
1661 |
--------------------------------------------------------------------------------
/library/src/main/java/com/daimajia/swipe/adapters/ArraySwipeAdapter.java:
--------------------------------------------------------------------------------
1 | package com.daimajia.swipe.adapters;
2 |
3 | import android.content.Context;
4 | import android.view.View;
5 | import android.view.ViewGroup;
6 | import android.widget.ArrayAdapter;
7 |
8 | import com.daimajia.swipe.SwipeLayout;
9 | import com.daimajia.swipe.implments.SwipeItemMangerImpl;
10 | import com.daimajia.swipe.interfaces.SwipeAdapterInterface;
11 | import com.daimajia.swipe.interfaces.SwipeItemMangerInterface;
12 | import com.daimajia.swipe.util.Attributes;
13 |
14 | import java.util.List;
15 |
16 | public abstract class ArraySwipeAdapter extends ArrayAdapter implements SwipeItemMangerInterface, SwipeAdapterInterface {
17 |
18 | private SwipeItemMangerImpl mItemManger = new SwipeItemMangerImpl(this);
19 | {}
20 | public ArraySwipeAdapter(Context context, int resource) {
21 | super(context, resource);
22 | }
23 |
24 | public ArraySwipeAdapter(Context context, int resource, int textViewResourceId) {
25 | super(context, resource, textViewResourceId);
26 | }
27 |
28 | public ArraySwipeAdapter(Context context, int resource, T[] objects) {
29 | super(context, resource, objects);
30 | }
31 |
32 | public ArraySwipeAdapter(Context context, int resource, int textViewResourceId, T[] objects) {
33 | super(context, resource, textViewResourceId, objects);
34 | }
35 |
36 | public ArraySwipeAdapter(Context context, int resource, List objects) {
37 | super(context, resource, objects);
38 | }
39 |
40 | public ArraySwipeAdapter(Context context, int resource, int textViewResourceId, List objects) {
41 | super(context, resource, textViewResourceId, objects);
42 | }
43 |
44 | @Override
45 | public void notifyDatasetChanged() {
46 | super.notifyDataSetChanged();
47 | }
48 |
49 | @Override
50 | public View getView(int position, View convertView, ViewGroup parent) {
51 | View v = super.getView(position, convertView, parent);
52 | mItemManger.bind(v, position);
53 | return v;
54 | }
55 |
56 | @Override
57 | public void openItem(int position) {
58 | mItemManger.openItem(position);
59 | }
60 |
61 | @Override
62 | public void closeItem(int position) {
63 | mItemManger.closeItem(position);
64 | }
65 |
66 | @Override
67 | public void closeAllExcept(SwipeLayout layout) {
68 | mItemManger.closeAllExcept(layout);
69 | }
70 |
71 | @Override
72 | public void closeAllItems() {
73 | mItemManger.closeAllItems();
74 | }
75 |
76 | @Override
77 | public List getOpenItems() {
78 | return mItemManger.getOpenItems();
79 | }
80 |
81 | @Override
82 | public List getOpenLayouts() {
83 | return mItemManger.getOpenLayouts();
84 | }
85 |
86 | @Override
87 | public void removeShownLayouts(SwipeLayout layout) {
88 | mItemManger.removeShownLayouts(layout);
89 | }
90 |
91 | @Override
92 | public boolean isOpen(int position) {
93 | return mItemManger.isOpen(position);
94 | }
95 |
96 | @Override
97 | public Attributes.Mode getMode() {
98 | return mItemManger.getMode();
99 | }
100 |
101 | @Override
102 | public void setMode(Attributes.Mode mode) {
103 | mItemManger.setMode(mode);
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/library/src/main/java/com/daimajia/swipe/adapters/BaseSwipeAdapter.java:
--------------------------------------------------------------------------------
1 | package com.daimajia.swipe.adapters;
2 |
3 | import android.view.View;
4 | import android.view.ViewGroup;
5 | import android.widget.BaseAdapter;
6 |
7 | import com.daimajia.swipe.SwipeLayout;
8 | import com.daimajia.swipe.implments.SwipeItemMangerImpl;
9 | import com.daimajia.swipe.interfaces.SwipeAdapterInterface;
10 | import com.daimajia.swipe.interfaces.SwipeItemMangerInterface;
11 | import com.daimajia.swipe.util.Attributes;
12 |
13 | import java.util.List;
14 |
15 | public abstract class BaseSwipeAdapter extends BaseAdapter implements SwipeItemMangerInterface, SwipeAdapterInterface {
16 |
17 | protected SwipeItemMangerImpl mItemManger = new SwipeItemMangerImpl(this);
18 |
19 | /**
20 | * return the {@link com.daimajia.swipe.SwipeLayout} resource id, int the view item.
21 | * @param position
22 | * @return
23 | */
24 | public abstract int getSwipeLayoutResourceId(int position);
25 |
26 | /**
27 | * generate a new view item.
28 | * Never bind SwipeListener or fill values here, every item has a chance to fill value or bind
29 | * listeners in fillValues.
30 | * to fill it in {@code fillValues} method.
31 | * @param position
32 | * @param parent
33 | * @return
34 | */
35 | public abstract View generateView(int position, ViewGroup parent);
36 |
37 | /**
38 | * fill values or bind listeners to the view.
39 | * @param position
40 | * @param convertView
41 | */
42 | public abstract void fillValues(int position, View convertView);
43 |
44 | @Override
45 | public void notifyDatasetChanged() {
46 | super.notifyDataSetChanged();
47 | }
48 |
49 |
50 | @Override
51 | public final View getView(int position, View convertView, ViewGroup parent) {
52 | View v = convertView;
53 | if(v == null){
54 | v = generateView(position, parent);
55 | }
56 | mItemManger.bind(v, position);
57 | fillValues(position, v);
58 | return v;
59 | }
60 |
61 | @Override
62 | public void openItem(int position) {
63 | mItemManger.openItem(position);
64 | }
65 |
66 | @Override
67 | public void closeItem(int position) {
68 | mItemManger.closeItem(position);
69 | }
70 |
71 | @Override
72 | public void closeAllExcept(SwipeLayout layout) {
73 | mItemManger.closeAllExcept(layout);
74 | }
75 |
76 | @Override
77 | public void closeAllItems() {
78 | mItemManger.closeAllItems();
79 | }
80 |
81 | @Override
82 | public List getOpenItems() {
83 | return mItemManger.getOpenItems();
84 | }
85 |
86 | @Override
87 | public List getOpenLayouts() {
88 | return mItemManger.getOpenLayouts();
89 | }
90 |
91 | @Override
92 | public void removeShownLayouts(SwipeLayout layout) {
93 | mItemManger.removeShownLayouts(layout);
94 | }
95 |
96 | @Override
97 | public boolean isOpen(int position) {
98 | return mItemManger.isOpen(position);
99 | }
100 |
101 | @Override
102 | public Attributes.Mode getMode() {
103 | return mItemManger.getMode();
104 | }
105 |
106 | @Override
107 | public void setMode(Attributes.Mode mode) {
108 | mItemManger.setMode(mode);
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/library/src/main/java/com/daimajia/swipe/adapters/CursorSwipeAdapter.java:
--------------------------------------------------------------------------------
1 | package com.daimajia.swipe.adapters;
2 |
3 | import android.content.Context;
4 | import android.database.Cursor;
5 | import android.support.v4.widget.CursorAdapter;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 |
9 | import com.daimajia.swipe.SwipeLayout;
10 | import com.daimajia.swipe.implments.SwipeItemMangerImpl;
11 | import com.daimajia.swipe.interfaces.SwipeAdapterInterface;
12 | import com.daimajia.swipe.interfaces.SwipeItemMangerInterface;
13 | import com.daimajia.swipe.util.Attributes;
14 |
15 | import java.util.List;
16 |
17 | public abstract class CursorSwipeAdapter extends CursorAdapter implements SwipeItemMangerInterface, SwipeAdapterInterface {
18 |
19 | private SwipeItemMangerImpl mItemManger = new SwipeItemMangerImpl(this);
20 |
21 | protected CursorSwipeAdapter(Context context, Cursor c, boolean autoRequery) {
22 | super(context, c, autoRequery);
23 | }
24 |
25 | protected CursorSwipeAdapter(Context context, Cursor c, int flags) {
26 | super(context, c, flags);
27 | }
28 |
29 | @Override
30 | public View getView(int position, View convertView, ViewGroup parent) {
31 | View v = super.getView(position, convertView, parent);
32 | mItemManger.bind(v, position);
33 | return v;
34 | }
35 |
36 | @Override
37 | public void openItem(int position) {
38 | mItemManger.openItem(position);
39 | }
40 |
41 | @Override
42 | public void closeItem(int position) {
43 | mItemManger.closeItem(position);
44 | }
45 |
46 | @Override
47 | public void closeAllExcept(SwipeLayout layout) {
48 | mItemManger.closeAllExcept(layout);
49 | }
50 |
51 | @Override
52 | public void closeAllItems() {
53 | mItemManger.closeAllItems();
54 | }
55 |
56 | @Override
57 | public List getOpenItems() {
58 | return mItemManger.getOpenItems();
59 | }
60 |
61 | @Override
62 | public List getOpenLayouts() {
63 | return mItemManger.getOpenLayouts();
64 | }
65 |
66 | @Override
67 | public void removeShownLayouts(SwipeLayout layout) {
68 | mItemManger.removeShownLayouts(layout);
69 | }
70 |
71 | @Override
72 | public boolean isOpen(int position) {
73 | return mItemManger.isOpen(position);
74 | }
75 |
76 | @Override
77 | public Attributes.Mode getMode() {
78 | return mItemManger.getMode();
79 | }
80 |
81 | @Override
82 | public void setMode(Attributes.Mode mode) {
83 | mItemManger.setMode(mode);
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/library/src/main/java/com/daimajia/swipe/adapters/RecyclerSwipeAdapter.java:
--------------------------------------------------------------------------------
1 | package com.daimajia.swipe.adapters;
2 |
3 | import android.support.v7.widget.RecyclerView;
4 | import android.view.ViewGroup;
5 |
6 | import com.daimajia.swipe.SwipeLayout;
7 | import com.daimajia.swipe.implments.SwipeItemMangerImpl;
8 | import com.daimajia.swipe.interfaces.SwipeAdapterInterface;
9 | import com.daimajia.swipe.interfaces.SwipeItemMangerInterface;
10 | import com.daimajia.swipe.util.Attributes;
11 |
12 | import java.util.List;
13 |
14 | public abstract class RecyclerSwipeAdapter extends RecyclerView.Adapter implements SwipeItemMangerInterface, SwipeAdapterInterface {
15 |
16 | public SwipeItemMangerImpl mItemManger = new SwipeItemMangerImpl(this);
17 |
18 | @Override
19 | public abstract VH onCreateViewHolder(ViewGroup parent, int viewType);
20 |
21 | @Override
22 | public abstract void onBindViewHolder(VH viewHolder, final int position);
23 |
24 | @Override
25 | public void notifyDatasetChanged() {
26 | super.notifyDataSetChanged();
27 | }
28 |
29 | @Override
30 | public void openItem(int position) {
31 | mItemManger.openItem(position);
32 | }
33 |
34 | @Override
35 | public void closeItem(int position) {
36 | mItemManger.closeItem(position);
37 | }
38 |
39 | @Override
40 | public void closeAllExcept(SwipeLayout layout) {
41 | mItemManger.closeAllExcept(layout);
42 | }
43 |
44 | @Override
45 | public void closeAllItems() {
46 | mItemManger.closeAllItems();
47 | }
48 |
49 | @Override
50 | public List getOpenItems() {
51 | return mItemManger.getOpenItems();
52 | }
53 |
54 | @Override
55 | public List getOpenLayouts() {
56 | return mItemManger.getOpenLayouts();
57 | }
58 |
59 | @Override
60 | public void removeShownLayouts(SwipeLayout layout) {
61 | mItemManger.removeShownLayouts(layout);
62 | }
63 |
64 | @Override
65 | public boolean isOpen(int position) {
66 | return mItemManger.isOpen(position);
67 | }
68 |
69 | @Override
70 | public Attributes.Mode getMode() {
71 | return mItemManger.getMode();
72 | }
73 |
74 | @Override
75 | public void setMode(Attributes.Mode mode) {
76 | mItemManger.setMode(mode);
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/library/src/main/java/com/daimajia/swipe/adapters/SimpleCursorSwipeAdapter.java:
--------------------------------------------------------------------------------
1 | package com.daimajia.swipe.adapters;
2 |
3 | import android.content.Context;
4 | import android.database.Cursor;
5 | import android.support.v4.widget.SimpleCursorAdapter;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 |
9 | import com.daimajia.swipe.SwipeLayout;
10 | import com.daimajia.swipe.implments.SwipeItemMangerImpl;
11 | import com.daimajia.swipe.interfaces.SwipeAdapterInterface;
12 | import com.daimajia.swipe.interfaces.SwipeItemMangerInterface;
13 | import com.daimajia.swipe.util.Attributes;
14 |
15 | import java.util.List;
16 |
17 | public abstract class SimpleCursorSwipeAdapter extends SimpleCursorAdapter implements SwipeItemMangerInterface, SwipeAdapterInterface {
18 |
19 | private SwipeItemMangerImpl mItemManger = new SwipeItemMangerImpl(this);
20 |
21 | protected SimpleCursorSwipeAdapter(Context context, int layout, Cursor c, String[] from, int[] to, int flags) {
22 | super(context, layout, c, from, to, flags);
23 | }
24 |
25 | protected SimpleCursorSwipeAdapter(Context context, int layout, Cursor c, String[] from, int[] to) {
26 | super(context, layout, c, from, to);
27 | }
28 |
29 | @Override
30 | public View getView(int position, View convertView, ViewGroup parent) {
31 | View v = super.getView(position, convertView, parent);
32 | mItemManger.bind(v, position);
33 | return v;
34 | }
35 |
36 | @Override
37 | public void openItem(int position) {
38 | mItemManger.openItem(position);
39 | }
40 |
41 | @Override
42 | public void closeItem(int position) {
43 | mItemManger.closeItem(position);
44 | }
45 |
46 | @Override
47 | public void closeAllExcept(SwipeLayout layout) {
48 | mItemManger.closeAllExcept(layout);
49 | }
50 |
51 | @Override
52 | public List getOpenItems() {
53 | return mItemManger.getOpenItems();
54 | }
55 |
56 | @Override
57 | public List getOpenLayouts() {
58 | return mItemManger.getOpenLayouts();
59 | }
60 |
61 | @Override
62 | public void removeShownLayouts(SwipeLayout layout) {
63 | mItemManger.removeShownLayouts(layout);
64 | }
65 |
66 | @Override
67 | public boolean isOpen(int position) {
68 | return mItemManger.isOpen(position);
69 | }
70 |
71 | @Override
72 | public Attributes.Mode getMode() {
73 | return mItemManger.getMode();
74 | }
75 |
76 | @Override
77 | public void setMode(Attributes.Mode mode) {
78 | mItemManger.setMode(mode);
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/library/src/main/java/com/daimajia/swipe/implments/SwipeItemMangerImpl.java:
--------------------------------------------------------------------------------
1 | package com.daimajia.swipe.implments;
2 |
3 | import android.view.View;
4 |
5 | import com.daimajia.swipe.SimpleSwipeListener;
6 | import com.daimajia.swipe.SwipeLayout;
7 | import com.daimajia.swipe.interfaces.SwipeAdapterInterface;
8 | import com.daimajia.swipe.interfaces.SwipeItemMangerInterface;
9 | import com.daimajia.swipe.util.Attributes;
10 |
11 | import java.util.ArrayList;
12 | import java.util.Collections;
13 | import java.util.HashSet;
14 | import java.util.List;
15 | import java.util.Set;
16 |
17 | /**
18 | * SwipeItemMangerImpl is a helper class to help all the adapters to maintain open status.
19 | */
20 | public class SwipeItemMangerImpl implements SwipeItemMangerInterface {
21 |
22 | private Attributes.Mode mode = Attributes.Mode.Single;
23 | public final int INVALID_POSITION = -1;
24 |
25 | protected int mOpenPosition = INVALID_POSITION;
26 |
27 | protected Set mOpenPositions = new HashSet();
28 | protected Set mShownLayouts = new HashSet();
29 |
30 | protected SwipeAdapterInterface swipeAdapterInterface;
31 |
32 | public SwipeItemMangerImpl(SwipeAdapterInterface swipeAdapterInterface) {
33 | if (swipeAdapterInterface == null)
34 | throw new IllegalArgumentException("SwipeAdapterInterface can not be null");
35 |
36 | this.swipeAdapterInterface = swipeAdapterInterface;
37 | }
38 |
39 | public Attributes.Mode getMode() {
40 | return mode;
41 | }
42 |
43 | public void setMode(Attributes.Mode mode) {
44 | this.mode = mode;
45 | mOpenPositions.clear();
46 | mShownLayouts.clear();
47 | mOpenPosition = INVALID_POSITION;
48 | }
49 |
50 | public void bind(View view, int position) {
51 | int resId = swipeAdapterInterface.getSwipeLayoutResourceId(position);
52 | SwipeLayout swipeLayout = (SwipeLayout) view.findViewById(resId);
53 | if (swipeLayout == null)
54 | throw new IllegalStateException("can not find SwipeLayout in target view");
55 |
56 | if (swipeLayout.getTag(resId) == null) {
57 | OnLayoutListener onLayoutListener = new OnLayoutListener(position);
58 | SwipeMemory swipeMemory = new SwipeMemory(position);
59 | swipeLayout.addSwipeListener(swipeMemory);
60 | swipeLayout.addOnLayoutListener(onLayoutListener);
61 | swipeLayout.setTag(resId, new ValueBox(position, swipeMemory, onLayoutListener));
62 | mShownLayouts.add(swipeLayout);
63 | } else {
64 | ValueBox valueBox = (ValueBox) swipeLayout.getTag(resId);
65 | valueBox.swipeMemory.setPosition(position);
66 | valueBox.onLayoutListener.setPosition(position);
67 | valueBox.position = position;
68 | }
69 | }
70 |
71 | @Override
72 | public void openItem(int position) {
73 | if (mode == Attributes.Mode.Multiple) {
74 | if (!mOpenPositions.contains(position))
75 | mOpenPositions.add(position);
76 | } else {
77 | mOpenPosition = position;
78 | }
79 | swipeAdapterInterface.notifyDatasetChanged();
80 | }
81 |
82 | @Override
83 | public void closeItem(int position) {
84 | if (mode == Attributes.Mode.Multiple) {
85 | mOpenPositions.remove(position);
86 | } else {
87 | if (mOpenPosition == position)
88 | mOpenPosition = INVALID_POSITION;
89 | }
90 | swipeAdapterInterface.notifyDatasetChanged();
91 | }
92 |
93 | @Override
94 | public void closeAllExcept(SwipeLayout layout) {
95 | for (SwipeLayout s : mShownLayouts) {
96 | if (s != layout)
97 | s.close();
98 | }
99 | }
100 |
101 | @Override
102 | public void closeAllItems() {
103 | if (mode == Attributes.Mode.Multiple) {
104 | mOpenPositions.clear();
105 | } else {
106 | mOpenPosition = INVALID_POSITION;
107 | }
108 | for (SwipeLayout s : mShownLayouts) {
109 | s.close();
110 | }
111 | }
112 |
113 | @Override
114 | public void removeShownLayouts(SwipeLayout layout) {
115 | mShownLayouts.remove(layout);
116 | }
117 |
118 | @Override
119 | public List getOpenItems() {
120 | if (mode == Attributes.Mode.Multiple) {
121 | return new ArrayList(mOpenPositions);
122 | } else {
123 | return Collections.singletonList(mOpenPosition);
124 | }
125 | }
126 |
127 | @Override
128 | public List getOpenLayouts() {
129 | return new ArrayList(mShownLayouts);
130 | }
131 |
132 | @Override
133 | public boolean isOpen(int position) {
134 | if (mode == Attributes.Mode.Multiple) {
135 | return mOpenPositions.contains(position);
136 | } else {
137 | return mOpenPosition == position;
138 | }
139 | }
140 |
141 | class ValueBox {
142 | OnLayoutListener onLayoutListener;
143 | SwipeMemory swipeMemory;
144 | int position;
145 |
146 | ValueBox(int position, SwipeMemory swipeMemory, OnLayoutListener onLayoutListener) {
147 | this.swipeMemory = swipeMemory;
148 | this.onLayoutListener = onLayoutListener;
149 | this.position = position;
150 | }
151 | }
152 |
153 | class OnLayoutListener implements SwipeLayout.OnLayout {
154 |
155 | private int position;
156 |
157 | OnLayoutListener(int position) {
158 | this.position = position;
159 | }
160 |
161 | public void setPosition(int position) {
162 | this.position = position;
163 | }
164 |
165 | @Override
166 | public void onLayout(SwipeLayout v) {
167 | if (isOpen(position)) {
168 | v.open(false, false);
169 | } else {
170 | v.close(false, false);
171 | }
172 | }
173 |
174 | }
175 |
176 | class SwipeMemory extends SimpleSwipeListener {
177 |
178 | private int position;
179 |
180 | SwipeMemory(int position) {
181 | this.position = position;
182 | }
183 |
184 | @Override
185 | public void onClose(SwipeLayout layout) {
186 | if (mode == Attributes.Mode.Multiple) {
187 | mOpenPositions.remove(position);
188 | } else {
189 | mOpenPosition = INVALID_POSITION;
190 | }
191 | }
192 |
193 | @Override
194 | public void onStartOpen(SwipeLayout layout) {
195 | if (mode == Attributes.Mode.Single) {
196 | closeAllExcept(layout);
197 | }
198 | }
199 |
200 | @Override
201 | public void onOpen(SwipeLayout layout) {
202 | if (mode == Attributes.Mode.Multiple)
203 | mOpenPositions.add(position);
204 | else {
205 | closeAllExcept(layout);
206 | mOpenPosition = position;
207 | }
208 | }
209 |
210 | public void setPosition(int position) {
211 | this.position = position;
212 | }
213 | }
214 |
215 | }
216 |
--------------------------------------------------------------------------------
/library/src/main/java/com/daimajia/swipe/interfaces/SwipeAdapterInterface.java:
--------------------------------------------------------------------------------
1 | package com.daimajia.swipe.interfaces;
2 |
3 | public interface SwipeAdapterInterface {
4 |
5 | int getSwipeLayoutResourceId(int position);
6 |
7 | void notifyDatasetChanged();
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/library/src/main/java/com/daimajia/swipe/interfaces/SwipeItemMangerInterface.java:
--------------------------------------------------------------------------------
1 | package com.daimajia.swipe.interfaces;
2 |
3 | import com.daimajia.swipe.SwipeLayout;
4 | import com.daimajia.swipe.util.Attributes;
5 |
6 | import java.util.List;
7 |
8 | public interface SwipeItemMangerInterface {
9 |
10 | void openItem(int position);
11 |
12 | void closeItem(int position);
13 |
14 | void closeAllExcept(SwipeLayout layout);
15 |
16 | void closeAllItems();
17 |
18 | List getOpenItems();
19 |
20 | List getOpenLayouts();
21 |
22 | void removeShownLayouts(SwipeLayout layout);
23 |
24 | boolean isOpen(int position);
25 |
26 | Attributes.Mode getMode();
27 |
28 | void setMode(Attributes.Mode mode);
29 | }
30 |
--------------------------------------------------------------------------------
/library/src/main/java/com/daimajia/swipe/util/Attributes.java:
--------------------------------------------------------------------------------
1 | package com.daimajia.swipe.util;
2 |
3 |
4 | public class Attributes {
5 |
6 | public enum Mode {
7 | Single, Multiple
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/library/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':demo', ':library'
2 |
--------------------------------------------------------------------------------