diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c6cbe56
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,8 @@
+*.iml
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
diff --git a/.idea/.name b/.idea/.name
new file mode 100644
index 0000000..8c870f5
--- /dev/null
+++ b/.idea/.name
@@ -0,0 +1 @@
+SwipListView
\ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000..96cc43e
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml
new file mode 100644
index 0000000..e7bedf3
--- /dev/null
+++ b/.idea/copyright/profiles_settings.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000..97626ba
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
new file mode 100644
index 0000000..c51a1d7
--- /dev/null
+++ b/.idea/gradle.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..1a3eaff
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..98b72f3
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml
new file mode 100644
index 0000000..7f68460
--- /dev/null
+++ b/.idea/runConfigurations.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/.gitignore b/app/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/app/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/app/build.gradle b/app/build.gradle
new file mode 100644
index 0000000..2991b52
--- /dev/null
+++ b/app/build.gradle
@@ -0,0 +1,29 @@
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 23
+ buildToolsVersion "23.0.3"
+
+ defaultConfig {
+ applicationId "swipelistview.yjn.com.swiplistview"
+ minSdkVersion 15
+ targetSdkVersion 23
+ versionCode 1
+ versionName "1.0"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+}
+
+dependencies {
+ compile project(':swipelistviewlibrary')
+ compile fileTree(dir: 'libs', include: ['*.jar'])
+ testCompile 'junit:junit:4.12'
+ compile 'com.android.support:appcompat-v7:23.3.0'
+ compile 'com.jakewharton:butterknife:6.1.0'
+
+}
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
new file mode 100644
index 0000000..d7adfc4
--- /dev/null
+++ b/app/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in F:\ZTEsoft\sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/app/src/androidTest/java/swipelistview/yjn/com/swiplistview/ApplicationTest.java b/app/src/androidTest/java/swipelistview/yjn/com/swiplistview/ApplicationTest.java
new file mode 100644
index 0000000..2fa2f59
--- /dev/null
+++ b/app/src/androidTest/java/swipelistview/yjn/com/swiplistview/ApplicationTest.java
@@ -0,0 +1,13 @@
+package swipelistview.yjn.com.swiplistview;
+
+import android.app.Application;
+import android.test.ApplicationTestCase;
+
+/**
+ * Testing Fundamentals
+ */
+public class ApplicationTest extends ApplicationTestCase {
+ public ApplicationTest() {
+ super(Application.class);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..f37fa9b
--- /dev/null
+++ b/app/src/main/AndroidManifest.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/swipelistview/yjn/com/swiplistview/adapter/TransferAdapter.java b/app/src/main/java/swipelistview/yjn/com/swiplistview/adapter/TransferAdapter.java
new file mode 100644
index 0000000..75f8462
--- /dev/null
+++ b/app/src/main/java/swipelistview/yjn/com/swiplistview/adapter/TransferAdapter.java
@@ -0,0 +1,89 @@
+package swipelistview.yjn.com.swiplistview.adapter;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import java.util.HashMap;
+import java.util.List;
+
+import butterknife.ButterKnife;
+import butterknife.InjectView;
+import swipelistview.yjn.com.swiplistview.R;
+import swipelistview.yjn.com.swiplistview.util.StringUtil;
+
+/**
+ * Description:
+ * Author: 0027008122 [yang.jianan@zte.com.cn]
+ * Time: 2016/3/31 16:29
+ * Version: 1.0
+ */
+public class TransferAdapter extends BaseAdapter {
+ private Context context;
+ private List> data;
+
+ public TransferAdapter(Context context, List> data) {
+ this.context = context;
+ this.data = data;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ ViewHolder mHolder;
+ if (convertView == null) {
+ convertView = LayoutInflater.from(context).inflate(R.layout.transfer_li_item, parent, false);
+ mHolder = new ViewHolder(convertView);
+ convertView.setTag(mHolder);
+ } else {
+ mHolder = (ViewHolder) convertView.getTag();
+ }
+
+ mHolder.happyNum.setText((String) data.get(position).get("happy"));
+
+ if (StringUtil.isEmpty((String) data.get(position).get("quantity"))) {
+ //如果 quantity 没有值, 就 隐藏quantity这行所属的 LinearLayout
+ mHolder.transferQuantityLinear.setVisibility(View.GONE);
+ } else {
+ mHolder.transferQuantity.setText((String) data.get(position).get("quantity"));
+ }
+
+ mHolder.transferTotal.setText((String) data.get(position).get("amount"));
+
+ return convertView;
+ }
+
+ class ViewHolder {
+ @InjectView(R.id.happy_Num)
+ TextView happyNum;
+ @InjectView(R.id.transfer_quantity)
+ TextView transferQuantity;
+ @InjectView(R.id.transfer_quantity_linear)
+ LinearLayout transferQuantityLinear;
+ @InjectView(R.id.transfer_total)
+ TextView transferTotal;
+
+ ViewHolder(View view) {
+ ButterKnife.inject(this, view);
+ }
+ }
+
+ @Override
+ public int getCount() {
+ return data.size();
+ }
+
+ @Override
+ public Object getItem(int position) {
+ return data.get(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+}
diff --git a/app/src/main/java/swipelistview/yjn/com/swiplistview/base/BaseActivity.java b/app/src/main/java/swipelistview/yjn/com/swiplistview/base/BaseActivity.java
new file mode 100644
index 0000000..1f061cc
--- /dev/null
+++ b/app/src/main/java/swipelistview/yjn/com/swiplistview/base/BaseActivity.java
@@ -0,0 +1,32 @@
+package swipelistview.yjn.com.swiplistview.base;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.support.v7.app.AppCompatActivity;
+import android.view.View;
+
+import swipelistview.yjn.com.swiplistview.widget.ToolbarWidget;
+
+/**
+ * Created by 0027006362 [liu.tong33@zte.com.cn]
+ * Date: 2016/3/8
+ * Time: 11:04
+ */
+public class BaseActivity extends AppCompatActivity {
+
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+
+ public void setBackListener(Activity context,ToolbarWidget toolbar) {
+ final Activity mContext = context;
+ if(toolbar != null){
+ toolbar.setNavBtnClickListener(new ToolbarWidget.ToolbarBtnOnclickListener() {
+ @Override
+ public void onClick(View v) {
+ mContext.onBackPressed();
+ }
+ });
+ }
+ }
+}
diff --git a/app/src/main/java/swipelistview/yjn/com/swiplistview/ui/MainActivity.java b/app/src/main/java/swipelistview/yjn/com/swiplistview/ui/MainActivity.java
new file mode 100644
index 0000000..5175259
--- /dev/null
+++ b/app/src/main/java/swipelistview/yjn/com/swiplistview/ui/MainActivity.java
@@ -0,0 +1,127 @@
+package swipelistview.yjn.com.swiplistview.ui;
+
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
+import android.os.Bundle;
+import android.util.TypedValue;
+import android.view.View;
+import android.widget.TextView;
+
+import com.yjn.swipelistview.swipelistviewlibrary.widget.SwipeMenu;
+import com.yjn.swipelistview.swipelistviewlibrary.widget.SwipeMenuCreator;
+import com.yjn.swipelistview.swipelistviewlibrary.widget.SwipeMenuItem;
+import com.yjn.swipelistview.swipelistviewlibrary.widget.SwipeMenuListView;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import butterknife.ButterKnife;
+import butterknife.InjectView;
+import butterknife.OnClick;
+import swipelistview.yjn.com.swiplistview.R;
+import swipelistview.yjn.com.swiplistview.adapter.TransferAdapter;
+import swipelistview.yjn.com.swiplistview.base.BaseActivity;
+import swipelistview.yjn.com.swiplistview.widget.ToolbarWidget;
+
+/**
+ * Description:
+ * Author: 0027008122 [yang.jianan@zte.com.cn]
+ * Time: 2016/3/31 14:18
+ * Version: 1.0
+ */
+public class MainActivity extends BaseActivity {
+
+ @InjectView(R.id.transfer_title)
+ ToolbarWidget transferTitle;
+ @InjectView(R.id.rechage_amount_tv)
+ TextView rechageAmountTv;
+ @InjectView(R.id.recharge_count_tv)
+ TextView rechargeCountTv;
+ @InjectView(R.id.list_view)
+ SwipeMenuListView listView;
+
+ //listview 数据
+ List> listViewData;
+ //listview 假数据
+ List> localTestData;
+
+ List> mAppList;
+
+ private TransferAdapter transferAdapter;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.transfer);
+ ButterKnife.inject(this);
+ setBackListener(this, transferTitle);
+
+ initData();
+
+ }
+
+ private void initData() {
+
+ localTestData = new ArrayList<>();
+
+ for (int i = 0; i < 10; i++) {
+ HashMap testData = new HashMap<>();
+ testData.put("happy", "happty" + i);
+ if (i % 2 == 0) {
+ testData.put("quantity", "15" + i);
+ }
+ testData.put("amount", "$" + "610" + i);
+ localTestData.add(testData);
+ }
+
+ transferAdapter = new TransferAdapter(MainActivity.this, localTestData);
+ listView.setAdapter(transferAdapter);
+
+ final SwipeMenuCreator creator = new SwipeMenuCreator() {
+ @Override
+ public void create(SwipeMenu menu) {
+
+ // create "delete" item
+ SwipeMenuItem deleteItem = new SwipeMenuItem(
+ getApplicationContext());
+ deleteItem.setBackground(new ColorDrawable(Color.parseColor("#fe3c3a")));
+ deleteItem.setWidth(dp2px(89));
+ deleteItem.setTitle("Delete");
+ deleteItem.setTitleColor(Color.WHITE);
+ deleteItem.setTitleSize(20);
+ menu.addMenuItem(deleteItem);
+ }
+ };
+ // set creator
+ listView.setMenuCreator(creator);
+
+ // listener item click event
+ listView.setOnMenuItemClickListener(new SwipeMenuListView.OnMenuItemClickListener() {
+ @Override
+ public boolean onMenuItemClick(int position, SwipeMenu menu, int index) {
+ if (index == 0) {
+ // delete
+ localTestData.remove(position);
+ transferAdapter.notifyDataSetChanged();
+ }
+ return false;
+ }
+ });
+ }
+
+ private int dp2px(int dp) {
+ return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
+ this.getResources().getDisplayMetrics());
+ }
+
+ @OnClick({R.id.rechage_amount_tv, R.id.recharge_count_tv})
+ public void onClick(View view) {
+ switch (view.getId()) {
+ case R.id.rechage_amount_tv:
+ break;
+ case R.id.recharge_count_tv:
+ break;
+ }
+ }
+}
diff --git a/app/src/main/java/swipelistview/yjn/com/swiplistview/util/StringUtil.java b/app/src/main/java/swipelistview/yjn/com/swiplistview/util/StringUtil.java
new file mode 100644
index 0000000..3d31f55
--- /dev/null
+++ b/app/src/main/java/swipelistview/yjn/com/swiplistview/util/StringUtil.java
@@ -0,0 +1,618 @@
+package swipelistview.yjn.com.swiplistview.util;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.math.BigDecimal;
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.TimeZone;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * 字符串操作工具包
+ * Author:0027004702 [shen.weijian@zte.com.cn]
+ * Date:2016-01-14
+ * Time:00:36
+ * Version:1.0
+ * TaskId:
+ */
+public class StringUtil {
+
+ private final static Pattern emailer = Pattern.compile("\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*");
+
+ private final static Pattern IMG_URL = Pattern.compile(".*?(gif|jpeg|png|jpg|bmp)");
+
+ private final static Pattern URL = Pattern.compile("^(https|http)://.*?$(net|com|.com.cn|org|me|)");
+
+ public final static DecimalFormat GHCFormat = new DecimalFormat("##0.00");
+
+ public final static DecimalFormat DATA_FORMAT = new DecimalFormat("##0.00 GB");
+
+ private final static ThreadLocal dateFormater = new ThreadLocal() {
+ @Override
+ protected SimpleDateFormat initialValue() {
+ return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ }
+ };
+
+ private final static ThreadLocal dateFormater2 = new ThreadLocal() {
+ @Override
+ protected SimpleDateFormat initialValue() {
+ return new SimpleDateFormat("yyyy-MM-dd");
+ }
+ };
+
+ /**
+ * 将字符串转位日期类型
+ *
+ * @param sdate
+ * @return
+ */
+ public static Date toDate(String sdate) {
+ return toDate(sdate, dateFormater.get());
+ }
+
+ public static Date toDate(String sdate, SimpleDateFormat dateFormater) {
+ try {
+ return dateFormater.parse(sdate);
+ } catch (ParseException e) {
+ return null;
+ }
+ }
+
+ public static String getDateString(Date date) {
+ return dateFormater.get().format(date);
+ }
+
+ public static String friendly_time2(String sdate) {
+ String res = "";
+ if (isEmpty(sdate))
+ return "";
+
+ String[] weekDays = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
+ String currentData = StringUtil.getDataTime("MM-dd");
+ int currentDay = toInt(currentData.substring(3));
+ int currentMoth = toInt(currentData.substring(0, 2));
+
+ int sMoth = toInt(sdate.substring(5, 7));
+ int sDay = toInt(sdate.substring(8, 10));
+ int sYear = toInt(sdate.substring(0, 4));
+ Date dt = new Date(sYear, sMoth - 1, sDay - 1);
+
+ if (sDay == currentDay && sMoth == currentMoth) {
+ res = "今天 / " + weekDays[getWeekOfDate(new Date())];
+ } else if (sDay == currentDay + 1 && sMoth == currentMoth) {
+ res = "昨天 / " + weekDays[(getWeekOfDate(new Date()) + 6) % 7];
+ } else {
+ if (sMoth < 10) {
+ res = "0";
+ }
+ res += sMoth + "/";
+ if (sDay < 10) {
+ res += "0";
+ }
+ res += sDay + " / " + weekDays[getWeekOfDate(dt)];
+ }
+
+ return res;
+ }
+
+
+ /**
+ * 智能格式化
+ */
+ public static String friendly_time3(String sdate) {
+ String res = "";
+ if (isEmpty(sdate))
+ return "";
+
+ Date date = StringUtil.toDate(sdate);
+ if (date == null)
+ return sdate;
+
+ SimpleDateFormat format = dateFormater2.get();
+
+ if (isToday(date.getTime())) {
+ format.applyPattern(isMorning(date.getTime()) ? "上午 hh:mm" : "下午 hh:mm");
+ res = format.format(date);
+ } else if (isYesterday(date.getTime())) {
+ format.applyPattern(isMorning(date.getTime()) ? "昨天 上午 hh:mm" : "昨天 下午 hh:mm");
+ res = format.format(date);
+ } else if (isCurrentYear(date.getTime())) {
+ format.applyPattern(isMorning(date.getTime()) ? "MM-dd 上午 hh:mm" : "MM-dd 下午 hh:mm");
+ res = format.format(date);
+ } else {
+ format.applyPattern(isMorning(date.getTime()) ? "yyyy-MM-dd 上午 hh:mm" : "yyyy-MM-dd 下午 hh:mm");
+ res = format.format(date);
+ }
+ return res;
+ }
+
+ /**
+ * @return 判断一个时间是不是上午
+ */
+ public static boolean isMorning(long when) {
+ android.text.format.Time time = new android.text.format.Time();
+ time.set(when);
+
+ int hour = time.hour;
+ return (hour >= 0) && (hour < 12);
+ }
+
+ public static boolean isAftermoon(long when) {
+ android.text.format.Time time = new android.text.format.Time();
+ time.set(when);
+
+ int hour = time.hour;
+ return (hour >= 12) && (hour < 18);
+ }
+
+ public static boolean isNight(long when) {
+ android.text.format.Time time = new android.text.format.Time();
+ time.set(when);
+
+ int hour = time.hour;
+ return (hour >= 18) && (hour < 24);
+ }
+
+ /**
+ * @return 判断一个时间是不是今天
+ */
+ public static boolean isToday(long when) {
+ android.text.format.Time time = new android.text.format.Time();
+ time.set(when);
+
+ int thenYear = time.year;
+ int thenMonth = time.month;
+ int thenMonthDay = time.monthDay;
+
+ time.set(System.currentTimeMillis());
+ return (thenYear == time.year)
+ && (thenMonth == time.month)
+ && (thenMonthDay == time.monthDay);
+ }
+
+ /**
+ * @return 判断一个时间是不是昨天
+ */
+ public static boolean isYesterday(long when) {
+ android.text.format.Time time = new android.text.format.Time();
+ time.set(when);
+
+ int thenYear = time.year;
+ int thenMonth = time.month;
+ int thenMonthDay = time.monthDay;
+
+ time.set(System.currentTimeMillis());
+ return (thenYear == time.year)
+ && (thenMonth == time.month)
+ && (time.monthDay - thenMonthDay == 1);
+ }
+
+ /**
+ * @return 判断一个时间是不是今年
+ */
+ public static boolean isCurrentYear(long when) {
+ android.text.format.Time time = new android.text.format.Time();
+ time.set(when);
+
+ int thenYear = time.year;
+
+ time.set(System.currentTimeMillis());
+ return (thenYear == time.year);
+ }
+
+ /**
+ * 获取当前日期是星期几
+ *
+ * @param dt
+ * @return 当前日期是星期几
+ */
+ public static int getWeekOfDate(Date dt) {
+ Calendar cal = Calendar.getInstance();
+ cal.setTime(dt);
+ int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
+ if (w < 0)
+ w = 0;
+ return w;
+ }
+
+ /**
+ * 判断给定字符串时间是否为今日
+ *
+ * @param sdate
+ * @return boolean
+ */
+ public static boolean isToday(String sdate) {
+ boolean b = false;
+ Date time = toDate(sdate);
+ Date today = new Date();
+ if (time != null) {
+ String nowDate = dateFormater2.get().format(today);
+ String timeDate = dateFormater2.get().format(time);
+ if (nowDate.equals(timeDate)) {
+ b = true;
+ }
+ }
+ return b;
+ }
+
+ /**
+ * 返回long类型的今天的日期
+ *
+ * @return
+ */
+ public static long getToday() {
+ Calendar cal = Calendar.getInstance();
+ String curDate = dateFormater2.get().format(cal.getTime());
+ curDate = curDate.replace("-", "");
+ return Long.parseLong(curDate);
+ }
+
+ public static String getCurTimeStr() {
+ Calendar cal = Calendar.getInstance();
+ String curDate = dateFormater.get().format(cal.getTime());
+ return curDate;
+ }
+
+ /***
+ * 计算两个时间差,返回的是的秒s
+ *
+ * @param dete1
+ * @param date2
+ * @return
+ * @author 火蚁 2015-2-9 下午4:50:06
+ */
+ public static long calDateDifferent(String dete1, String date2) {
+
+ long diff = 0;
+
+ Date d1 = null;
+ Date d2 = null;
+
+ try {
+ d1 = dateFormater.get().parse(dete1);
+ d2 = dateFormater.get().parse(date2);
+
+ // 毫秒ms
+ diff = d2.getTime() - d1.getTime();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return diff / 1000;
+ }
+
+ /**
+ * 判断给定字符串是否空白串。 空白串是指由空格、制表符、回车符、换行符组成的字符串 若输入字符串为null或空字符串,返回true
+ *
+ * @param input
+ * @return boolean
+ */
+ public static boolean isEmpty(String input) {
+ if (input == null || "".equals(input))
+ return true;
+ for (int i = 0; i < input.length(); i++) {
+ char c = input.charAt(i);
+ if (c != ' ' && c != '\t' && c != '\r' && c != '\n') {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * 判断是不是一个合法的电子邮件地址
+ *
+ * @param email ""
+ * @return
+ */
+ public static boolean isEmail(String email) {
+ if (email == null || email.trim().length() == 0)
+ return false;
+ return emailer.matcher(email).matches();
+ }
+
+ /**
+ * 验证是否是手机号码
+ *
+ * @param str
+ * @return
+ */
+ public static boolean isMobile(String str) {
+ Pattern pattern = Pattern.compile("1[0-9]{10}");
+ Matcher matcher = pattern.matcher(str);
+ if (matcher.matches()) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * 判断一个url是否为图片url
+ *
+ * @param url ""
+ * @return boolean
+ */
+ public static boolean isImgUrl(String url) {
+ return !(url == null || url.trim().length() == 0) && IMG_URL.matcher(url).matches();
+ }
+
+ /**
+ * 判断是否为一个合法的url地址
+ *
+ * @param str ""
+ * @return boolean
+ */
+ public static boolean isUrl(String str) {
+ if (str == null || str.trim().length() == 0)
+ return false;
+ return URL.matcher(str).matches();
+ }
+
+ /**
+ * 字符串转整数
+ *
+ * @param str ""
+ * @param defValue ""
+ * @return int
+ */
+ public static int toInt(String str, int defValue) {
+ try {
+ return Integer.parseInt(str);
+ } catch (Exception ignored) {
+ }
+ return defValue;
+ }
+
+ /**
+ * 对象转整数
+ *
+ * @param obj ""
+ * @return 转换异常返回 0
+ */
+ public static int toInt(Object obj) {
+ if (obj == null)
+ return 0;
+ return toInt(obj.toString(), 0);
+ }
+
+ /**
+ * 判断账号 是否为由 字母数字下划线 组成
+ *
+ * @param firstChar ""
+ * @return 数字格式不正确 返回 false
+ */
+ public static boolean isCustAccount(String firstChar) {
+ Pattern pattern = Pattern.compile("[0-9a-zA-Z _-]+$");
+// Pattern pattern = Pattern.compile("^[a-zA-Z0-9_]{1,}$");
+ Matcher matcher = pattern.matcher(firstChar);
+ if (matcher.matches()) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * 判断账号首字母 是否为非数字
+ *
+ * @param str ""
+ * @return 首字母匹配异常(非数字) 返回 false
+ */
+ public static boolean isNum(String str) {
+ try {
+ new BigDecimal(str);
+ return true;
+ } catch (Exception e) {
+ return false;
+ }
+
+ }
+
+ /**
+ * 对象转整数
+ *
+ * @param obj ""
+ * @return 转换异常返回 0
+ */
+ public static long toLong(String obj) {
+ try {
+ return Long.parseLong(obj);
+ } catch (Exception ignored) {
+ }
+ return 0;
+ }
+
+ /**
+ * 字符串转布尔值
+ *
+ * @param b ""
+ * @return 转换异常返回 false
+ */
+ public static boolean toBool(String b) {
+ try {
+ return Boolean.parseBoolean(b);
+ } catch (Exception ignored) {
+ }
+ return false;
+ }
+
+ public static String getString(String s) {
+ return s == null ? "" : s;
+ }
+
+ /**
+ * 将一个InputStream流转换成字符串
+ *
+ * @param is ""
+ * @return String
+ */
+ public static String toConvertString(InputStream is) {
+ StringBuffer res = new StringBuffer();
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader read = new BufferedReader(isr);
+ try {
+ String line;
+ line = read.readLine();
+ while (line != null) {
+ res.append(line).append("
");
+ line = read.readLine();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ if (null != isr) {
+ isr.close();
+ isr.close();
+ }
+ if (null != read) {
+ read.close();
+ read = null;
+ }
+ if (null != is) {
+ is.close();
+ is = null;
+ }
+ } catch (IOException ignored) {
+ }
+ }
+ return res.toString();
+ }
+
+ /***
+ * 截取字符串
+ *
+ * @param start 从那里开始,0算起
+ * @param num 截取多少个
+ * @param str 截取的字符串
+ * @return String
+ */
+ public static String getSubString(int start, int num, String str) {
+ if (str == null) {
+ return "";
+ }
+ int leng = str.length();
+ if (start < 0) {
+ start = 0;
+ }
+ if (start > leng) {
+ start = leng;
+ }
+ if (num < 0) {
+ num = 1;
+ }
+ int end = start + num;
+ if (end > leng) {
+ end = leng;
+ }
+ return str.substring(start, end);
+ }
+
+ /**
+ * 获取当前时间为每年第几周
+ *
+ * @return ""
+ */
+ public static int getWeekOfYear() {
+ return getWeekOfYear(new Date());
+ }
+
+ /**
+ * 获取当前时间为每年第几周
+ *
+ * @param date ""
+ * @return int
+ */
+ public static int getWeekOfYear(Date date) {
+ Calendar c = Calendar.getInstance();
+ c.setFirstDayOfWeek(Calendar.MONDAY);
+ c.setTime(date);
+ int week = c.get(Calendar.WEEK_OF_YEAR) - 1;
+ week = week == 0 ? 52 : week;
+ return week > 0 ? week : 1;
+ }
+
+ public static int[] getCurrentDate() {
+ int[] dateBundle = new int[3];
+ String[] temp = getDataTime("yyyy-MM-dd").split("-");
+
+ for (int i = 0; i < 3; i++) {
+ try {
+ dateBundle[i] = Integer.parseInt(temp[i]);
+ } catch (Exception e) {
+ dateBundle[i] = 0;
+ }
+ }
+ return dateBundle;
+ }
+
+ /**
+ * 返回当前系统时间
+ */
+ public static String getDataTime(String format) {
+ SimpleDateFormat df = new SimpleDateFormat(format);
+ return df.format(new Date());
+ }
+
+ /**
+ * 转百分比 保留两位小数
+ *
+ * @param p1
+ * @param p2
+ * @return
+ */
+ public static String percent(double p1, double p2) {
+ String str;
+ double p3 = p1 / p2;
+ NumberFormat nf = NumberFormat.getPercentInstance();
+ nf.setMinimumFractionDigits(2);
+ str = nf.format(p3);
+ return str;
+ }
+
+ /**
+ * 转百分比 保留整数
+ *
+ * @param p1
+ * @param p2
+ * @return
+ */
+ public static String percent2(double p1, double p2) {
+ String str;
+ double p3 = p1 / p2;
+ NumberFormat nf = NumberFormat.getPercentInstance();
+ nf.setMinimumFractionDigits(0);
+ str = nf.format(p3);
+ return str;
+ }
+
+ public static int percent2Number(double p1, double p2) {
+
+ if (p2 == 0)
+ return 0;
+
+ Number number = 0;
+ NumberFormat nf = NumberFormat.getPercentInstance();
+ try {
+ number = nf.parse(percent2(p1 * 100, p2));
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+ return number.intValue();
+ }
+
+ public static float parseMoney(String mstr) {
+ Float money = (isEmpty(mstr) ? 0 : Float.valueOf(mstr));
+ return money;
+ }
+}
diff --git a/app/src/main/java/swipelistview/yjn/com/swiplistview/widget/ToolbarWidget.java b/app/src/main/java/swipelistview/yjn/com/swiplistview/widget/ToolbarWidget.java
new file mode 100644
index 0000000..84d4d6e
--- /dev/null
+++ b/app/src/main/java/swipelistview/yjn/com/swiplistview/widget/ToolbarWidget.java
@@ -0,0 +1,146 @@
+package swipelistview.yjn.com.swiplistview.widget;
+
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.support.v7.widget.Toolbar;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ImageButton;
+import android.widget.TextView;
+
+import butterknife.ButterKnife;
+import butterknife.InjectView;
+import butterknife.OnClick;
+import swipelistview.yjn.com.swiplistview.R;
+
+/**
+ * Description: 自定义 toolbar
+ * Author 0027004702.
+ * Time:16/1/26 16:53
+ * Version:1.0
+ * Task:
+ */
+public class ToolbarWidget extends Toolbar {
+
+ private Context context;
+
+ private ToolbarBtnOnclickListener listener;
+
+ private ToolbarMenuOnclickListener menuOnclickListener;
+
+ // TODO 从属性配置文件中获取
+ private int mTitleMarginTop;
+
+ private int mTitleMarginBottom;
+
+ private int mTitleMarginStart;
+
+ private int mTitleMarginEnd;
+
+ // TODO navigation icon 这里其实不应该仅仅是显示或不显示后退键
+ private static final Class superView = ToolbarWidget.class.getSuperclass();
+
+ @InjectView(R.id.widget_toolbar_title)
+ TextView mTitleTextView;
+
+ @InjectView(R.id.widget_toolbar_subtitle)
+ TextView mSubtitleTextView;
+
+ @InjectView(R.id.toolbar_l_nav)
+ ImageButton leftNavBtn;
+
+ @InjectView((R.id.toolbar_r_nav))
+ ImageButton rightNavBtn;
+
+ public ToolbarWidget(Context context) {
+ this(context, null);
+ }
+
+ public ToolbarWidget(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public ToolbarWidget(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+
+ this.context = context;
+
+ View view = LayoutInflater.from(context).inflate(R.layout.widget_toolbar, this);
+
+ ButterKnife.inject(this, view);
+
+ initView(attrs, defStyleAttr);
+
+ }
+
+ private void initView(AttributeSet attrs, int defStyleAttr) {
+
+ TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.toolbarWidget);
+
+ Drawable lNavIcon = ta.getDrawable(R.styleable.toolbarWidget_leftnav);
+ if (lNavIcon != null) {
+// leftNavBtn.setBackgroundDrawable(lNavIcon);
+
+ leftNavBtn.setImageDrawable(lNavIcon);
+ leftNavBtn.setVisibility(VISIBLE);
+ }
+
+ Drawable rNavIcon = ta.getDrawable(R.styleable.toolbarWidget_rightnav);
+ if (rNavIcon != null) {
+ rightNavBtn.setBackgroundDrawable(rNavIcon);
+ rightNavBtn.setVisibility(VISIBLE);
+ }
+
+ final CharSequence title = ta.getText(R.styleable.toolbarWidget_title);
+ if (!TextUtils.isEmpty(title)) {
+ mTitleTextView.setText(title);
+ }
+
+ if (ta.hasValue(R.styleable.toolbarWidget_titlecolor)) {
+ mTitleTextView.setTextColor(ta.getColor(R.styleable.toolbarWidget_titlecolor, 0xffffffff));
+ }
+
+
+ // TODO subtitle
+
+ }
+
+ @OnClick(R.id.toolbar_l_nav)
+ void leftNavBtnOnclick() {
+ this.listener.onClick(leftNavBtn);
+ }
+
+ @OnClick(R.id.toolbar_r_nav)
+ void rightNavBtnOnClick() {
+ this.menuOnclickListener.menuOnclick(rightNavBtn);
+ }
+
+ public void setNavBtnClickListener(ToolbarBtnOnclickListener listener) {
+ this.listener = listener;
+ }
+
+ public void setMenuOnclickListener(ToolbarMenuOnclickListener listener) {
+ this.menuOnclickListener = listener;
+ }
+
+ @Override
+ public void setSubtitle(CharSequence subtitle) {
+ mSubtitleTextView.setVisibility(View.VISIBLE);
+ mSubtitleTextView.setText(subtitle);
+ super.setSubtitle(subtitle);
+ }
+
+ public interface ToolbarBtnOnclickListener {
+ void onClick(View v);
+ }
+
+ public interface ToolbarMenuOnclickListener {
+ void menuOnclick(View v);
+ }
+
+
+}
diff --git a/app/src/main/res/drawable-xhdpi/toolbar_left_back.png b/app/src/main/res/drawable-xhdpi/toolbar_left_back.png
new file mode 100644
index 0000000..005ec15
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/toolbar_left_back.png differ
diff --git a/app/src/main/res/drawable-xhdpi/transfer_icon.png b/app/src/main/res/drawable-xhdpi/transfer_icon.png
new file mode 100644
index 0000000..1aa70ba
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/transfer_icon.png differ
diff --git a/app/src/main/res/drawable/common_btn_normal.xml b/app/src/main/res/drawable/common_btn_normal.xml
new file mode 100644
index 0000000..1e64052
--- /dev/null
+++ b/app/src/main/res/drawable/common_btn_normal.xml
@@ -0,0 +1,16 @@
+
+
+
+
+ -
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/common_btn_pressed.xml b/app/src/main/res/drawable/common_btn_pressed.xml
new file mode 100644
index 0000000..ab72556
--- /dev/null
+++ b/app/src/main/res/drawable/common_btn_pressed.xml
@@ -0,0 +1,27 @@
+
+
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/common_btn_selector.xml b/app/src/main/res/drawable/common_btn_selector.xml
new file mode 100644
index 0000000..2a49ee6
--- /dev/null
+++ b/app/src/main/res/drawable/common_btn_selector.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/switcher_active_btn_bkg.xml b/app/src/main/res/drawable/switcher_active_btn_bkg.xml
new file mode 100644
index 0000000..d0c7f5a
--- /dev/null
+++ b/app/src/main/res/drawable/switcher_active_btn_bkg.xml
@@ -0,0 +1,14 @@
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/transfer.xml b/app/src/main/res/layout/transfer.xml
new file mode 100644
index 0000000..d8b2b73
--- /dev/null
+++ b/app/src/main/res/layout/transfer.xml
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/transfer_li_item.xml b/app/src/main/res/layout/transfer_li_item.xml
new file mode 100644
index 0000000..d12f628
--- /dev/null
+++ b/app/src/main/res/layout/transfer_li_item.xml
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/widget_toolbar.xml b/app/src/main/res/layout/widget_toolbar.xml
new file mode 100644
index 0000000..a9fa9be
--- /dev/null
+++ b/app/src/main/res/layout/widget_toolbar.xml
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..cde69bc
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..c133a0c
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..bfa42f0
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..324e72c
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..aee44e1
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/values-w820dp/dimens.xml b/app/src/main/res/values-w820dp/dimens.xml
new file mode 100644
index 0000000..63fc816
--- /dev/null
+++ b/app/src/main/res/values-w820dp/dimens.xml
@@ -0,0 +1,6 @@
+
+
+ 64dp
+
diff --git a/app/src/main/res/values/attr.xml b/app/src/main/res/values/attr.xml
new file mode 100644
index 0000000..bba2d0d
--- /dev/null
+++ b/app/src/main/res/values/attr.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..2b8be60
--- /dev/null
+++ b/app/src/main/res/values/colors.xml
@@ -0,0 +1,43 @@
+
+
+ #3F51B5
+ #303F9F
+ #FF4081
+
+
+ #40FFFFFF
+ #FFFFFF
+ #000000
+ #808080
+ #FF0000
+ #FFD700
+ #FFFF00
+ #008000
+ #800080
+ #FFC0CB
+ #FFA500
+ #FFFACD
+ #F5F5F5
+ #708090
+ #0083FF
+
+ #ea5a0e
+
+ #ed4233
+ #999999
+
+ #c1c1c1
+
+
+ #313131
+ #707070
+
+
+ #707070
+ #f0eff5
+
+ #dedede
+
+
+ #f0eff5
+
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..21d6f7d
--- /dev/null
+++ b/app/src/main/res/values/dimens.xml
@@ -0,0 +1,8 @@
+
+
+ 16dp
+ 16dp
+
+ 19sp
+ 18sp
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..da8a0e0
--- /dev/null
+++ b/app/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ SwipListView
+
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..11c5ba6
--- /dev/null
+++ b/app/src/main/res/values/styles.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/test/java/swipelistview/yjn/com/swiplistview/ExampleUnitTest.java b/app/src/test/java/swipelistview/yjn/com/swiplistview/ExampleUnitTest.java
new file mode 100644
index 0000000..280921b
--- /dev/null
+++ b/app/src/test/java/swipelistview/yjn/com/swiplistview/ExampleUnitTest.java
@@ -0,0 +1,15 @@
+package swipelistview.yjn.com.swiplistview;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * To work on unit tests, switch the Test Artifact in the Build Variants view.
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() throws Exception {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..d7c2c93
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,26 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+ repositories {
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:2.0.0'
+
+ /*// https://bintray.com
+ classpath 'com.novoda:bintray-release:0.3.4'*/
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ jcenter()
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000..1d3591c
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,18 @@
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+# Default value: -Xmx10248m -XX:MaxPermSize=256m
+# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..13372ae
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..122a0dc
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Mon Dec 28 10:00:20 PST 2015
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip
diff --git a/gradlew b/gradlew
new file mode 100644
index 0000000..9d82f78
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,160 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..8a0b282
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..3fb6e70
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1 @@
+include ':app', ':swipelistviewlibrary'
diff --git a/swipelistviewlibrary/.gitignore b/swipelistviewlibrary/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/swipelistviewlibrary/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/swipelistviewlibrary/build.gradle b/swipelistviewlibrary/build.gradle
new file mode 100644
index 0000000..8801459
--- /dev/null
+++ b/swipelistviewlibrary/build.gradle
@@ -0,0 +1,34 @@
+apply plugin: 'com.android.library'
+
+android {
+ compileSdkVersion 23
+ buildToolsVersion "23.0.3"
+
+ defaultConfig {
+ minSdkVersion 15
+ targetSdkVersion 23
+ versionCode 1
+ versionName "1.0"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+}
+
+dependencies {
+ compile fileTree(dir: 'libs', include: ['*.jar'])
+ testCompile 'junit:junit:4.12'
+ compile 'com.android.support:appcompat-v7:23.3.0'
+}
+
+/*publish {
+ userOrg = 'yangxiaoge' //bintray.com用户名
+ groupId = 'com.yjn' //jcenter上的路径
+ artifacts = 'SwipeListViewLibrary' //项目名称
+ publishVersion = '1.0.0' //版本号
+ desc = 'hey, guays. This is my first repository. ' //描述,不重要
+ website = 'https://github.com/yangxiaoge/SwipeListView'//网站,不重要
+}*/
diff --git a/swipelistviewlibrary/proguard-rules.pro b/swipelistviewlibrary/proguard-rules.pro
new file mode 100644
index 0000000..d7adfc4
--- /dev/null
+++ b/swipelistviewlibrary/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in F:\ZTEsoft\sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/swipelistviewlibrary/src/androidTest/java/com/yjn/swipelistview/swipelistviewlibrary/ApplicationTest.java b/swipelistviewlibrary/src/androidTest/java/com/yjn/swipelistview/swipelistviewlibrary/ApplicationTest.java
new file mode 100644
index 0000000..0e535c0
--- /dev/null
+++ b/swipelistviewlibrary/src/androidTest/java/com/yjn/swipelistview/swipelistviewlibrary/ApplicationTest.java
@@ -0,0 +1,13 @@
+package com.yjn.swipelistview.swipelistviewlibrary;
+
+import android.app.Application;
+import android.test.ApplicationTestCase;
+
+/**
+ * Testing Fundamentals
+ */
+public class ApplicationTest extends ApplicationTestCase {
+ public ApplicationTest() {
+ super(Application.class);
+ }
+}
\ No newline at end of file
diff --git a/swipelistviewlibrary/src/main/AndroidManifest.xml b/swipelistviewlibrary/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..c7fe518
--- /dev/null
+++ b/swipelistviewlibrary/src/main/AndroidManifest.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
diff --git a/swipelistviewlibrary/src/main/java/com/yjn/swipelistview/swipelistviewlibrary/widget/BaseSwipListAdapter.java b/swipelistviewlibrary/src/main/java/com/yjn/swipelistview/swipelistviewlibrary/widget/BaseSwipListAdapter.java
new file mode 100644
index 0000000..2a56493
--- /dev/null
+++ b/swipelistviewlibrary/src/main/java/com/yjn/swipelistview/swipelistviewlibrary/widget/BaseSwipListAdapter.java
@@ -0,0 +1,41 @@
+/*
+* The MIT License (MIT)
+*
+* Copyright (c) 2015 nimengbo
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all
+* copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*/
+package com.yjn.swipelistview.swipelistviewlibrary.widget;
+
+import android.widget.BaseAdapter;
+
+/**
+ * Created by Abner on 15/11/20.
+ * Email nimengbo@gmail.com
+ * github https://github.com/nimengbo
+ */
+public abstract class BaseSwipListAdapter extends BaseAdapter {
+
+ public boolean getSwipEnableByPosition(int position){
+ return true;
+ }
+
+
+
+}
diff --git a/swipelistviewlibrary/src/main/java/com/yjn/swipelistview/swipelistviewlibrary/widget/SwipeMenu.java b/swipelistviewlibrary/src/main/java/com/yjn/swipelistview/swipelistviewlibrary/widget/SwipeMenu.java
new file mode 100644
index 0000000..cecdd5a
--- /dev/null
+++ b/swipelistviewlibrary/src/main/java/com/yjn/swipelistview/swipelistviewlibrary/widget/SwipeMenu.java
@@ -0,0 +1,53 @@
+package com.yjn.swipelistview.swipelistviewlibrary.widget;
+
+import android.content.Context;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @author baoyz
+ * @date 2014-8-23
+ *
+ */
+public class SwipeMenu {
+
+ private Context mContext;
+ private List mItems;
+ private int mViewType;
+
+ public SwipeMenu(Context context) {
+ mContext = context;
+ mItems = new ArrayList();
+ }
+
+ public Context getContext() {
+ return mContext;
+ }
+
+ public void addMenuItem(SwipeMenuItem item) {
+ mItems.add(item);
+ }
+
+ public void removeMenuItem(SwipeMenuItem item) {
+ mItems.remove(item);
+ }
+
+ public List getMenuItems() {
+ return mItems;
+ }
+
+ public SwipeMenuItem getMenuItem(int index) {
+ return mItems.get(index);
+ }
+
+ public int getViewType() {
+ return mViewType;
+ }
+
+ public void setViewType(int viewType) {
+ this.mViewType = viewType;
+ }
+
+}
diff --git a/swipelistviewlibrary/src/main/java/com/yjn/swipelistview/swipelistviewlibrary/widget/SwipeMenuAdapter.java b/swipelistviewlibrary/src/main/java/com/yjn/swipelistview/swipelistviewlibrary/widget/SwipeMenuAdapter.java
new file mode 100644
index 0000000..2adc947
--- /dev/null
+++ b/swipelistviewlibrary/src/main/java/com/yjn/swipelistview/swipelistviewlibrary/widget/SwipeMenuAdapter.java
@@ -0,0 +1,148 @@
+package com.yjn.swipelistview.swipelistviewlibrary.widget;
+
+import android.content.Context;
+import android.database.DataSetObserver;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ListAdapter;
+import android.widget.WrapperListAdapter;
+
+/**
+ *
+ * @author baoyz
+ * @date 2014-8-24
+ *
+ */
+public class SwipeMenuAdapter implements WrapperListAdapter,
+ SwipeMenuView.OnSwipeItemClickListener {
+
+ private ListAdapter mAdapter;
+ private Context mContext;
+ private SwipeMenuListView.OnMenuItemClickListener onMenuItemClickListener;
+
+ public SwipeMenuAdapter(Context context, ListAdapter adapter) {
+ mAdapter = adapter;
+ mContext = context;
+ }
+
+ @Override
+ public int getCount() {
+ return mAdapter.getCount();
+ }
+
+ @Override
+ public Object getItem(int position) {
+ return mAdapter.getItem(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return mAdapter.getItemId(position);
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ SwipeMenuLayout layout = null;
+ if (convertView == null) {
+ View contentView = mAdapter.getView(position, convertView, parent);
+ SwipeMenu menu = new SwipeMenu(mContext);
+ menu.setViewType(getItemViewType(position));
+ createMenu(menu);
+ SwipeMenuView menuView = new SwipeMenuView(menu,
+ (SwipeMenuListView) parent);
+ menuView.setOnSwipeItemClickListener(this);
+ SwipeMenuListView listView = (SwipeMenuListView) parent;
+ layout = new SwipeMenuLayout(contentView, menuView,
+ listView.getCloseInterpolator(),
+ listView.getOpenInterpolator());
+ layout.setPosition(position);
+ } else {
+ layout = (SwipeMenuLayout) convertView;
+ layout.closeMenu();
+ layout.setPosition(position);
+ View view = mAdapter.getView(position, layout.getContentView(),
+ parent);
+ }
+ if (mAdapter instanceof BaseSwipListAdapter) {
+ boolean swipEnable = (((BaseSwipListAdapter) mAdapter).getSwipEnableByPosition(position));
+ layout.setSwipEnable(swipEnable);
+ }
+ return layout;
+ }
+
+ public void createMenu(SwipeMenu menu) {
+ // Test Code
+ SwipeMenuItem item = new SwipeMenuItem(mContext);
+ item.setTitle("Item 1");
+ item.setBackground(new ColorDrawable(Color.GRAY));
+ item.setWidth(300);
+ menu.addMenuItem(item);
+
+ item = new SwipeMenuItem(mContext);
+ item.setTitle("Item 2");
+ item.setBackground(new ColorDrawable(Color.RED));
+ item.setWidth(300);
+ menu.addMenuItem(item);
+ }
+
+ @Override
+ public void onItemClick(SwipeMenuView view, SwipeMenu menu, int index) {
+ if (onMenuItemClickListener != null) {
+ onMenuItemClickListener.onMenuItemClick(view.getPosition(), menu,
+ index);
+ }
+ }
+
+ public void setOnSwipeItemClickListener(
+ SwipeMenuListView.OnMenuItemClickListener onMenuItemClickListener) {
+ this.onMenuItemClickListener = onMenuItemClickListener;
+ }
+
+ @Override
+ public void registerDataSetObserver(DataSetObserver observer) {
+ mAdapter.registerDataSetObserver(observer);
+ }
+
+ @Override
+ public void unregisterDataSetObserver(DataSetObserver observer) {
+ mAdapter.unregisterDataSetObserver(observer);
+ }
+
+ @Override
+ public boolean areAllItemsEnabled() {
+ return mAdapter.areAllItemsEnabled();
+ }
+
+ @Override
+ public boolean isEnabled(int position) {
+ return mAdapter.isEnabled(position);
+ }
+
+ @Override
+ public boolean hasStableIds() {
+ return mAdapter.hasStableIds();
+ }
+
+ @Override
+ public int getItemViewType(int position) {
+ return mAdapter.getItemViewType(position);
+ }
+
+ @Override
+ public int getViewTypeCount() {
+ return mAdapter.getViewTypeCount();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return mAdapter.isEmpty();
+ }
+
+ @Override
+ public ListAdapter getWrappedAdapter() {
+ return mAdapter;
+ }
+
+}
diff --git a/swipelistviewlibrary/src/main/java/com/yjn/swipelistview/swipelistviewlibrary/widget/SwipeMenuCreator.java b/swipelistviewlibrary/src/main/java/com/yjn/swipelistview/swipelistviewlibrary/widget/SwipeMenuCreator.java
new file mode 100644
index 0000000..1d6c6d2
--- /dev/null
+++ b/swipelistviewlibrary/src/main/java/com/yjn/swipelistview/swipelistviewlibrary/widget/SwipeMenuCreator.java
@@ -0,0 +1,13 @@
+package com.yjn.swipelistview.swipelistviewlibrary.widget;
+
+
+/**
+ *
+ * @author baoyz
+ * @date 2014-8-24
+ *
+ */
+public interface SwipeMenuCreator {
+
+ void create(SwipeMenu menu);
+}
diff --git a/swipelistviewlibrary/src/main/java/com/yjn/swipelistview/swipelistviewlibrary/widget/SwipeMenuItem.java b/swipelistviewlibrary/src/main/java/com/yjn/swipelistview/swipelistviewlibrary/widget/SwipeMenuItem.java
new file mode 100644
index 0000000..7acf99d
--- /dev/null
+++ b/swipelistviewlibrary/src/main/java/com/yjn/swipelistview/swipelistviewlibrary/widget/SwipeMenuItem.java
@@ -0,0 +1,96 @@
+package com.yjn.swipelistview.swipelistviewlibrary.widget;
+
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+
+/**
+ *
+ * @author baoyz
+ * @date 2014-8-23
+ *
+ */
+public class SwipeMenuItem {
+
+ private int id;
+ private Context mContext;
+ private String title;
+ private Drawable icon;
+ private Drawable background;
+ private int titleColor;
+ private int titleSize;
+ private int width;
+
+ public SwipeMenuItem(Context context) {
+ mContext = context;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public int getTitleColor() {
+ return titleColor;
+ }
+
+ public int getTitleSize() {
+ return titleSize;
+ }
+
+ public void setTitleSize(int titleSize) {
+ this.titleSize = titleSize;
+ }
+
+ public void setTitleColor(int titleColor) {
+ this.titleColor = titleColor;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public void setTitle(int resId) {
+ setTitle(mContext.getString(resId));
+ }
+
+ public Drawable getIcon() {
+ return icon;
+ }
+
+ public void setIcon(Drawable icon) {
+ this.icon = icon;
+ }
+
+ public void setIcon(int resId) {
+ this.icon = mContext.getResources().getDrawable(resId);
+ }
+
+ public Drawable getBackground() {
+ return background;
+ }
+
+ public void setBackground(Drawable background) {
+ this.background = background;
+ }
+
+ public void setBackground(int resId) {
+ this.background = mContext.getResources().getDrawable(resId);
+ }
+
+ public int getWidth() {
+ return width;
+ }
+
+ public void setWidth(int width) {
+ this.width = width;
+ }
+
+}
diff --git a/swipelistviewlibrary/src/main/java/com/yjn/swipelistview/swipelistviewlibrary/widget/SwipeMenuLayout.java b/swipelistviewlibrary/src/main/java/com/yjn/swipelistview/swipelistviewlibrary/widget/SwipeMenuLayout.java
new file mode 100644
index 0000000..80e3936
--- /dev/null
+++ b/swipelistviewlibrary/src/main/java/com/yjn/swipelistview/swipelistviewlibrary/widget/SwipeMenuLayout.java
@@ -0,0 +1,362 @@
+package com.yjn.swipelistview.swipelistviewlibrary.widget;
+
+import android.content.Context;
+import android.support.v4.view.GestureDetectorCompat;
+import android.support.v4.widget.ScrollerCompat;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.GestureDetector.OnGestureListener;
+import android.view.GestureDetector.SimpleOnGestureListener;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.animation.Interpolator;
+import android.widget.AbsListView;
+import android.widget.FrameLayout;
+
+/**
+ *
+ * @author baoyz
+ * @date 2014-8-23
+ *
+ */
+public class SwipeMenuLayout extends FrameLayout {
+
+ private static final int CONTENT_VIEW_ID = 1;
+ private static final int MENU_VIEW_ID = 2;
+
+ private static final int STATE_CLOSE = 0;
+ private static final int STATE_OPEN = 1;
+
+ private int mSwipeDirection;
+
+ private View mContentView;
+ private SwipeMenuView mMenuView;
+ private int mDownX;
+ private int state = STATE_CLOSE;
+ private GestureDetectorCompat mGestureDetector;
+ private OnGestureListener mGestureListener;
+ private boolean isFling;
+ private int MIN_FLING = dp2px(15);
+ private int MAX_VELOCITYX = -dp2px(500);
+ private ScrollerCompat mOpenScroller;
+ private ScrollerCompat mCloseScroller;
+ private int mBaseX;
+ private int position;
+ private Interpolator mCloseInterpolator;
+ private Interpolator mOpenInterpolator;
+
+ private boolean mSwipEnable = true;
+
+ public SwipeMenuLayout(View contentView, SwipeMenuView menuView) {
+ this(contentView, menuView, null, null);
+ }
+
+ public SwipeMenuLayout(View contentView, SwipeMenuView menuView,
+ Interpolator closeInterpolator, Interpolator openInterpolator) {
+ super(contentView.getContext());
+ mCloseInterpolator = closeInterpolator;
+ mOpenInterpolator = openInterpolator;
+ mContentView = contentView;
+ mMenuView = menuView;
+ mMenuView.setLayout(this);
+ init();
+ }
+
+ // private SwipeMenuLayout(Context context, AttributeSet attrs, int
+ // defStyle) {
+ // super(context, attrs, defStyle);
+ // }
+
+ private SwipeMenuLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ private SwipeMenuLayout(Context context) {
+ super(context);
+ }
+
+ public int getPosition() {
+ return position;
+ }
+
+ public void setPosition(int position) {
+ this.position = position;
+ mMenuView.setPosition(position);
+ }
+
+ public void setSwipeDirection(int swipeDirection) {
+ mSwipeDirection = swipeDirection;
+ }
+
+ private void init() {
+ setLayoutParams(new AbsListView.LayoutParams(LayoutParams.MATCH_PARENT,
+ LayoutParams.WRAP_CONTENT));
+ mGestureListener = new SimpleOnGestureListener() {
+ @Override
+ public boolean onDown(MotionEvent e) {
+ isFling = false;
+ return true;
+ }
+
+ @Override
+ public boolean onFling(MotionEvent e1, MotionEvent e2,
+ float velocityX, float velocityY) {
+ // TODO
+ if (Math.abs(e1.getX() - e2.getX()) > MIN_FLING
+ && velocityX < MAX_VELOCITYX) {
+ isFling = true;
+ }
+ // Log.i("byz", MAX_VELOCITYX + ", velocityX = " + velocityX);
+ return super.onFling(e1, e2, velocityX, velocityY);
+ }
+ };
+ mGestureDetector = new GestureDetectorCompat(getContext(),
+ mGestureListener);
+
+ // mScroller = ScrollerCompat.create(getContext(), new
+ // BounceInterpolator());
+ if (mCloseInterpolator != null) {
+ mCloseScroller = ScrollerCompat.create(getContext(),
+ mCloseInterpolator);
+ } else {
+ mCloseScroller = ScrollerCompat.create(getContext());
+ }
+ if (mOpenInterpolator != null) {
+ mOpenScroller = ScrollerCompat.create(getContext(),
+ mOpenInterpolator);
+ } else {
+ mOpenScroller = ScrollerCompat.create(getContext());
+ }
+
+ LayoutParams contentParams = new LayoutParams(
+ LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
+ mContentView.setLayoutParams(contentParams);
+ if (mContentView.getId() < 1) {
+ mContentView.setId(CONTENT_VIEW_ID);
+ }
+
+ mMenuView.setId(MENU_VIEW_ID);
+ mMenuView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
+ LayoutParams.WRAP_CONTENT));
+
+ addView(mContentView);
+ addView(mMenuView);
+
+ // if (mContentView.getBackground() == null) {
+ // mContentView.setBackgroundColor(Color.WHITE);
+ // }
+
+ // in android 2.x, MenuView height is MATCH_PARENT is not work.
+ // getViewTreeObserver().addOnGlobalLayoutListener(
+ // new OnGlobalLayoutListener() {
+ // @Override
+ // public void onGlobalLayout() {
+ // setMenuHeight(mContentView.getHeight());
+ // // getViewTreeObserver()
+ // // .removeGlobalOnLayoutListener(this);
+ // }
+ // });
+
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+ }
+
+ public boolean onSwipe(MotionEvent event) {
+ mGestureDetector.onTouchEvent(event);
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ mDownX = (int) event.getX();
+ isFling = false;
+ break;
+ case MotionEvent.ACTION_MOVE:
+ // Log.i("byz", "downX = " + mDownX + ", moveX = " + event.getX());
+ int dis = (int) (mDownX - event.getX());
+ if (state == STATE_OPEN) {
+ dis += mMenuView.getWidth()*mSwipeDirection;;
+ }
+ swipe(dis);
+ break;
+ // add by liutong start
+ // 当 listview 处于 有 父 view 的 时候 滑动 有时候 会 触发 cancel 事件
+ case MotionEvent.ACTION_CANCEL:
+ if ((isFling || Math.abs(mDownX - event.getX()) > (mMenuView.getWidth() / 4)) &&
+ Math.signum(mDownX - event.getX()) == mSwipeDirection) {
+ // open
+ smoothOpenMenu();
+ }
+ else {
+ // close
+ smoothCloseMenu();
+ return false;
+ }
+ break;
+ // add by liutong end
+ case MotionEvent.ACTION_UP:
+ if ((isFling || Math.abs(mDownX - event.getX()) > (mMenuView.getWidth() / 2)) &&
+ Math.signum(mDownX - event.getX()) == mSwipeDirection) {
+ // open
+ smoothOpenMenu();
+ } else {
+ // close
+ smoothCloseMenu();
+ return false;
+ }
+ break;
+ }
+ return true;
+ }
+
+ public boolean isOpen() {
+ return state == STATE_OPEN;
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ return super.onTouchEvent(event);
+ }
+
+ private void swipe(int dis) {
+ if(!mSwipEnable){
+ return ;
+ }
+ if (Math.signum(dis) != mSwipeDirection) {
+ dis = 0;
+ } else if (Math.abs(dis) > mMenuView.getWidth()) {
+ dis = mMenuView.getWidth()*mSwipeDirection;
+ }
+
+ mContentView.layout(-dis, mContentView.getTop(),
+ mContentView.getWidth() -dis, getMeasuredHeight());
+
+ if (mSwipeDirection == SwipeMenuListView.DIRECTION_LEFT) {
+
+ mMenuView.layout(mContentView.getWidth() - dis, mMenuView.getTop(),
+ mContentView.getWidth() + mMenuView.getWidth() - dis,
+ mMenuView.getBottom());
+ } else {
+ mMenuView.layout(-mMenuView.getWidth() - dis, mMenuView.getTop(),
+ - dis, mMenuView.getBottom());
+ }
+ }
+
+ @Override
+ public void computeScroll() {
+ if (state == STATE_OPEN) {
+ if (mOpenScroller.computeScrollOffset()) {
+ swipe(mOpenScroller.getCurrX()*mSwipeDirection);
+ postInvalidate();
+ }
+ } else {
+ if (mCloseScroller.computeScrollOffset()) {
+ swipe((mBaseX - mCloseScroller.getCurrX())*mSwipeDirection);
+ postInvalidate();
+ }
+ }
+ }
+
+ public void smoothCloseMenu() {
+ state = STATE_CLOSE;
+ if (mSwipeDirection == SwipeMenuListView.DIRECTION_LEFT) {
+ mBaseX = -mContentView.getLeft();
+ mCloseScroller.startScroll(0, 0, mMenuView.getWidth(), 0, 350);
+ } else {
+ mBaseX = mMenuView.getRight();
+ mCloseScroller.startScroll(0, 0, mMenuView.getWidth(), 0, 350);
+ }
+ postInvalidate();
+ }
+
+ public void smoothOpenMenu() {
+ if(!mSwipEnable){
+ return ;
+ }
+ state = STATE_OPEN;
+ if (mSwipeDirection == SwipeMenuListView.DIRECTION_LEFT) {
+ mOpenScroller.startScroll(-mContentView.getLeft(), 0, mMenuView.getWidth(), 0, 350);
+ } else {
+ mOpenScroller.startScroll(mContentView.getLeft(), 0, mMenuView.getWidth(), 0, 350);
+ }
+ postInvalidate();
+ }
+
+ public void closeMenu() {
+ if (mCloseScroller.computeScrollOffset()) {
+ mCloseScroller.abortAnimation();
+ }
+ if (state == STATE_OPEN) {
+ state = STATE_CLOSE;
+ swipe(0);
+ }
+ }
+
+ public void openMenu() {
+ if(!mSwipEnable){
+ return ;
+ }
+ if (state == STATE_CLOSE) {
+ state = STATE_OPEN;
+ swipe(mMenuView.getWidth() * mSwipeDirection);
+ }
+ }
+
+ public View getContentView() {
+ return mContentView;
+ }
+
+ public SwipeMenuView getMenuView() {
+ return mMenuView;
+ }
+
+ private int dp2px(int dp) {
+ return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
+ getContext().getResources().getDisplayMetrics());
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ mMenuView.measure(MeasureSpec.makeMeasureSpec(0,
+ MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(
+ getMeasuredHeight(), MeasureSpec.EXACTLY));
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ mContentView.layout(0, 0, getMeasuredWidth(),
+ mContentView.getMeasuredHeight());
+ if (mSwipeDirection == SwipeMenuListView.DIRECTION_LEFT) {
+ mMenuView.layout(getMeasuredWidth(), 0,
+ getMeasuredWidth() + mMenuView.getMeasuredWidth(),
+ mContentView.getMeasuredHeight());
+ } else {
+ mMenuView.layout(-mMenuView.getMeasuredWidth(), 0,
+ 0, mContentView.getMeasuredHeight());
+ }
+ }
+
+ public void setMenuHeight(int measuredHeight) {
+ Log.i("byz", "pos = " + position + ", height = " + measuredHeight);
+ LayoutParams params = (LayoutParams) mMenuView.getLayoutParams();
+ if (params.height != measuredHeight) {
+ params.height = measuredHeight;
+ mMenuView.setLayoutParams(mMenuView.getLayoutParams());
+ }
+ }
+
+ public void setSwipEnable(boolean swipEnable){
+ mSwipEnable = swipEnable;
+ }
+
+ public boolean getSwipEnable(){
+ return mSwipEnable;
+ }
+}
diff --git a/swipelistviewlibrary/src/main/java/com/yjn/swipelistview/swipelistviewlibrary/widget/SwipeMenuListView.java b/swipelistviewlibrary/src/main/java/com/yjn/swipelistview/swipelistviewlibrary/widget/SwipeMenuListView.java
new file mode 100644
index 0000000..ffa71c4
--- /dev/null
+++ b/swipelistviewlibrary/src/main/java/com/yjn/swipelistview/swipelistviewlibrary/widget/SwipeMenuListView.java
@@ -0,0 +1,374 @@
+package com.yjn.swipelistview.swipelistviewlibrary.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.animation.Interpolator;
+import android.widget.ListAdapter;
+import android.widget.ListView;
+
+/**
+ * @author baoyz
+ * @date 2014-8-18
+ */
+public class SwipeMenuListView extends ListView {
+
+ private static final int TOUCH_STATE_NONE = 0;
+ private static final int TOUCH_STATE_X = 1;
+ private static final int TOUCH_STATE_Y = 2;
+
+ public static final int DIRECTION_LEFT = 1;
+ public static final int DIRECTION_RIGHT = -1;
+ private int mDirection = 1;//swipe from right to left by default
+
+ private int MAX_Y = 5;
+ private int MAX_X = 3;
+ private float mDownX;
+ private float mDownY;
+ private int mTouchState;
+ private int mTouchPosition;
+ private SwipeMenuLayout mTouchView;
+ private OnSwipeListener mOnSwipeListener;
+
+ private SwipeMenuCreator mMenuCreator;
+ private OnMenuItemClickListener mOnMenuItemClickListener;
+ private OnMenuStateChangeListener mOnMenuStateChangeListener;
+ private Interpolator mCloseInterpolator;
+ private Interpolator mOpenInterpolator;
+
+ public SwipeMenuListView(Context context) {
+ super(context);
+ init();
+ }
+
+ public SwipeMenuListView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init();
+ }
+
+ public SwipeMenuListView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init();
+ }
+
+ private void init() {
+ MAX_X = dp2px(MAX_X);
+ MAX_Y = dp2px(MAX_Y);
+ mTouchState = TOUCH_STATE_NONE;
+ }
+
+ @Override
+ public void setAdapter(ListAdapter adapter) {
+ super.setAdapter(new SwipeMenuAdapter(getContext(), adapter) {
+ @Override
+ public void createMenu(SwipeMenu menu) {
+ if (mMenuCreator != null) {
+ mMenuCreator.create(menu);
+ }
+ }
+
+ @Override
+ public void onItemClick(SwipeMenuView view, SwipeMenu menu,
+ int index) {
+ boolean flag = false;
+ if (mOnMenuItemClickListener != null) {
+ flag = mOnMenuItemClickListener.onMenuItemClick(
+ view.getPosition(), menu, index);
+ }
+ if (mTouchView != null && !flag) {
+ mTouchView.smoothCloseMenu();
+ }
+ }
+ });
+ }
+
+ public void setCloseInterpolator(Interpolator interpolator) {
+ mCloseInterpolator = interpolator;
+ }
+
+ public void setOpenInterpolator(Interpolator interpolator) {
+ mOpenInterpolator = interpolator;
+ }
+
+ public Interpolator getOpenInterpolator() {
+ return mOpenInterpolator;
+ }
+
+ public Interpolator getCloseInterpolator() {
+ return mCloseInterpolator;
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ //在拦截处处理,在滑动设置了点击事件的地方也能swip,点击时又不能影响原来的点击事件
+ int action = ev.getAction();
+ switch (action) {
+ case MotionEvent.ACTION_DOWN:
+ mDownX = ev.getX();
+ mDownY = ev.getY();
+ boolean handled = super.onInterceptTouchEvent(ev);
+ mTouchState = TOUCH_STATE_NONE;
+ mTouchPosition = pointToPosition((int) ev.getX(), (int) ev.getY());
+ View view = getChildAt(mTouchPosition - getFirstVisiblePosition());
+
+ //只在空的时候赋值 以免每次触摸都赋值,会有多个open状态
+ if (view instanceof SwipeMenuLayout) {
+ //如果有打开了 就拦截.
+ if (mTouchView != null && mTouchView.isOpen() && !inRangeOfView(mTouchView.getMenuView(), ev)) {
+ return true;
+ }
+ mTouchView = (SwipeMenuLayout) view;
+ mTouchView.setSwipeDirection(mDirection);
+ }
+ //如果摸在另外个view
+ if (mTouchView != null && mTouchView.isOpen() && view != mTouchView) {
+ handled = true;
+ }
+
+ if (mTouchView != null) {
+ mTouchView.onSwipe(ev);
+ }
+ return handled;
+ case MotionEvent.ACTION_MOVE:
+ float dy = Math.abs((ev.getY() - mDownY));
+ float dx = Math.abs((ev.getX() - mDownX));
+ if (Math.abs(dy) > MAX_Y || Math.abs(dx) > MAX_X) {
+ //每次拦截的down都把触摸状态设置成了TOUCH_STATE_NONE 只有返回true才会走onTouchEvent 所以写在这里就够了
+ if (mTouchState == TOUCH_STATE_NONE) {
+ if (Math.abs(dy) > MAX_Y) {
+ mTouchState = TOUCH_STATE_Y;
+ } else if (dx > MAX_X) {
+ mTouchState = TOUCH_STATE_X;
+ if (mOnSwipeListener != null) {
+ mOnSwipeListener.onSwipeStart(mTouchPosition);
+ }
+ }
+ }
+ return true;
+ }
+ }
+ return super.onInterceptTouchEvent(ev);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ if (ev.getAction() != MotionEvent.ACTION_DOWN && mTouchView == null)
+ return super.onTouchEvent(ev);
+ int action = ev.getAction();
+ switch (action) {
+ case MotionEvent.ACTION_DOWN:
+ int oldPos = mTouchPosition;
+ mDownX = ev.getX();
+ mDownY = ev.getY();
+ mTouchState = TOUCH_STATE_NONE;
+
+ mTouchPosition = pointToPosition((int) ev.getX(), (int) ev.getY());
+
+ if (mTouchPosition == oldPos && mTouchView != null
+ && mTouchView.isOpen()) {
+ mTouchState = TOUCH_STATE_X;
+ mTouchView.onSwipe(ev);
+ return true;
+ }
+
+ View view = getChildAt(mTouchPosition - getFirstVisiblePosition());
+
+ if (mTouchView != null && mTouchView.isOpen()) {
+ mTouchView.smoothCloseMenu();
+ mTouchView = null;
+ // return super.onTouchEvent(ev);
+ // try to cancel the touch event
+ MotionEvent cancelEvent = MotionEvent.obtain(ev);
+ cancelEvent.setAction(MotionEvent.ACTION_CANCEL);
+ onTouchEvent(cancelEvent);
+ if (mOnMenuStateChangeListener != null) {
+ mOnMenuStateChangeListener.onMenuClose(oldPos);
+ }
+ return true;
+ }
+ if (view instanceof SwipeMenuLayout) {
+ mTouchView = (SwipeMenuLayout) view;
+ mTouchView.setSwipeDirection(mDirection);
+ }
+ if (mTouchView != null) {
+ mTouchView.onSwipe(ev);
+ }
+ break;
+ case MotionEvent.ACTION_MOVE:
+ //有些可能有header,要减去header再判断
+ mTouchPosition = pointToPosition((int) ev.getX(), (int) ev.getY()) - getHeaderViewsCount();
+ //如果滑动了一下没完全展现,就收回去,这时候mTouchView已经赋值,再滑动另外一个不可以swip的view
+ //会导致mTouchView swip 。 所以要用位置判断是否滑动的是一个view
+ if (!mTouchView.getSwipEnable() || mTouchPosition != mTouchView.getPosition()) {
+ break;
+ }
+ float dy = Math.abs((ev.getY() - mDownY));
+ float dx = Math.abs((ev.getX() - mDownX));
+ if (mTouchState == TOUCH_STATE_X) {
+ if (mTouchView != null) {
+ mTouchView.onSwipe(ev);
+ }
+ getSelector().setState(new int[]{0});
+ ev.setAction(MotionEvent.ACTION_CANCEL);
+ super.onTouchEvent(ev);
+ return true;
+ } else if (mTouchState == TOUCH_STATE_NONE) {
+ if (Math.abs(dy) > MAX_Y) {
+ mTouchState = TOUCH_STATE_Y;
+ } else if (dx > MAX_X) {
+ mTouchState = TOUCH_STATE_X;
+ if (mOnSwipeListener != null) {
+ mOnSwipeListener.onSwipeStart(mTouchPosition);
+ }
+ }
+ }
+ break;
+ // add by liutong start
+ // 当 listview 处于 有 父 view 的 时候 滑动 有时候 会 触发 cancel 事件
+ case MotionEvent.ACTION_CANCEL:
+ if (mTouchState == TOUCH_STATE_X) {
+ if (mTouchView != null) {
+ boolean isBeforeOpen = mTouchView.isOpen();
+ mTouchView.onSwipe(ev);
+ boolean isAfterOpen = mTouchView.isOpen();
+ if (isBeforeOpen != isAfterOpen && mOnMenuStateChangeListener != null) {
+ if (isAfterOpen) {
+ mOnMenuStateChangeListener.onMenuOpen(mTouchPosition);
+ } else {
+ mOnMenuStateChangeListener.onMenuClose(mTouchPosition);
+ }
+ }
+ if (!isAfterOpen) {
+ mTouchPosition = -1;
+ mTouchView = null;
+ }
+ }
+ if (mOnSwipeListener != null) {
+ mOnSwipeListener.onSwipeEnd(mTouchPosition);
+ }
+ ev.setAction(MotionEvent.ACTION_CANCEL);
+ super.onTouchEvent(ev);
+ return true;
+ }
+ break;
+ // add by liutong start
+ case MotionEvent.ACTION_UP:
+ if (mTouchState == TOUCH_STATE_X) {
+ if (mTouchView != null) {
+ boolean isBeforeOpen = mTouchView.isOpen();
+ mTouchView.onSwipe(ev);
+ boolean isAfterOpen = mTouchView.isOpen();
+ if (isBeforeOpen != isAfterOpen && mOnMenuStateChangeListener != null) {
+ if (isAfterOpen) {
+ mOnMenuStateChangeListener.onMenuOpen(mTouchPosition);
+ } else {
+ mOnMenuStateChangeListener.onMenuClose(mTouchPosition);
+ }
+ }
+ if (!isAfterOpen) {
+ mTouchPosition = -1;
+ mTouchView = null;
+ }
+ }
+ if (mOnSwipeListener != null) {
+ mOnSwipeListener.onSwipeEnd(mTouchPosition);
+ }
+ ev.setAction(MotionEvent.ACTION_CANCEL);
+ super.onTouchEvent(ev);
+ return true;
+ }
+ break;
+ }
+ return super.onTouchEvent(ev);
+ }
+
+ public void smoothOpenMenu(int position) {
+ if (position >= getFirstVisiblePosition()
+ && position <= getLastVisiblePosition()) {
+ View view = getChildAt(position - getFirstVisiblePosition());
+ if (view instanceof SwipeMenuLayout) {
+ mTouchPosition = position;
+ if (mTouchView != null && mTouchView.isOpen()) {
+ mTouchView.smoothCloseMenu();
+ }
+ mTouchView = (SwipeMenuLayout) view;
+ mTouchView.setSwipeDirection(mDirection);
+ mTouchView.smoothOpenMenu();
+ }
+ }
+ }
+
+ public void smoothCloseMenu(){
+ if (mTouchView != null && mTouchView.isOpen()) {
+ mTouchView.smoothCloseMenu();
+ }
+ }
+
+ private int dp2px(int dp) {
+ return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
+ getContext().getResources().getDisplayMetrics());
+ }
+
+ public void setMenuCreator(SwipeMenuCreator menuCreator) {
+ this.mMenuCreator = menuCreator;
+ }
+
+ public void setOnMenuItemClickListener(
+ OnMenuItemClickListener onMenuItemClickListener) {
+ this.mOnMenuItemClickListener = onMenuItemClickListener;
+ }
+
+ public void setOnSwipeListener(OnSwipeListener onSwipeListener) {
+ this.mOnSwipeListener = onSwipeListener;
+ }
+
+ public void setOnMenuStateChangeListener(OnMenuStateChangeListener onMenuStateChangeListener) {
+ mOnMenuStateChangeListener = onMenuStateChangeListener;
+ }
+
+ public static interface OnMenuItemClickListener {
+ boolean onMenuItemClick(int position, SwipeMenu menu, int index);
+ }
+
+ public static interface OnSwipeListener {
+ void onSwipeStart(int position);
+
+ void onSwipeEnd(int position);
+ }
+
+ public static interface OnMenuStateChangeListener {
+ void onMenuOpen(int position);
+
+ void onMenuClose(int position);
+ }
+
+ public void setSwipeDirection(int direction) {
+ mDirection = direction;
+ }
+
+ /**
+ * 判断点击事件是否在某个view内
+ *
+ * @param view
+ * @param ev
+ * @return
+ */
+ public static boolean inRangeOfView(View view, MotionEvent ev) {
+ int[] location = new int[2];
+ view.getLocationOnScreen(location);
+ int x = location[0];
+ int y = location[1];
+ if (ev.getRawX() < x || ev.getRawX() > (x + view.getWidth()) || ev.getRawY() < y || ev.getRawY() > (y + view.getHeight())) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ int mExpandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
+ super.onMeasure(widthMeasureSpec, mExpandSpec);
+ }
+}
diff --git a/swipelistviewlibrary/src/main/java/com/yjn/swipelistview/swipelistviewlibrary/widget/SwipeMenuView.java b/swipelistviewlibrary/src/main/java/com/yjn/swipelistview/swipelistviewlibrary/widget/SwipeMenuView.java
new file mode 100644
index 0000000..7027bca
--- /dev/null
+++ b/swipelistviewlibrary/src/main/java/com/yjn/swipelistview/swipelistviewlibrary/widget/SwipeMenuView.java
@@ -0,0 +1,106 @@
+package com.yjn.swipelistview.swipelistviewlibrary.widget;
+
+import android.text.TextUtils;
+import android.view.Gravity;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import java.util.List;
+
+/**
+ *
+ * @author baoyz
+ * @date 2014-8-23
+ *
+ */
+public class SwipeMenuView extends LinearLayout implements OnClickListener {
+
+ private SwipeMenuListView mListView;
+ private SwipeMenuLayout mLayout;
+ private SwipeMenu mMenu;
+ private OnSwipeItemClickListener onItemClickListener;
+ private int position;
+
+ public int getPosition() {
+ return position;
+ }
+
+ public void setPosition(int position) {
+ this.position = position;
+ }
+
+ public SwipeMenuView(SwipeMenu menu, SwipeMenuListView listView) {
+ super(menu.getContext());
+ if(listView != null){
+ mListView = listView;
+ }
+ mMenu = menu;
+ List items = menu.getMenuItems();
+ int id = 0;
+ for (SwipeMenuItem item : items) {
+ addItem(item, id++);
+ }
+ }
+
+ private void addItem(SwipeMenuItem item, int id) {
+ LayoutParams params = new LayoutParams(item.getWidth(),
+ LayoutParams.MATCH_PARENT);
+ LinearLayout parent = new LinearLayout(getContext());
+ parent.setId(id);
+ parent.setGravity(Gravity.CENTER);
+ parent.setOrientation(LinearLayout.VERTICAL);
+ parent.setLayoutParams(params);
+ parent.setBackgroundDrawable(item.getBackground());
+ parent.setOnClickListener(this);
+ addView(parent);
+
+ if (item.getIcon() != null) {
+ parent.addView(createIcon(item));
+ }
+ if (!TextUtils.isEmpty(item.getTitle())) {
+ parent.addView(createTitle(item));
+ }
+
+ }
+
+ private ImageView createIcon(SwipeMenuItem item) {
+ ImageView iv = new ImageView(getContext());
+ iv.setImageDrawable(item.getIcon());
+ return iv;
+ }
+
+ private TextView createTitle(SwipeMenuItem item) {
+ TextView tv = new TextView(getContext());
+ tv.setText(item.getTitle());
+ tv.setGravity(Gravity.CENTER);
+ tv.setTextSize(item.getTitleSize());
+ tv.setTextColor(item.getTitleColor());
+ return tv;
+ }
+
+ @Override
+ public void onClick(View v) {
+ if (onItemClickListener != null && mLayout.isOpen()) {
+ onItemClickListener.onItemClick(this, mMenu, v.getId());
+ }
+ }
+
+ public OnSwipeItemClickListener getOnSwipeItemClickListener() {
+ return onItemClickListener;
+ }
+
+ public void setOnSwipeItemClickListener(OnSwipeItemClickListener onItemClickListener) {
+ this.onItemClickListener = onItemClickListener;
+ }
+
+ public void setLayout(SwipeMenuLayout mLayout) {
+ this.mLayout = mLayout;
+ }
+
+ public static interface OnSwipeItemClickListener {
+ void onItemClick(SwipeMenuView view, SwipeMenu menu, int index);
+ }
+}
diff --git a/swipelistviewlibrary/src/main/res/values/strings.xml b/swipelistviewlibrary/src/main/res/values/strings.xml
new file mode 100644
index 0000000..0324dd8
--- /dev/null
+++ b/swipelistviewlibrary/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ SwipeListViewLibrary
+
diff --git a/swipelistviewlibrary/src/test/java/com/yjn/swipelistview/swipelistviewlibrary/ExampleUnitTest.java b/swipelistviewlibrary/src/test/java/com/yjn/swipelistview/swipelistviewlibrary/ExampleUnitTest.java
new file mode 100644
index 0000000..914cf52
--- /dev/null
+++ b/swipelistviewlibrary/src/test/java/com/yjn/swipelistview/swipelistviewlibrary/ExampleUnitTest.java
@@ -0,0 +1,15 @@
+package com.yjn.swipelistview.swipelistviewlibrary;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * To work on unit tests, switch the Test Artifact in the Build Variants view.
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() throws Exception {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file