diff --git a/.gitignore b/.gitignore index f9c1bbb..27222b9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,47 +1,47 @@ -# built application files -# *.apk -*.ap_ -lint.xml - -# files for the dex VM -*.dex - -# Java class files -*.class - -# generated files -bin/ -gen/ - -# maven -target/ - -# Local configuration file (sdk path, etc) -local.properties - -# Windows thumbnail db -Thumbs.db - -# OSX files -.DS_Store - -# Eclipse project files -.classpath -.project -.settings - -# Android Studio -.idea -#.idea/workspace.xml - remove # and delete .idea if it better suit your needs. -build/ -.gradle - -# Proguard folder generated by Eclipse -proguard/ - -# Log Files -*.log - -# Other -.svn - +# built application files +# *.apk +*.ap_ +lint.xml + +# files for the dex VM +*.dex + +# Java class files +*.class + +# generated files +bin/ +gen/ + +# maven +target/ + +# Local configuration file (sdk path, etc) +local.properties + +# Windows thumbnail db +Thumbs.db + +# OSX files +.DS_Store + +# Eclipse project files +.classpath +.project +.settings + +# Android Studio +.idea +#.idea/workspace.xml - remove # and delete .idea if it better suit your needs. +build/ +.gradle + +# Proguard folder generated by Eclipse +proguard/ + +# Log Files +*.log + +# Other +.svn + diff --git a/README.md b/README.md index 99223f1..c439546 100644 --- a/README.md +++ b/README.md @@ -5,11 +5,12 @@ Android 开源项目 Demo ### 添加规范 各项目需要新建一个属于自己的文件夹,用于后续上传该开源库使用示例工程代码 -- 该文件夹以`开源库名-demo`命名,全小写,单词间用`-`连接。如果已有该文件夹,则以`开源库名-demo-${GitHub 用户名}`命名,如`event-bus-demo-trinea`; +- 该文件夹以`开源库名-demo`命名,全小写,单词间用`-`连接。 +如果已有该文件夹,则以`开源库名-demo-${GitHub 用户名}`命名,如`event-bus-demo-trinea`; - 示例工程要求覆盖到该开源项目所有功能,不允许拷贝官方 Demo; -- 若没有自己的 Code Format 文件,使用 [common](https://github.com/android-cn/android-open-project-demo/tree/master/common) 文件夹下 code format,code template 文件; +- Android Studio 用默认的格式化文件,Eclipse 用 [common](common) 文件夹下 code format,code template 文件; - 文件夹下需要有名为 apk 的子文件夹,用于存放可运行 APK 文件; - 文件夹下需要有名为 README.md 的介绍文件,其中包含以下内容。 (1). Demo Download (2). Screenshot 截图可使用 [licecap](http://www.cockos.com/licecap/) -具体可参考:[EventBus Demo ReadMe](https://github.com/android-cn/android-open-project-demo/tree/master/event-bus-demo) +具体可参考:[EventBus Demo ReadMe](event-bus-demo) diff --git a/active-android-demo/.gitignore b/active-android-demo/.gitignore new file mode 100644 index 0000000..afbdab3 --- /dev/null +++ b/active-android-demo/.gitignore @@ -0,0 +1,6 @@ +.gradle +/local.properties +/.idea/workspace.xml +/.idea/libraries +.DS_Store +/build diff --git a/active-android-demo/active-android-demo.iml b/active-android-demo/active-android-demo.iml new file mode 100644 index 0000000..2a02201 --- /dev/null +++ b/active-android-demo/active-android-demo.iml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/active-android-demo/app/.gitignore b/active-android-demo/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/active-android-demo/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/active-android-demo/app/app.iml b/active-android-demo/app/app.iml new file mode 100644 index 0000000..8d27a9e --- /dev/null +++ b/active-android-demo/app/app.iml @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/active-android-demo/app/build.gradle b/active-android-demo/app/build.gradle new file mode 100644 index 0000000..074d092 --- /dev/null +++ b/active-android-demo/app/build.gradle @@ -0,0 +1,33 @@ +apply plugin: 'com.android.application' +repositories { + mavenCentral() + maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } +} + + +android { + compileSdkVersion 21 + buildToolsVersion "21.1.1" + + defaultConfig { + applicationId "ouyang.activeandroid" + minSdkVersion 15 + targetSdkVersion 21 + versionCode 1 + versionName "1.0" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + compile fileTree(dir: 'libs', include: ['*.jar']) + compile 'com.android.support:support-v4:21.+' + compile 'com.michaelpardo:activeandroid:3.1.0-SNAPSHOT' + compile 'com.google.code.gson:gson:2.3.1' + compile project(':library') +} diff --git a/active-android-demo/app/proguard-rules.pro b/active-android-demo/app/proguard-rules.pro new file mode 100644 index 0000000..2b76c9d --- /dev/null +++ b/active-android-demo/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 D:\android-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/active-android-demo/app/src/androidTest/java/ouyang/activeandroid/ApplicationTest.java b/active-android-demo/app/src/androidTest/java/ouyang/activeandroid/ApplicationTest.java new file mode 100644 index 0000000..61ed873 --- /dev/null +++ b/active-android-demo/app/src/androidTest/java/ouyang/activeandroid/ApplicationTest.java @@ -0,0 +1,13 @@ +package ouyang.activeandroid; + +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/active-android-demo/app/src/main/AndroidManifest.xml b/active-android-demo/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..2a001e5 --- /dev/null +++ b/active-android-demo/app/src/main/AndroidManifest.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/active-android-demo/app/src/main/java/ouyang/activeandroid/FoodActivity.java b/active-android-demo/app/src/main/java/ouyang/activeandroid/FoodActivity.java new file mode 100644 index 0000000..9ea9e31 --- /dev/null +++ b/active-android-demo/app/src/main/java/ouyang/activeandroid/FoodActivity.java @@ -0,0 +1,84 @@ +package ouyang.activeandroid; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.view.MenuItem; +import android.view.View; +import android.widget.ArrayAdapter; +import android.widget.ListAdapter; +import android.widget.ListView; +import android.widget.Toast; + +import com.activeandroid.query.Select; +import com.tjerkw.slideexpandable.library.ActionSlideExpandableListView; + +import java.util.List; + +import ouyang.adapter.FoodAdapter; +import ouyang.model.Food; + +/** + * Created by zuxiang on 2015/2/8. + */ +public class FoodActivity extends Activity { + ActionSlideExpandableListView mListView; + List mFoods; + FoodAdapter mAdapter; + + private long mId; + public static final int FOOD_RESULT = 0 << 1; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_food); + getActionBar().setDisplayHomeAsUpEnabled(true); + + mListView = (ActionSlideExpandableListView) findViewById(R.id.listview); + mId = getIntent().getLongExtra("id", 0L); + mFoods = new Select().from(Food.class).where("cid=?", mId).execute(); + mAdapter = new FoodAdapter(this, mFoods, mId); + mListView.setAdapter(mAdapter); + mListView.setItemActionListener(new ActionSlideExpandableListView.OnActionClickListener() { + @Override + public void onClick(View listView, View buttonview, int position) { + Food food = (Food) mAdapter.getItem(position); + if (buttonview.getId() == R.id.btn_update) { + Intent intent = new Intent(FoodActivity.this, UpdateFoodActivity.class); + intent.putExtra("food", food); + startActivityForResult(intent, FOOD_RESULT); + } + + if (buttonview.getId() == R.id.btn_delete) { + mAdapter.delete(food.pk_id); + } + } + }, R.id.btn_update, R.id.btn_delete); + } + + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode == FOOD_RESULT) { + mFoods = new Select().from(Food.class).where("cid=?", mId).execute(); + mAdapter.replaceAll(mFoods); + } + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + finish(); + return true; + } + return super.onOptionsItemSelected(item); + } +} + + + + + diff --git a/active-android-demo/app/src/main/java/ouyang/activeandroid/FoodCategoryActivity.java b/active-android-demo/app/src/main/java/ouyang/activeandroid/FoodCategoryActivity.java new file mode 100644 index 0000000..81be450 --- /dev/null +++ b/active-android-demo/app/src/main/java/ouyang/activeandroid/FoodCategoryActivity.java @@ -0,0 +1,65 @@ +package ouyang.activeandroid; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.app.NavUtils; +import android.view.MenuItem; +import android.view.View; +import android.widget.AdapterView; +import android.widget.ListView; + +import com.activeandroid.ActiveAndroid; +import com.activeandroid.query.Select; + +import java.util.ArrayList; +import java.util.List; + +import ouyang.adapter.FoodCategoryAdapter; +import ouyang.model.Category; +import ouyang.model.Food; + +/** + * Created by zuxiang on 2015/2/8. + */ +public class FoodCategoryActivity extends Activity { + ListView mListView; + FoodCategoryAdapter mAdapter; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_activeandroid); + getActionBar().setDisplayHomeAsUpEnabled(true); + + mListView = (ListView) findViewById(R.id.listview); + List foodCatogroys = new Select().from(Category.class).execute(); + mAdapter = new FoodCategoryAdapter(this, foodCatogroys); + mListView.setAdapter(mAdapter); + mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + Intent intent = new Intent(FoodCategoryActivity.this, FoodActivity.class); + intent.putExtra("id", id); + startActivity(intent); + } + }); + + + } + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + finish(); + return true; + } + return super.onOptionsItemSelected(item); + } + + + + + + +} diff --git a/active-android-demo/app/src/main/java/ouyang/activeandroid/FoodCategoryCpActivity.java b/active-android-demo/app/src/main/java/ouyang/activeandroid/FoodCategoryCpActivity.java new file mode 100644 index 0000000..f5835c0 --- /dev/null +++ b/active-android-demo/app/src/main/java/ouyang/activeandroid/FoodCategoryCpActivity.java @@ -0,0 +1,82 @@ +package ouyang.activeandroid; + +import android.app.Activity; +import android.app.LoaderManager; +import android.content.CursorLoader; +import android.content.Intent; +import android.content.Loader; +import android.database.Cursor; +import android.os.Bundle; +import android.view.MenuItem; +import android.view.View; +import android.widget.AdapterView; +import android.widget.ListView; +import android.widget.SimpleCursorAdapter; + +import com.activeandroid.content.ContentProvider; + +import java.util.ArrayList; +import java.util.List; + +import ouyang.adapter.FoodAdapter; +import ouyang.adapter.FoodCategoryAdapter; +import ouyang.adapter.FoodCategoryCursorAdapter; +import ouyang.model.Category; + +/** + * Created by zuxiang on 2015/2/11. + */ +public class FoodCategoryCpActivity extends Activity implements LoaderManager.LoaderCallbacks{ + ListView mListView; + private FoodCategoryCursorAdapter mAdapter; + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_activeandroid); + getActionBar().setDisplayHomeAsUpEnabled(true); + + + mListView = (ListView)findViewById(R.id.listview); + mAdapter = new FoodCategoryCursorAdapter(this); + mListView.setAdapter(mAdapter); + + + getLoaderManager().initLoader(0, null,this); + mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + Intent intent = new Intent(FoodCategoryCpActivity.this, FoodCpActivity.class); + intent.putExtra("id", parent.getAdapter().getItemId(position)); + startActivity(intent); + } + }); + } + + @Override + public Loader onCreateLoader(int id, Bundle args) { + return new CursorLoader(this, + ContentProvider.createUri(Category.class, null), + null, null, null, null + ); + } + + @Override + public void onLoadFinished(Loader loader, Cursor data) { + mAdapter.swapCursor(data); + } + + @Override + public void onLoaderReset(Loader loader) { + mAdapter.swapCursor(null); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + finish(); + return true; + } + return super.onOptionsItemSelected(item); + } +} diff --git a/active-android-demo/app/src/main/java/ouyang/activeandroid/FoodCpActivity.java b/active-android-demo/app/src/main/java/ouyang/activeandroid/FoodCpActivity.java new file mode 100644 index 0000000..bdb1254 --- /dev/null +++ b/active-android-demo/app/src/main/java/ouyang/activeandroid/FoodCpActivity.java @@ -0,0 +1,79 @@ +package ouyang.activeandroid; + +import android.app.Activity; +import android.app.LoaderManager; +import android.content.CursorLoader; +import android.content.Intent; +import android.content.Loader; +import android.database.Cursor; +import android.os.Bundle; +import android.view.MenuItem; +import android.view.View; +import android.widget.ListView; + +import com.activeandroid.content.ContentProvider; +import com.activeandroid.query.Delete; +import com.tjerkw.slideexpandable.library.ActionSlideExpandableListView; + +import java.util.List; + +import ouyang.adapter.FoodAdapter; +import ouyang.adapter.FoodCategoryCursorAdapter; +import ouyang.adapter.FoodCursorAdapter; +import ouyang.model.Category; +import ouyang.model.Food; + +/** + * Created by zuxiang on 2015/2/12. + */ +public class FoodCpActivity extends Activity implements LoaderManager.LoaderCallbacks { + ListView mListView; + List mFoods; + FoodCursorAdapter mAdapter; + + private long mId; + public static final int FOODCP_RESULT = 0 << 1; + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_activeandroid); + getActionBar().setDisplayHomeAsUpEnabled(true); + + + mListView = (ListView) findViewById(R.id.listview); + mId = getIntent().getLongExtra("id", 0L); + mAdapter = new FoodCursorAdapter(this); + mListView.setAdapter(mAdapter); + getLoaderManager().initLoader(0, null, this); + } + + @Override + public Loader onCreateLoader(int id, Bundle args) { + return new CursorLoader(this, + ContentProvider.createUri(Food.class, null), + null, "cid=?", new String[]{String.valueOf(mId)}, null + ); + } + + @Override + public void onLoadFinished(Loader loader, Cursor data) { + mAdapter.swapCursor(data); + } + + @Override + public void onLoaderReset(Loader loader) { + mAdapter.swapCursor(null); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + finish(); + return true; + } + return super.onOptionsItemSelected(item); + } +} diff --git a/active-android-demo/app/src/main/java/ouyang/activeandroid/MainActivity.java b/active-android-demo/app/src/main/java/ouyang/activeandroid/MainActivity.java new file mode 100644 index 0000000..f1fa000 --- /dev/null +++ b/active-android-demo/app/src/main/java/ouyang/activeandroid/MainActivity.java @@ -0,0 +1,130 @@ +package ouyang.activeandroid; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.widget.Button; + +import com.activeandroid.ActiveAndroid; +import com.activeandroid.query.Delete; + +import java.util.List; + +import ouyang.model.Category; +import ouyang.model.CategoryResult; +import ouyang.model.Food; +import ouyang.model.FoodResult; + + +public class MainActivity extends Activity{ + Button mBtnActive; + Button mBtnActiveContentProvider; + + private static final int ACTIVE = 1<<0; + private static final int CONTENTPROVIDER = 1<<1; + private Handler mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + super.handleMessage(msg); + if(msg.what==ACTIVE) { + startActivity(new Intent(MainActivity.this, FoodCategoryActivity.class)); + } + if(msg.what==CONTENTPROVIDER){ + startActivity(new Intent(MainActivity.this, FoodCategoryCpActivity.class)); + } + } + }; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + + mBtnActive = (Button) findViewById(R.id.btn_activesimple); + mBtnActive.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + new Thread(new Runnable() { + @Override + public void run() { + initData(); + mHandler.sendEmptyMessage(ACTIVE); + } + }).start(); + } + }); + + mBtnActiveContentProvider= (Button)findViewById(R.id.btn_activecontentprovdier); + mBtnActiveContentProvider.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + new Thread(new Runnable() { + @Override + public void run() { + initData(); + mHandler.sendEmptyMessage(CONTENTPROVIDER); + } + }).start(); + } + }); + + } + + private void initData(){ + try { + new Delete().from(Category.class).execute(); + new Delete().from(Food.class).execute(); + ActiveAndroid.beginTransaction(); + List categoryList = CategoryResult.getCategorys(CategoryResult.CATEGORY_JSON); + for (Category category : categoryList) { + category.save(); + } + List foodList1 = FoodResult.getFoods(FoodResult.F1_JSON); + for (Food food : foodList1) { + food.save(); + } + + List foodList2 = FoodResult.getFoods(FoodResult.F2_JSON); + for (Food food : foodList2) { + food.save(); + } + List foodList3 = FoodResult.getFoods(FoodResult.F3_JSON); + for (Food food : foodList3) { + food.save(); + } + ActiveAndroid.setTransactionSuccessful(); + } finally { + ActiveAndroid.endTransaction(); + } + } + + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + // Inflate the menu; this adds items to the action bar if it is present. + getMenuInflater().inflate(R.menu.menu_main, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + // Handle action bar item clicks here. The action bar will + // automatically handle clicks on the Home/Up button, so long + // as you specify a parent activity in AndroidManifest.xml. + int id = item.getItemId(); + + //noinspection SimplifiableIfStatement + if (id == R.id.action_settings) { + return true; + } + + return super.onOptionsItemSelected(item); + } + +} diff --git a/active-android-demo/app/src/main/java/ouyang/activeandroid/UpdateFoodActivity.java b/active-android-demo/app/src/main/java/ouyang/activeandroid/UpdateFoodActivity.java new file mode 100644 index 0000000..2ab5f40 --- /dev/null +++ b/active-android-demo/app/src/main/java/ouyang/activeandroid/UpdateFoodActivity.java @@ -0,0 +1,58 @@ +package ouyang.activeandroid; + +import android.app.Activity; +import android.os.Bundle; +import android.view.MenuItem; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; + +import com.activeandroid.query.Update; + +import ouyang.model.Food; + +/** + * Created by zuxiang on 2015/2/11. + */ +public class UpdateFoodActivity extends Activity { + EditText mEtName; + EditText mEtPrice; + Button mBtnUpdate; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_updatefood); + getActionBar().setDisplayHomeAsUpEnabled(true); + mEtName = (EditText) findViewById(R.id.et_name); + mEtPrice = (EditText) findViewById(R.id.et_price); + mBtnUpdate = (Button) findViewById(R.id.btn_update); + + final Food food = (Food) getIntent().getSerializableExtra("food"); + mEtName.setText(food.name); + mEtPrice.setText(String.valueOf(food.price)); + mBtnUpdate.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + String name = mEtName.getText().toString(); + String price = mEtPrice.getText().toString(); + if (name.equals("") || price.equals("")) { + return; + } + new Update(Food.class).set("Name=?,Price=?", name, price).where("pk_id=?",food.pk_id).execute(); + setResult(FoodActivity.FOOD_RESULT); + finish(); + } + }); + + } + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + finish(); + return true; + } + return super.onOptionsItemSelected(item); + } +} diff --git a/active-android-demo/app/src/main/java/ouyang/adapter/FoodAdapter.java b/active-android-demo/app/src/main/java/ouyang/adapter/FoodAdapter.java new file mode 100644 index 0000000..1aede7f --- /dev/null +++ b/active-android-demo/app/src/main/java/ouyang/adapter/FoodAdapter.java @@ -0,0 +1,47 @@ +package ouyang.adapter; + +import android.content.Context; +import android.view.View; +import android.widget.TextView; + +import com.activeandroid.query.Delete; +import com.activeandroid.query.Select; + +import java.util.List; + +import ouyang.activeandroid.R; +import ouyang.model.Food; + +/** + * Created by zuxiang on 2015/2/8. + */ +public class FoodAdapter extends SimpleBaseAdapter { + private long cid; + + public FoodAdapter(Context context, List data, long cid) { + super(context, data); + this.cid = cid; + } + + @Override + public int getItemResource() { + return R.layout.item_food; + } + + @Override + public View getItemView(int position, View convertView, ViewHolder holder) { + Food food = data.get(position); + TextView tvName = holder.getView(R.id.tv_name); + TextView tvPrice = holder.getView(R.id.tv_price); + tvName.setText(food.name); + tvPrice.setText("¥" + food.price); + return convertView; + } + + public void delete(int id) { + new Delete().from(Food.class).where("pk_id = ? ", id).execute(); + data = new Select().from(Food.class).where("cid=?", cid).execute(); + notifyDataSetChanged(); + } + +} diff --git a/active-android-demo/app/src/main/java/ouyang/adapter/FoodCategoryAdapter.java b/active-android-demo/app/src/main/java/ouyang/adapter/FoodCategoryAdapter.java new file mode 100644 index 0000000..5bec149 --- /dev/null +++ b/active-android-demo/app/src/main/java/ouyang/adapter/FoodCategoryAdapter.java @@ -0,0 +1,37 @@ +package ouyang.adapter; + +import android.content.Context; +import android.view.View; +import android.widget.TextView; + +import java.util.List; + +import ouyang.activeandroid.R; +import ouyang.model.Category; + +/** + * Created by zuxiang on 2015/2/8. + */ +public class FoodCategoryAdapter extends SimpleBaseAdapter { + + public FoodCategoryAdapter(Context context, List data) { + super(context, data); + } + + @Override + public int getItemResource() { + return R.layout.item_category; + } + + @Override + public long getItemId(int position) { + return data.get(position).id; + } + + @Override + public View getItemView(int position, View convertView, ViewHolder holder) { + TextView tvName= holder.getView(R.id.tv_name); + tvName.setText(data.get(position).name); + return convertView; + } +} diff --git a/active-android-demo/app/src/main/java/ouyang/adapter/FoodCategoryCursorAdapter.java b/active-android-demo/app/src/main/java/ouyang/adapter/FoodCategoryCursorAdapter.java new file mode 100644 index 0000000..277449b --- /dev/null +++ b/active-android-demo/app/src/main/java/ouyang/adapter/FoodCategoryCursorAdapter.java @@ -0,0 +1,50 @@ +package ouyang.adapter; + +import android.content.Context; +import android.database.Cursor; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CursorAdapter; +import android.widget.TextView; + +import ouyang.activeandroid.R; +import ouyang.model.Category; + +/** + * Created by zuxiang on 2015/2/11. + */ +public class FoodCategoryCursorAdapter extends CursorAdapter { + private Cursor mCursor; + + public FoodCategoryCursorAdapter(Context context) { + super(context, null, false); + } + + + @Override + public Object getItem(int position) { + mCursor.moveToPosition(position); + return Category.getCategory(mCursor); + } + + @Override + public long getItemId(int position) { + mCursor.moveToPosition(position); + return Category.getCategory(mCursor).id; + } + + @Override + public View newView(Context context, Cursor cursor, ViewGroup parent) { + mCursor = cursor; + LayoutInflater layoutInflater = LayoutInflater.from(context); + return layoutInflater.inflate(R.layout.item_category,null); + } + + @Override + public void bindView(View view, Context context, Cursor cursor) { + Category category = Category.getCategory(cursor); + TextView tvName = (TextView)view.findViewById(R.id.tv_name); + tvName.setText(category.name); + } +} diff --git a/active-android-demo/app/src/main/java/ouyang/adapter/FoodCursorAdapter.java b/active-android-demo/app/src/main/java/ouyang/adapter/FoodCursorAdapter.java new file mode 100644 index 0000000..21fd114 --- /dev/null +++ b/active-android-demo/app/src/main/java/ouyang/adapter/FoodCursorAdapter.java @@ -0,0 +1,46 @@ +package ouyang.adapter; + +import android.content.Context; +import android.database.Cursor; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CursorAdapter; +import android.widget.TextView; + +import ouyang.activeandroid.R; +import ouyang.model.Category; +import ouyang.model.Food; + +/** + * Created by zuxiang on 2015/2/12. + */ +public class FoodCursorAdapter extends CursorAdapter { + private Cursor mCursor; + + public FoodCursorAdapter(Context context) { + super(context, null, false); + } + + @Override + public View newView(Context context, Cursor cursor, ViewGroup parent) { + mCursor = cursor; + LayoutInflater layoutInflater = LayoutInflater.from(context); + return layoutInflater.inflate(R.layout.item_cpfood, null); + } + + @Override + public Object getItem(int position) { + mCursor.moveToPosition(position); + return Food.getFood(mCursor); + } + + @Override + public void bindView(View view, Context context, Cursor cursor) { + Food food = Food.getFood(cursor); + TextView tvName = (TextView) view.findViewById(R.id.tv_name); + TextView tvPrice = (TextView) view.findViewById(R.id.tv_price); + tvName.setText(food.name); + tvPrice.setText("¥" + food.price); + } +} diff --git a/active-android-demo/app/src/main/java/ouyang/adapter/SimpleBaseAdapter.java b/active-android-demo/app/src/main/java/ouyang/adapter/SimpleBaseAdapter.java new file mode 100644 index 0000000..65cff49 --- /dev/null +++ b/active-android-demo/app/src/main/java/ouyang/adapter/SimpleBaseAdapter.java @@ -0,0 +1,113 @@ +package ouyang.adapter; + +import android.content.Context; +import android.util.SparseArray; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zuxiang on 2015/2/8. + */ +public abstract class SimpleBaseAdapter extends BaseAdapter { + + protected Context context; + protected List data; + + public SimpleBaseAdapter(Context context, List data) { + this.context = context; + this.data = data == null ? new ArrayList() : new ArrayList(data); + } + + @Override + public int getCount() { + return data.size(); + } + + @Override + public Object getItem(int position) { + if (position >= data.size()) + return null; + return data.get(position); + } + + @Override + public long getItemId(int position) { + return position; + } + + /** + * 该方法需要子类实现,需要返回item布局的resource id + * + * @return + */ + public abstract int getItemResource(); + + /** + * 使用该getItemView方法替换原来的getView方法,需要子类实现 + * + * @param position + * @param convertView + * @param parent + * @param holder + * @return + */ + public abstract View getItemView(int position, View convertView, ViewHolder holder); + + @SuppressWarnings("unchecked") + @Override + public View getView(int position, View convertView, ViewGroup parent) { + ViewHolder holder; + if (null == convertView) { + convertView = View.inflate(context, getItemResource(), null); + holder = new ViewHolder(convertView); + convertView.setTag(holder); + } else { + holder = (ViewHolder) convertView.getTag(); + } + return getItemView(position, convertView, holder); + } + + public class ViewHolder { + private SparseArray views = new SparseArray(); + private View convertView; + + public ViewHolder(View convertView) { + this.convertView = convertView; + } + + @SuppressWarnings("unchecked") + public T getView(int resId) { + View v = views.get(resId); + if (null == v) { + v = convertView.findViewById(resId); + views.put(resId, v); + } + return (T) v; + } + } + + public void addAll(List elem) { + data.addAll(elem); + notifyDataSetChanged(); + } + + public void remove(T elem) { + data.remove(elem); + notifyDataSetChanged(); + } + + public void remove(int index) { + data.remove(index); + notifyDataSetChanged(); + } + + public void replaceAll(List elem) { + data.clear(); + data.addAll(elem); + notifyDataSetChanged(); + } +} \ No newline at end of file diff --git a/active-android-demo/app/src/main/java/ouyang/model/Category.java b/active-android-demo/app/src/main/java/ouyang/model/Category.java new file mode 100644 index 0000000..7330317 --- /dev/null +++ b/active-android-demo/app/src/main/java/ouyang/model/Category.java @@ -0,0 +1,36 @@ +package ouyang.model; + +import android.database.Cursor; +import android.provider.BaseColumns; + +import com.activeandroid.Model; +import com.activeandroid.annotation.Column; +import com.activeandroid.annotation.Table; + +/** + * Created by zuxiang on 2015/2/8. + */ +@Table(name = "categorys") +public class Category extends Model { + @Column(name = "Name") + public String name; + @Column(name="cid") + public int id; + + @Column(name=BaseColumns._ID) + public int ID; + public Category(String name) { + this.name = name; + } + + public Category(){ + + } + + public static Category getCategory(Cursor cursor){ + Category category = new Category(); + category.name = cursor.getString(cursor.getColumnIndex("Name")); + category.id = cursor.getInt(cursor.getColumnIndex("cid")); + return category; + } +} diff --git a/active-android-demo/app/src/main/java/ouyang/model/CategoryResult.java b/active-android-demo/app/src/main/java/ouyang/model/CategoryResult.java new file mode 100644 index 0000000..54fd99e --- /dev/null +++ b/active-android-demo/app/src/main/java/ouyang/model/CategoryResult.java @@ -0,0 +1,19 @@ +package ouyang.model; + +import com.google.gson.Gson; + +import java.util.List; + +/** + * Created by zuxiang on 2015/2/9. + */ +public class CategoryResult { + public static final String CATEGORY_JSON = "{\"rows\": [ {\"id\":1, \"name\": \"IT一族\"},{\"id\":2,\"name\": \"高富帅\" },{ \"id\":3,\"name\": \"白富美\" }]}"; + public List rows; + + public static List getCategorys(String json) { + Gson gson = new Gson(); + CategoryResult categoryResult = gson.fromJson(json, CategoryResult.class); + return categoryResult.rows; + } +} diff --git a/active-android-demo/app/src/main/java/ouyang/model/Food.java b/active-android-demo/app/src/main/java/ouyang/model/Food.java new file mode 100644 index 0000000..1853291 --- /dev/null +++ b/active-android-demo/app/src/main/java/ouyang/model/Food.java @@ -0,0 +1,46 @@ +package ouyang.model; + +import android.database.Cursor; +import android.provider.BaseColumns; + +import com.activeandroid.Model; +import com.activeandroid.annotation.Column; +import com.activeandroid.annotation.Table; + +import java.io.Serializable; + +/** + * Created by zuxiang on 2015/2/8. + */ +@Table(name = "foods") +public class Food extends Model implements Serializable { + @Column(name = "Name") + public String name; + @Column(name = "Price") + public float price; + @Column(name = BaseColumns._ID) + public int ID; + @Column(name = "pk_id") + public int pk_id; + + @Column(name = "cid") + public int cid; + + public Food(String foodName, float price) { + this.name = foodName; + this.price = price; + } + + public Food() { + + } + + public static Food getFood(Cursor cursor) { + Food food = new Food(); + food.cid = cursor.getInt(cursor.getColumnIndex("cid")); + food.name = cursor.getString(cursor.getColumnIndex("Name")); + food.price = cursor.getFloat(cursor.getColumnIndex("Price")); + food.pk_id = cursor.getInt(cursor.getColumnIndex("pk_id")); + return food; + } +} diff --git a/active-android-demo/app/src/main/java/ouyang/model/FoodResult.java b/active-android-demo/app/src/main/java/ouyang/model/FoodResult.java new file mode 100644 index 0000000..2745b53 --- /dev/null +++ b/active-android-demo/app/src/main/java/ouyang/model/FoodResult.java @@ -0,0 +1,21 @@ +package ouyang.model; + +import com.google.gson.Gson; + +import java.util.List; + +/** + * Created by zuxiang on 2015/2/9. + */ +public class FoodResult { + public static final String F1_JSON = "{\"rows\": [{\"pk_id\":1, \"cid\": 1,\"name\": \"海西青虾\",\"price\": 150.12},{\"pk_id\":2, \"cid\": 1,\"name\": \"海鲜套餐\",\"price\": 102.12}, {\"pk_id\":3,\"cid\": 1,\"name\": \"叉烧鸭肉套餐\",\"price\": 110.12},{\"pk_id\":4,\"cid\": 1,\"name\": \"鲜虾一盘\",\"price\": 10.12},{\"pk_id\":5,\"cid\": 1,\"name\": \"白切鸡套餐\",\"price\": 10.12},{\"pk_id\":6,\"cid\": 1,\"name\": \"红烧酱鸭\", \"price\": 160.12}, {\"pk_id\":7,\"cid\": 1,\"name\": \"叉烧鸭肉套餐\", \"price\": 110.12},{\"pk_id\":8,\"cid\": 1,\"name\": \"珍珠贝套餐\",\"price\": 107.12}]}"; + public static final String F2_JSON ="{\"rows\": [{\"cid\":2,\t\"pk_id\":11,\"name\": \"青椒肉丝\", \"price\": 150.12},{\"cid\":2,\"pk_id\":12,\"name\": \"荔枝肉\",\"price\": 102.12}, {\"cid\":2,\"pk_id\":13,\"name\": \"排骨套餐\",\"price\": 110.12},{\"cid\":2,\t\"pk_id\":14, \"name\": \"鸡排套餐\", \"price\": 10.12}, {\"cid\":2,\"pk_id\":15, \"name\": \"鸭腿套餐\",\"price\": 10.12 }, {\"cid\":2,\"pk_id\":16,\"name\": \"鸡翅套餐\",\"price\": 160.12} ]}"; + public static final String F3_JSON = "{\"rows\": [{\"cid\": 3,\"pk_id\":20,\"name\": \"兔肉套餐\", \"price\": 130.12},{\"cid\": 3,\"pk_id\":21,\"name\": \"带鱼套餐\", \"price\": 150.12 }, {\"cid\": 3,\"pk_id\":22,\"name\": \"筒骨套餐\",\"price\": 102.12 }, { \"cid\": 3,\"pk_id\":23,\"name\": \"叉烧鸡套餐\",\"price\": 110.12},{ \"name\": \"白切鸡套餐\",\"price\": 10.12}]}"; + private List rows; + + public static List getFoods(String json) { + Gson gson = new Gson(); + FoodResult foodResult = gson.fromJson(json, FoodResult.class); + return foodResult.rows; + } +} diff --git a/active-android-demo/app/src/main/res/drawable-hdpi/ic_launcher.png b/active-android-demo/app/src/main/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 0000000..96a442e Binary files /dev/null and b/active-android-demo/app/src/main/res/drawable-hdpi/ic_launcher.png differ diff --git a/active-android-demo/app/src/main/res/drawable-mdpi/ic_launcher.png b/active-android-demo/app/src/main/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 0000000..359047d Binary files /dev/null and b/active-android-demo/app/src/main/res/drawable-mdpi/ic_launcher.png differ diff --git a/active-android-demo/app/src/main/res/drawable-xhdpi/ic_launcher.png b/active-android-demo/app/src/main/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 0000000..71c6d76 Binary files /dev/null and b/active-android-demo/app/src/main/res/drawable-xhdpi/ic_launcher.png differ diff --git a/active-android-demo/app/src/main/res/drawable-xxhdpi/ic_launcher.png b/active-android-demo/app/src/main/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..4df1894 Binary files /dev/null and b/active-android-demo/app/src/main/res/drawable-xxhdpi/ic_launcher.png differ diff --git a/active-android-demo/app/src/main/res/layout/activity_activeandroid.xml b/active-android-demo/app/src/main/res/layout/activity_activeandroid.xml new file mode 100644 index 0000000..3706fb0 --- /dev/null +++ b/active-android-demo/app/src/main/res/layout/activity_activeandroid.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/active-android-demo/app/src/main/res/layout/activity_food.xml b/active-android-demo/app/src/main/res/layout/activity_food.xml new file mode 100644 index 0000000..3fd2396 --- /dev/null +++ b/active-android-demo/app/src/main/res/layout/activity_food.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/active-android-demo/app/src/main/res/layout/activity_main.xml b/active-android-demo/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..abada51 --- /dev/null +++ b/active-android-demo/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,23 @@ + + + + android:text="2.1滑动删除"> + android:text="2.2item拖动"> + android:text="2.3多个item删除"> + android:text="2.4列表展开"> + android:text="2.5item增加"> + + + + + + \ No newline at end of file diff --git a/listview-animations-demo/ListviewAnimationDemo/res/layout/item_undo_row.xml b/listview-animations-demo/ListviewAnimationDemo/app/src/main/res/layout/item_undo_row.xml similarity index 100% rename from listview-animations-demo/ListviewAnimationDemo/res/layout/item_undo_row.xml rename to listview-animations-demo/ListviewAnimationDemo/app/src/main/res/layout/item_undo_row.xml diff --git a/listview-animations-demo/ListviewAnimationDemo/res/menu/menu_expandablelistitem.xml b/listview-animations-demo/ListviewAnimationDemo/app/src/main/res/menu/menu_expandablelistitem.xml similarity index 100% rename from listview-animations-demo/ListviewAnimationDemo/res/menu/menu_expandablelistitem.xml rename to listview-animations-demo/ListviewAnimationDemo/app/src/main/res/menu/menu_expandablelistitem.xml diff --git a/listview-animations-demo/ListviewAnimationDemo/res/menu/menu_item_animation.xml b/listview-animations-demo/ListviewAnimationDemo/app/src/main/res/menu/menu_item_animation.xml similarity index 100% rename from listview-animations-demo/ListviewAnimationDemo/res/menu/menu_item_animation.xml rename to listview-animations-demo/ListviewAnimationDemo/app/src/main/res/menu/menu_item_animation.xml diff --git a/listview-animations-demo/ListviewAnimationDemo/res/menu/menu_swipe_to_dismiss.xml b/listview-animations-demo/ListviewAnimationDemo/app/src/main/res/menu/menu_swipe_to_dismiss.xml similarity index 100% rename from listview-animations-demo/ListviewAnimationDemo/res/menu/menu_swipe_to_dismiss.xml rename to listview-animations-demo/ListviewAnimationDemo/app/src/main/res/menu/menu_swipe_to_dismiss.xml diff --git a/listview-animations-demo/ListviewAnimationDemo/res/menu/swipe_to_dismiss.xml b/listview-animations-demo/ListviewAnimationDemo/app/src/main/res/menu/swipe_to_dismiss.xml similarity index 100% rename from listview-animations-demo/ListviewAnimationDemo/res/menu/swipe_to_dismiss.xml rename to listview-animations-demo/ListviewAnimationDemo/app/src/main/res/menu/swipe_to_dismiss.xml diff --git a/listview-animations-demo/ListviewAnimationDemo/app/src/main/res/mipmap-hdpi/ic_launcher.png b/listview-animations-demo/ListviewAnimationDemo/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..cde69bc Binary files /dev/null and b/listview-animations-demo/ListviewAnimationDemo/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/listview-animations-demo/ListviewAnimationDemo/app/src/main/res/mipmap-mdpi/ic_launcher.png b/listview-animations-demo/ListviewAnimationDemo/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..c133a0c Binary files /dev/null and b/listview-animations-demo/ListviewAnimationDemo/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/listview-animations-demo/ListviewAnimationDemo/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/listview-animations-demo/ListviewAnimationDemo/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..bfa42f0 Binary files /dev/null and b/listview-animations-demo/ListviewAnimationDemo/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/listview-animations-demo/ListviewAnimationDemo/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/listview-animations-demo/ListviewAnimationDemo/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..324e72c Binary files /dev/null and b/listview-animations-demo/ListviewAnimationDemo/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/listview-animations-demo/ListviewAnimationDemo/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/listview-animations-demo/ListviewAnimationDemo/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..aee44e1 Binary files /dev/null and b/listview-animations-demo/ListviewAnimationDemo/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/listview-animations-demo/ListviewAnimationDemo/app/src/main/res/values/colors.xml b/listview-animations-demo/ListviewAnimationDemo/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..3ab3e9c --- /dev/null +++ b/listview-animations-demo/ListviewAnimationDemo/app/src/main/res/values/colors.xml @@ -0,0 +1,6 @@ + + + #3F51B5 + #303F9F + #FF4081 + diff --git a/listview-animations-demo/ListviewAnimationDemo/res/values/strings.xml b/listview-animations-demo/ListviewAnimationDemo/app/src/main/res/values/strings.xml similarity index 100% rename from listview-animations-demo/ListviewAnimationDemo/res/values/strings.xml rename to listview-animations-demo/ListviewAnimationDemo/app/src/main/res/values/strings.xml diff --git a/listview-animations-demo/ListviewAnimationDemo/app/src/main/res/values/styles.xml b/listview-animations-demo/ListviewAnimationDemo/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..6ce89c7 --- /dev/null +++ b/listview-animations-demo/ListviewAnimationDemo/app/src/main/res/values/styles.xml @@ -0,0 +1,20 @@ + + + + + + + + + diff --git a/listview-animations-demo/ListviewAnimationDemo/app/src/test/java/com/example/listviewanimationdemo/ExampleUnitTest.java b/listview-animations-demo/ListviewAnimationDemo/app/src/test/java/com/example/listviewanimationdemo/ExampleUnitTest.java new file mode 100644 index 0000000..2669dea --- /dev/null +++ b/listview-animations-demo/ListviewAnimationDemo/app/src/test/java/com/example/listviewanimationdemo/ExampleUnitTest.java @@ -0,0 +1,15 @@ +package com.example.listviewanimationdemo; + +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/listview-animations-demo/ListviewAnimationDemo/build.gradle b/listview-animations-demo/ListviewAnimationDemo/build.gradle new file mode 100644 index 0000000..be515a8 --- /dev/null +++ b/listview-animations-demo/ListviewAnimationDemo/build.gradle @@ -0,0 +1,23 @@ +// 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:1.3.0' + + // 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/listview-animations-demo/ListviewAnimationDemo/gradle.properties b/listview-animations-demo/ListviewAnimationDemo/gradle.properties new file mode 100644 index 0000000..1d3591c --- /dev/null +++ b/listview-animations-demo/ListviewAnimationDemo/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/listview-animations-demo/ListviewAnimationDemo/gradle/wrapper/gradle-wrapper.jar b/listview-animations-demo/ListviewAnimationDemo/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..8c0fb64 Binary files /dev/null and b/listview-animations-demo/ListviewAnimationDemo/gradle/wrapper/gradle-wrapper.jar differ diff --git a/listview-animations-demo/ListviewAnimationDemo/gradle/wrapper/gradle-wrapper.properties b/listview-animations-demo/ListviewAnimationDemo/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..7f33594 --- /dev/null +++ b/listview-animations-demo/ListviewAnimationDemo/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Thu Nov 05 12:26:32 CST 2015 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip diff --git a/listview-animations-demo/ListviewAnimationDemo/gradlew b/listview-animations-demo/ListviewAnimationDemo/gradlew new file mode 100644 index 0000000..91a7e26 --- /dev/null +++ b/listview-animations-demo/ListviewAnimationDemo/gradlew @@ -0,0 +1,164 @@ +#!/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 + +# For Cygwin, ensure paths are in UNIX format before anything is touched. +if $cygwin ; then + [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` +fi + +# 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\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +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"` + + # 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/listview-animations-demo/ListviewAnimationDemo/gradlew.bat b/listview-animations-demo/ListviewAnimationDemo/gradlew.bat new file mode 100644 index 0000000..8a0b282 --- /dev/null +++ b/listview-animations-demo/ListviewAnimationDemo/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/listview-animations-demo/ListviewAnimationDemo/res/layout/item_list_row.xml b/listview-animations-demo/ListviewAnimationDemo/res/layout/item_list_row.xml deleted file mode 100644 index a22709c..0000000 --- a/listview-animations-demo/ListviewAnimationDemo/res/layout/item_list_row.xml +++ /dev/null @@ -1,7 +0,0 @@ - - diff --git a/listview-animations-demo/ListviewAnimationDemo/settings.gradle b/listview-animations-demo/ListviewAnimationDemo/settings.gradle new file mode 100644 index 0000000..e7b4def --- /dev/null +++ b/listview-animations-demo/ListviewAnimationDemo/settings.gradle @@ -0,0 +1 @@ +include ':app' diff --git a/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/AnimateDismissActivity.java b/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/AnimateDismissActivity.java deleted file mode 100644 index 76d662f..0000000 --- a/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/AnimateDismissActivity.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2013 Niek Haarman - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.example.listviewanimationdemo; - -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.support.v4.app.FragmentActivity; -import android.view.LayoutInflater; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.widget.AbsListView; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.Button; -import android.widget.CheckedTextView; -import android.widget.ListView; - -import com.example.listviewanimationdemo.base.BaseListActivity; -import com.nhaarman.listviewanimations.ArrayAdapter; -import com.nhaarman.listviewanimations.itemmanipulation.AnimateDismissAdapter; -import com.nhaarman.listviewanimations.itemmanipulation.OnDismissCallback; - -import java.util.ArrayList; -import java.util.List; - -public class AnimateDismissActivity extends FragmentActivity { - - private List mSelectedPositions; - private MyListAdapter mAdapter; - - - public static void actionToAnimateDismiss(Context context) { - Intent intent = new Intent(context, AnimateDismissActivity.class); - context.startActivity(intent); - } - - @Override - protected void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_animateremoval); - - mSelectedPositions = new ArrayList(); - - ListView listView = (ListView) findViewById(R.id.activity_animateremoval_listview); - mAdapter = new MyListAdapter(BaseListActivity.getItems()); - final AnimateDismissAdapter animateDismissAdapter = new AnimateDismissAdapter(mAdapter, new MyOnDismissCallback()); - animateDismissAdapter.setAbsListView(listView); - listView.setAdapter(animateDismissAdapter); - - Button button = (Button) findViewById(R.id.activity_animateremoval_button); - button.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(final View v) { - animateDismissAdapter.animateDismiss(mSelectedPositions); - mSelectedPositions.clear(); - } - }); - - listView.setOnItemClickListener(new OnItemClickListener() { - - @Override - public void onItemClick(final AdapterView parent, final View view, final int position, final long id) { - CheckedTextView tv = (CheckedTextView) view; - tv.toggle(); - if (tv.isChecked()) { - mSelectedPositions.add(position); - } else { - mSelectedPositions.remove((Integer) position); - } - } - }); - } - - private class MyOnDismissCallback implements OnDismissCallback { - - @Override - public void onDismiss(final AbsListView listView, final int[] reverseSortedPositions) { - for (int position : reverseSortedPositions) { - mAdapter.remove(position); - } - } - } - - private class MyListAdapter extends ArrayAdapter { - - public MyListAdapter(final ArrayList items) { - super(items); - } - - @Override - public View getView(final int position, final View convertView, final ViewGroup parent) { - CheckedTextView tv = (CheckedTextView) convertView; - if (tv == null) { - tv = (CheckedTextView) LayoutInflater.from(AnimateDismissActivity.this).inflate(R.layout.item_animateremoval_row, parent, false); - } - tv.setText(String.valueOf(getItem(position))); - tv.setChecked(mSelectedPositions.contains(position)); - return tv; - } - } -} diff --git a/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/DragAndDropActivity.java b/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/DragAndDropActivity.java deleted file mode 100644 index 12799ca..0000000 --- a/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/DragAndDropActivity.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2013 Niek Haarman - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.example.listviewanimationdemo; - -import android.content.Context; -import android.content.Intent; -import android.graphics.Color; -import android.os.Bundle; -import android.view.Gravity; -import android.widget.TextView; -import android.widget.Toast; - -import com.example.listviewanimationdemo.base.BaseListActivity; -import com.nhaarman.listviewanimations.ArrayAdapter; -import com.nhaarman.listviewanimations.swinginadapters.prepared.AlphaInAnimationAdapter; -import com.nhaarman.listviewanimations.widget.DynamicListView; - -public class DragAndDropActivity extends BaseListActivity { - - public static void actionToDragAndDrop(Context context) { - Intent intent = new Intent(context, DragAndDropActivity.class); - context.startActivity(intent); - } - - @Override - protected void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_draganddrop); - - DynamicListView listView = (DynamicListView) findViewById(R.id.activity_draganddrop_listview); - listView.setDivider(null); - - TextView headerView =new TextView(this); - headerView.setText("这是头部"); - headerView.setTextColor(Color.RED); - headerView.setGravity(Gravity.CENTER); - listView.addHeaderView(headerView); - - final ArrayAdapter adapter = createListAdapter(); - AlphaInAnimationAdapter animAdapter = new AlphaInAnimationAdapter(adapter); - animAdapter.setInitialDelayMillis(100); - animAdapter.setAbsListView(listView); - listView.setAdapter(animAdapter); - - Toast.makeText(this, "长按item开始拖拽", Toast.LENGTH_LONG).show(); - listView.setOnItemMovedListener(new DynamicListView.OnItemMovedListener() { - @Override - public void onItemMoved(final int newPosition) { - Toast.makeText(getApplicationContext(), adapter.getItem(newPosition) + " 移动到位置" + newPosition, Toast.LENGTH_SHORT).show(); - } - }); - } -} diff --git a/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/ExpandableListItemActivity.java b/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/ExpandableListItemActivity.java deleted file mode 100644 index e1ea154..0000000 --- a/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/ExpandableListItemActivity.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright 2013 Niek Haarman - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.example.listviewanimationdemo; - -import android.content.Context; -import android.content.Intent; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.os.Bundle; -import android.support.v4.util.LruCache; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.TextView; -import android.widget.Toast; - -import com.example.listviewanimationdemo.base.BaseListActivity; -import com.nhaarman.listviewanimations.itemmanipulation.ExpandableListItemAdapter; -import com.nhaarman.listviewanimations.swinginadapters.prepared.AlphaInAnimationAdapter; - -import java.util.List; - -public class ExpandableListItemActivity extends BaseListActivity { - - private MyExpandableListItemAdapter mExpandableListItemAdapter; - private boolean mLimited; - - public static void actionToExpandableList(Context context) { - Intent intent = new Intent(context, ExpandableListItemActivity.class); - context.startActivity(intent); - } - - @Override - protected void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - mExpandableListItemAdapter = new MyExpandableListItemAdapter(this, getItems()); - AlphaInAnimationAdapter alphaInAnimationAdapter = new AlphaInAnimationAdapter(mExpandableListItemAdapter); - alphaInAnimationAdapter.setAbsListView(getListView()); - alphaInAnimationAdapter.setInitialDelayMillis(500); - getListView().setAdapter(alphaInAnimationAdapter); - - Toast.makeText(this, "点击卡片进行展开收缩操作", Toast.LENGTH_LONG).show(); - } - - private static class MyExpandableListItemAdapter extends ExpandableListItemAdapter { - - private final Context mContext; - private final LruCache mMemoryCache; - - /** - * Creates a new ExpandableListItemAdapter with the specified list, or an empty list if - * items == null. - */ - private MyExpandableListItemAdapter(final Context context, final List items) { - super(context, R.layout.item_expandablelistitem_card, R.id.activity_expandablelistitem_card_title, R.id.activity_expandablelistitem_card_content, items); - mContext = context; - - final int cacheSize = (int) (Runtime.getRuntime().maxMemory() / 1024); - mMemoryCache = new LruCache(cacheSize) { - @Override - protected int sizeOf(final Integer key, final Bitmap bitmap) { - // The cache size will be measured in kilobytes rather than - // number of items. - return bitmap.getRowBytes() * bitmap.getHeight() / 1024; - } - }; - } - - @Override - public View getTitleView(final int position, final View convertView, final ViewGroup parent) { - TextView tv = (TextView) convertView; - if (tv == null) { - tv = new TextView(mContext); - } - tv.setText("卡片"+position); - return tv; - } - - @Override - public View getContentView(final int position, final View convertView, final ViewGroup parent) { - ImageView imageView = (ImageView) convertView; - if (imageView == null) { - imageView = new ImageView(mContext); - imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); - } - - int imageResId; - switch (getItem(position) % 5) { - case 0: - imageResId = R.drawable.img_nature1; - break; - case 1: - imageResId = R.drawable.img_nature2; - break; - case 2: - imageResId = R.drawable.img_nature3; - break; - case 3: - imageResId = R.drawable.img_nature4; - break; - default: - imageResId = R.drawable.img_nature5; - } - - Bitmap bitmap = getBitmapFromMemCache(imageResId); - if (bitmap == null) { - bitmap = BitmapFactory.decodeResource(mContext.getResources(), imageResId); - addBitmapToMemoryCache(imageResId, bitmap); - } - imageView.setImageBitmap(bitmap); - - return imageView; - } - - private void addBitmapToMemoryCache(final int key, final Bitmap bitmap) { - if (getBitmapFromMemCache(key) == null) { - mMemoryCache.put(key, bitmap); - } - } - - private Bitmap getBitmapFromMemCache(final int key) { - return mMemoryCache.get(key); - } - } - - @Override - public boolean onCreateOptionsMenu(final Menu menu) { - getMenuInflater().inflate(R.menu.menu_expandablelistitem, menu); - return super.onCreateOptionsMenu(menu); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.menu_expandable_limit: - mLimited = !mLimited; - item.setChecked(mLimited); - mExpandableListItemAdapter.setLimit(mLimited ? 2 : 0); - return true; - } - return super.onOptionsItemSelected(item); - } -} diff --git a/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/HomeActivity.java b/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/HomeActivity.java deleted file mode 100644 index d34cf1c..0000000 --- a/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/HomeActivity.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.example.listviewanimationdemo; - -import com.example.listviewanimationdemo.itemanimation.ItemAnimationMainActivity; -import com.example.listviewanimationdemo.itemmanipulation.AnimateAdditionActivity; -import com.example.listviewanimationdemo.itemmanipulation.AnimateDismissActivity; -import com.example.listviewanimationdemo.itemmanipulation.DragAndDropActivity; -import com.example.listviewanimationdemo.itemmanipulation.ExpandableListItemActivity; -import com.example.listviewanimationdemo.itemmanipulation.SwipeToDismissActivity; - -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.support.v4.app.FragmentActivity; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.Toast; - -public class HomeActivity extends FragmentActivity implements OnClickListener { - @Override - public void onCreate(Bundle bundle) { - super.onCreate(bundle); - setTitle("ListAnimation动画示例"); - setContentView(R.layout.activity_home); - initView(); - } - - void initView() { - findViewById(R.id.home_item_animation_btn).setOnClickListener(this); - findViewById(R.id.home_swipe_to_dismiss_btn).setOnClickListener(this); - findViewById(R.id.home_item_drag_btn).setOnClickListener(this); - findViewById(R.id.home_multiple_item_dismiss_btn).setOnClickListener( - this); - findViewById(R.id.home_item_expend_btn).setOnClickListener(this); - findViewById(R.id.home_item_add_btn).setOnClickListener(this); - findViewById(R.id.home_item_go_github).setOnClickListener(this); - findViewById(R.id.home_item_go_la_github).setOnClickListener(this); - findViewById(R.id.home_item_go_demo_author_blog).setOnClickListener(this); - } - - @Override - public void onClick(View v) { - int id = v.getId(); - switch (id) { - case R.id.home_item_animation_btn: - ItemAnimationMainActivity.actionToItemAnimationMain(this); - break; - case R.id.home_swipe_to_dismiss_btn: - SwipeToDismissActivity.actionToSwipeDismiss(this); - break; - case R.id.home_item_drag_btn: - DragAndDropActivity.actionToDragAndDrop(this); - break; - case R.id.home_multiple_item_dismiss_btn: - AnimateDismissActivity.actionToAnimateDismiss(this); - break; - case R.id.home_item_expend_btn: - ExpandableListItemActivity.actionToExpandableList(this); - break; - case R.id.home_item_add_btn: - AnimateAdditionActivity.actionToItemAddition(this); - break; - - case R.id.home_item_go_github: - Toast.makeText(this, "正在转向demo项目主页...", Toast.LENGTH_SHORT).show(); - openBrower("https://github.com/android-cn/android-open-project-demo"); - break; - case R.id.home_item_go_la_github: - Toast.makeText(this, "正在转向ListviewAnimation项目主页...", - Toast.LENGTH_SHORT).show(); - openBrower("https://github.com/nhaarman/ListViewAnimations"); - break; - case R.id.home_item_go_demo_author_blog: - Toast.makeText(this, "正在转向Demo作者博客主页...", - Toast.LENGTH_SHORT).show(); - openBrower("http://waylife.github.io"); - break; - default: - break; - } - } - - public void openBrower(String url) { - Uri uri = Uri.parse(url); - Intent intent = new Intent(Intent.ACTION_VIEW, uri); - intent.setPackage("com.android.browser"); - startActivity(intent); - } -} diff --git a/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/SwipeToDismissActivity.java b/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/SwipeToDismissActivity.java deleted file mode 100644 index 997add4..0000000 --- a/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/SwipeToDismissActivity.java +++ /dev/null @@ -1,149 +0,0 @@ -package com.example.listviewanimationdemo; - -import java.util.Arrays; - -import com.example.listviewanimationdemo.base.BaseListActivity; -import com.nhaarman.listviewanimations.ArrayAdapter; -import com.nhaarman.listviewanimations.itemmanipulation.OnDismissCallback; -import com.nhaarman.listviewanimations.itemmanipulation.swipedismiss.SwipeDismissAdapter; -import com.nhaarman.listviewanimations.itemmanipulation.swipedismiss.contextualundo.ContextualUndoAdapter; -import com.nhaarman.listviewanimations.itemmanipulation.swipedismiss.contextualundo.ContextualUndoAdapter.CountDownFormatter; -import com.nhaarman.listviewanimations.itemmanipulation.swipedismiss.contextualundo.ContextualUndoAdapter.DeleteItemCallback; - -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.support.v4.app.FragmentActivity; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AbsListView; -import android.widget.TextView; -import android.widget.Toast; - -public class SwipeToDismissActivity extends BaseListActivity implements OnDismissCallback, DeleteItemCallback { - - public static void actionToSwipeDismiss(Context context) { - Intent intent = new Intent(context, SwipeToDismissActivity.class); - context.startActivity(intent); - } - - private ArrayAdapter mAdapter; - - @Override - protected void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - mAdapter = createListAdapter(); - setSwipeDismissAdapter(); - } - - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.swipe_to_dismiss, menu); - return true; - } - - public boolean onMenuItemSelected(int featureId, MenuItem item) { - int id = item.getItemId(); - switch (id) { - case R.id.swipe_menu_main: - setSwipeDismissAdapter(); - break; - case R.id.swipe_menu_with_undo: - setContextualUndoAdapter(); - break; - case R.id.swipe_menu_with_undo_2: - setContextualUndoWithTimedDeleteAdapter(); - break; - case R.id.swipe_menu_with_undo_3: - setContextualUndoWithTimedDeleteAndCountDownAdapter(); - break; - default: - break; - } - return true; - } - - - void initView() { - // findViewById(R.id.home_item_animation_btn).setOnClickListener(this); - // findViewById(R.id.home_item_expend_btn).setOnClickListener(this); - // findViewById(R.id.home_swipe_to_dismiss_btn).setOnClickListener(this); - } - - - private void setSwipeDismissAdapter() { - SwipeDismissAdapter adapter = new SwipeDismissAdapter(mAdapter, this); - adapter.setAbsListView(getListView()); - getListView().setAdapter(adapter); - } - - @Override - public void onDismiss(final AbsListView listView, final int[] reverseSortedPositions) { - for (int position : reverseSortedPositions) { - mAdapter.remove(position); - } - Toast.makeText(this, "Removed positions: " + Arrays.toString(reverseSortedPositions), Toast.LENGTH_SHORT).show(); - } - - private void setContextualUndoAdapter() { - ContextualUndoAdapter adapter = new ContextualUndoAdapter(mAdapter, R.layout.item_undo_row, R.id.undo_row_undobutton, this); - adapter.setAbsListView(getListView()); - getListView().setAdapter(adapter); - } - - @Override - public void deleteItem(final int position) { - mAdapter.remove(position); - mAdapter.notifyDataSetChanged(); - } - - private void setContextualUndoWithTimedDeleteAdapter() { - ContextualUndoAdapter adapter = new ContextualUndoAdapter(mAdapter, R.layout.item_undo_row, R.id.undo_row_undobutton, 3000, this); - adapter.setAbsListView(getListView()); - getListView().setAdapter(adapter); - } - - private void setContextualUndoWithTimedDeleteAndCountDownAdapter() { - ContextualUndoAdapter adapter = new ContextualUndoAdapter(mAdapter, R.layout.item_undo_row, R.id.undo_row_undobutton, 3000, R.id.undo_row_texttv, this, new MyFormatCountDownCallback()); - adapter.setAbsListView(getListView()); - getListView().setAdapter(adapter); - } - - private class MyFormatCountDownCallback implements CountDownFormatter { - - @Override - public String getCountDownString(final long millisUntilFinished) { - int seconds = (int) Math.ceil(millisUntilFinished / 1000.0); - - if (seconds > 0) { - return seconds+"s"; - } - return "..."; - } - } - - - private class AnimSelectionAdapter extends ArrayAdapter { - - public AnimSelectionAdapter() { - addAll("Swipe-To-Dismiss", "Contextual Undo", "CU - Timed Delete", "CU - Count Down"); - } - - @Override - public View getView(final int position, final View convertView, final ViewGroup parent) { - TextView tv = (TextView) convertView; - if (tv == null) { - tv = (TextView) LayoutInflater.from(SwipeToDismissActivity.this).inflate(android.R.layout.simple_list_item_1, parent, false); - } - - tv.setText(getItem(position)); - - return tv; - } - } - -} diff --git a/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/base/BaseListActivity.java b/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/base/BaseListActivity.java deleted file mode 100644 index 58d8ddb..0000000 --- a/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/base/BaseListActivity.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.example.listviewanimationdemo.base; - -import java.util.ArrayList; - - -import com.example.listviewanimationdemo.R; -import com.nhaarman.listviewanimations.ArrayAdapter; - -import android.content.Context; -import android.os.Bundle; -import android.support.v4.app.FragmentActivity; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ListView; -import android.widget.TextView; - -public class BaseListActivity extends FragmentActivity { - - private ListView mListView; - - @Override - protected void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_baselist); - mListView = (ListView) findViewById(R.id.activity_baselist_listview); - mListView.setDivider(null); - } - - public ListView getListView() { - return mListView; - } - - protected ArrayAdapter createListAdapter() { - return new MyListAdapter(this, getItems()); - } - - public static ArrayList getItems() { - ArrayList items = new ArrayList(); - for (int i = 0; i < 1000; i++) { - items.add(i); - } - return items; - } - - private static class MyListAdapter extends ArrayAdapter { - - private final Context mContext; - - public MyListAdapter(final Context context, - final ArrayList items) { - super(items); - mContext = context; - } - - @Override - public long getItemId(final int position) { - return getItem(position).hashCode(); - } - - @Override - public boolean hasStableIds() { - return true; - } - - @Override - public View getView(final int position, final View convertView, - final ViewGroup parent) { - TextView tv = (TextView) convertView; - if (tv == null) { - tv = (TextView) LayoutInflater.from(mContext).inflate( - R.layout.item_list_row, parent, false); - } - tv.setText("第 " + getItem(position)+"行"); - return tv; - } - } - -} diff --git a/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/itemanimation/GoogleCardsActivity.java b/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/itemanimation/GoogleCardsActivity.java deleted file mode 100644 index de30cdc..0000000 --- a/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/itemanimation/GoogleCardsActivity.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright 2013 Niek Haarman - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.example.listviewanimationdemo.itemanimation; - -import java.util.ArrayList; - -import android.content.Context; -import android.content.Intent; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.os.Bundle; -import android.support.v4.app.FragmentActivity; -import android.support.v4.util.LruCache; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AbsListView; -import android.widget.ImageView; -import android.widget.ListView; -import android.widget.TextView; - -import com.example.listviewanimationdemo.R; -import com.nhaarman.listviewanimations.ArrayAdapter; -import com.nhaarman.listviewanimations.itemmanipulation.OnDismissCallback; -import com.nhaarman.listviewanimations.itemmanipulation.swipedismiss.SwipeDismissAdapter; -import com.nhaarman.listviewanimations.swinginadapters.prepared.SwingBottomInAnimationAdapter; - -public class GoogleCardsActivity extends FragmentActivity implements OnDismissCallback { - - private GoogleCardsAdapter mGoogleCardsAdapter; - - public static void actionToGoogleCard(Context context){ - Intent intent =new Intent(context,GoogleCardsActivity.class); - context.startActivity(intent); - } - - @Override - protected void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setTitle("Google Card"); - setContentView(R.layout.activity_googlecards); - - ListView listView = (ListView) findViewById(R.id.activity_googlecards_listview); - - mGoogleCardsAdapter = new GoogleCardsAdapter(this); - SwingBottomInAnimationAdapter swingBottomInAnimationAdapter = new SwingBottomInAnimationAdapter(new SwipeDismissAdapter(mGoogleCardsAdapter, this)); - swingBottomInAnimationAdapter.setInitialDelayMillis(300); - swingBottomInAnimationAdapter.setAbsListView(listView); - - listView.setAdapter(swingBottomInAnimationAdapter); - - mGoogleCardsAdapter.addAll(getItems()); - } - - private ArrayList getItems() { - ArrayList items = new ArrayList(); - for (int i = 0; i < 100; i++) { - items.add(i); - } - return items; - } - - @Override - public void onDismiss(final AbsListView listView, final int[] reverseSortedPositions) { - for (int position : reverseSortedPositions) { - mGoogleCardsAdapter.remove(position); - } - } - - private static class GoogleCardsAdapter extends ArrayAdapter { - - private final Context mContext; - private final LruCache mMemoryCache; - - public GoogleCardsAdapter(final Context context) { - mContext = context; - - final int cacheSize = (int) (Runtime.getRuntime().maxMemory() / 1024); - mMemoryCache = new LruCache(cacheSize) { - @Override - protected int sizeOf(final Integer key, final Bitmap bitmap) { - // The cache size will be measured in kilobytes rather than - // number of items. - return bitmap.getRowBytes() * bitmap.getHeight() / 1024; - } - }; - } - - @Override - public View getView(final int position, final View convertView, final ViewGroup parent) { - ViewHolder viewHolder; - View view = convertView; - if (view == null) { - view = LayoutInflater.from(mContext).inflate(R.layout.activity_googlecards_card, parent, false); - - viewHolder = new ViewHolder(); - viewHolder.textView = (TextView) view.findViewById(R.id.activity_googlecards_card_textview); - view.setTag(viewHolder); - - viewHolder.imageView = (ImageView) view.findViewById(R.id.activity_googlecards_card_imageview); - } else { - viewHolder = (ViewHolder) view.getTag(); - } - - viewHolder.textView.setText("这是第 " + (getItem(position) + 1)+"个卡片"); - setImageView(viewHolder, position); - - return view; - } - - private void setImageView(final ViewHolder viewHolder, final int position) { - int imageResId; - switch (getItem(position) % 5) { - case 0: - imageResId = R.drawable.img_nature1; - break; - case 1: - imageResId = R.drawable.img_nature2; - break; - case 2: - imageResId = R.drawable.img_nature3; - break; - case 3: - imageResId = R.drawable.img_nature4; - break; - default: - imageResId = R.drawable.img_nature5; - } - - Bitmap bitmap = getBitmapFromMemCache(imageResId); - if (bitmap == null) { - bitmap = BitmapFactory.decodeResource(mContext.getResources(), imageResId); - addBitmapToMemoryCache(imageResId, bitmap); - } - viewHolder.imageView.setImageBitmap(bitmap); - } - - private void addBitmapToMemoryCache(final int key, final Bitmap bitmap) { - if (getBitmapFromMemCache(key) == null) { - mMemoryCache.put(key, bitmap); - } - } - - private Bitmap getBitmapFromMemCache(final int key) { - return mMemoryCache.get(key); - } - - private static class ViewHolder { - TextView textView; - ImageView imageView; - } - } -} diff --git a/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/itemanimation/GridViewActivity.java b/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/itemanimation/GridViewActivity.java deleted file mode 100644 index f6371fe..0000000 --- a/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/itemanimation/GridViewActivity.java +++ /dev/null @@ -1,140 +0,0 @@ -package com.example.listviewanimationdemo.itemanimation; - -import java.util.ArrayList; -import java.util.List; -import android.annotation.SuppressLint; -import android.content.Context; -import android.content.Intent; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.os.Build; -import android.os.Bundle; -import android.support.v4.app.FragmentActivity; -import android.support.v4.util.LruCache; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.GridView; -import android.widget.ImageView; - -import com.example.listviewanimationdemo.R; -import com.nhaarman.listviewanimations.ArrayAdapter; -import com.nhaarman.listviewanimations.swinginadapters.prepared.SwingBottomInAnimationAdapter; - -public class GridViewActivity extends FragmentActivity { - - public static void actionToGridView(Context context) { - Intent intent = new Intent(context, GridViewActivity.class); - context.startActivity(intent); - } - - @SuppressLint("InlinedApi") - @Override - protected void onCreate(final Bundle savedInstanceState) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - getWindow() - .addFlags( - android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); - } - super.onCreate(savedInstanceState); - setTitle("Gridview动画"); - setContentView(R.layout.activity_gridview); - - GridView gridView = (GridView) findViewById(R.id.activity_gridview_gv); - SwingBottomInAnimationAdapter swingBottomInAnimationAdapter = new SwingBottomInAnimationAdapter( - new MyAdapter(this, getItems())); - swingBottomInAnimationAdapter.setAbsListView(gridView); - swingBottomInAnimationAdapter.setInitialDelayMillis(300); - gridView.setAdapter(swingBottomInAnimationAdapter); - - } - - private ArrayList getItems() { - ArrayList items = new ArrayList(); - for (int i = 0; i < 100; i++) { - items.add(i); - } - return items; - } - - private static class MyAdapter extends ArrayAdapter { - - private final Context mContext; - private final LruCache mMemoryCache; - - public MyAdapter(final Context context, final List list) { - super(list); - mContext = context; - - final int cacheSize = (int) (Runtime.getRuntime().maxMemory() / 1024); - mMemoryCache = new LruCache(cacheSize) { - @Override - protected int sizeOf(final Integer key, final Bitmap bitmap) { - // The cache size will be measured in kilobytes rather than - // number of items. - return bitmap.getRowBytes() * bitmap.getHeight() / 1024; - } - }; - } - - @Override - public View getView(final int position, final View convertView, - final ViewGroup viewGroup) { - ImageView imageView = (ImageView) convertView; - - if (imageView == null) { - imageView = new ImageView(mContext); - imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); - } - - int imageResId; - switch (getItem(position) % 5) { - case 0: - imageResId = R.drawable.img_nature1; - break; - case 1: - imageResId = R.drawable.img_nature2; - break; - case 2: - imageResId = R.drawable.img_nature3; - break; - case 3: - imageResId = R.drawable.img_nature4; - break; - default: - imageResId = R.drawable.img_nature5; - } - - Bitmap bitmap = getBitmapFromMemCache(imageResId); - if (bitmap == null) { - bitmap = BitmapFactory.decodeResource(mContext.getResources(), - imageResId); - addBitmapToMemoryCache(imageResId, bitmap); - } - imageView.setImageBitmap(bitmap); - - return imageView; - } - - private void addBitmapToMemoryCache(final int key, final Bitmap bitmap) { - if (getBitmapFromMemCache(key) == null) { - mMemoryCache.put(key, bitmap); - } - } - - private Bitmap getBitmapFromMemCache(final int key) { - return mMemoryCache.get(key); - } - } - - @Override - public boolean onOptionsItemSelected(final MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - finish(); - return true; - default: - return super.onOptionsItemSelected(item); - } - } -} diff --git a/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/itemanimation/ItemAnimationActivity.java b/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/itemanimation/ItemAnimationActivity.java deleted file mode 100644 index 1446320..0000000 --- a/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/itemanimation/ItemAnimationActivity.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2013 Niek Haarman - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.example.listviewanimationdemo.itemanimation; - -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.BaseAdapter; -import android.widget.TextView; - -import com.example.listviewanimationdemo.R; -import com.example.listviewanimationdemo.base.BaseListActivity; -import com.nhaarman.listviewanimations.ArrayAdapter; -import com.nhaarman.listviewanimations.swinginadapters.AnimationAdapter; -import com.nhaarman.listviewanimations.swinginadapters.prepared.AlphaInAnimationAdapter; -import com.nhaarman.listviewanimations.swinginadapters.prepared.ScaleInAnimationAdapter; -import com.nhaarman.listviewanimations.swinginadapters.prepared.SwingBottomInAnimationAdapter; -import com.nhaarman.listviewanimations.swinginadapters.prepared.SwingLeftInAnimationAdapter; -import com.nhaarman.listviewanimations.swinginadapters.prepared.SwingRightInAnimationAdapter; - -import java.util.ArrayList; - -public class ItemAnimationActivity extends BaseListActivity { - - private BaseAdapter mAdapter; - - public static void actionToItemAnimation(Context context) { - Intent intent = new Intent(context, ItemAnimationActivity.class); - context.startActivity(intent); - } - @Override - protected void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setTitle("item动画"); - mAdapter = new MyAdapter(this, getItems()); - setAlphaAdapter(); - } - - private void setAlphaAdapter() { - AnimationAdapter animAdapter = new AlphaInAnimationAdapter(mAdapter); - animAdapter.setAbsListView(getListView()); - getListView().setAdapter(animAdapter); - } - - private void setLeftAdapter() { - AnimationAdapter animAdapter = new SwingLeftInAnimationAdapter(mAdapter); - animAdapter.setAbsListView(getListView()); - getListView().setAdapter(animAdapter); - } - - private void setRightAdapter() { - AnimationAdapter animAdapter = new SwingRightInAnimationAdapter( - mAdapter); - animAdapter.setAbsListView(getListView()); - getListView().setAdapter(animAdapter); - } - - private void setBottomAdapter() { - AnimationAdapter animAdapter = new SwingBottomInAnimationAdapter( - mAdapter); - animAdapter.setAbsListView(getListView()); - getListView().setAdapter(animAdapter); - } - - private void setBottomRightAdapter() { - AnimationAdapter animAdapter = new SwingBottomInAnimationAdapter( - new SwingRightInAnimationAdapter(mAdapter)); - animAdapter.setAbsListView(getListView()); - getListView().setAdapter(animAdapter); - } - - private void setScaleAdapter() { - AnimationAdapter animAdapter = new ScaleInAnimationAdapter(mAdapter); - animAdapter.setAbsListView(getListView()); - getListView().setAdapter(animAdapter); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.menu_item_animation, menu); - return true; - } - - @Override - public boolean onMenuItemSelected(int featureId, MenuItem item) { - int id = item.getItemId(); - switch (id) { - case R.id.menu_item_animation_alpha: - setAlphaAdapter(); - break; - case R.id.menu_item_animation_left: - setLeftAdapter(); - break; - case R.id.menu_item_animation_right: - setRightAdapter(); - break; - case R.id.menu_item_animation_bottom: - setBottomAdapter(); - break; - case R.id.menu_item_animation_bottom_right: - setBottomRightAdapter(); - break; - case R.id.menu_item_animation_scale: - setScaleAdapter(); - break; - default: - break; - } - return true; - } - - /* Non-ListViewAnimations related stuff below */ - - class MyAdapter extends ArrayAdapter { - - private final Context mContext; - - public MyAdapter(final Context context, final ArrayList items) { - super(items); - mContext = context; - } - - @Override - public long getItemId(final int position) { - return getItem(position).hashCode(); - } - - @Override - public View getView(final int position, final View convertView, - final ViewGroup parent) { - TextView tv = (TextView) convertView; - if (tv == null) { - tv = (TextView) LayoutInflater.from(mContext).inflate( - R.layout.item_list_row, parent, false); - } - tv.setText("******第 " + getItem(position) + "行******"); - return tv; - } - } -} \ No newline at end of file diff --git a/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/itemanimation/ItemAnimationMainActivity.java b/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/itemanimation/ItemAnimationMainActivity.java deleted file mode 100644 index 2f66a6b..0000000 --- a/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/itemanimation/ItemAnimationMainActivity.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.example.listviewanimationdemo.itemanimation; - -import com.example.listviewanimationdemo.R; - -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.support.v4.app.FragmentActivity; -import android.view.View; -import android.view.View.OnClickListener; - -public class ItemAnimationMainActivity extends FragmentActivity implements - OnClickListener { - - public static void actionToItemAnimationMain(Context context) { - Intent intent = new Intent(context, ItemAnimationMainActivity.class); - context.startActivity(intent); - } - - @Override - public void onCreate(Bundle bundle) { - super.onCreate(bundle); - setTitle("item动画主页"); - setContentView(R.layout.activity_item_animation_main); - findViewById(R.id.item_animation_main_1).setOnClickListener(this); - findViewById(R.id.item_animation_main_google_card).setOnClickListener( - this); - findViewById(R.id.item_animation_main_gridview) - .setOnClickListener(this); - } - - @Override - public void onClick(View v) { - int id = v.getId(); - switch (id) { - case R.id.item_animation_main_1: - ItemAnimationActivity.actionToItemAnimation(this); - break; - case R.id.item_animation_main_google_card: - GoogleCardsActivity.actionToGoogleCard(this); - break; - case R.id.item_animation_main_gridview: - GridViewActivity.actionToGridView(this); - break; - default: - break; - } - } -} diff --git a/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/itemmanipulation/AnimateAdditionActivity.java b/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/itemmanipulation/AnimateAdditionActivity.java deleted file mode 100644 index 8e72a86..0000000 --- a/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/itemmanipulation/AnimateAdditionActivity.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2013 Niek Haarman - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.example.listviewanimationdemo.itemmanipulation; - -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.TextView; -import android.widget.Toast; - -import com.example.listviewanimationdemo.R; -import com.example.listviewanimationdemo.base.BaseListActivity; -import com.nhaarman.listviewanimations.ArrayAdapter; -import com.nhaarman.listviewanimations.itemmanipulation.AnimateAdditionAdapter; - -import java.util.ArrayList; - -public class AnimateAdditionActivity extends BaseListActivity implements - AdapterView.OnItemClickListener { - - private int mAddedItemNumber; - private AnimateAdditionAdapter mAnimateAdditionAdapter; - - public static void actionToItemAddition(Context context) { - Intent intent = new Intent(context, AnimateAdditionActivity.class); - context.startActivity(intent); - } - - @Override - protected void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setTitle("增加item"); - MyAdapter myAdapter = new MyAdapter(this, getStringItems()); - - mAnimateAdditionAdapter = new AnimateAdditionAdapter(myAdapter); - mAnimateAdditionAdapter.setListView(getListView()); - - getListView().setAdapter(mAnimateAdditionAdapter); - getListView().setOnItemClickListener(this); - - Toast.makeText(this, "点击某一项来增加一项", Toast.LENGTH_LONG).show(); - } - - private static ArrayList getStringItems() { - ArrayList items = new ArrayList(); - for (int i = 0; i < 1000; i++) { - items.add(">>>第 " + i + "行==="); - } - return items; - } - - @Override - public void onItemClick(final AdapterView parent, final View view, - final int position, final long id) { - mAnimateAdditionAdapter.insert(position, "***新增加的item: " - + mAddedItemNumber); - mAddedItemNumber++; - } - - private static class MyAdapter extends ArrayAdapter { - - private final Context mContext; - - public MyAdapter(final Context context, final ArrayList items) { - super(items); - mContext = context; - } - - @Override - public long getItemId(final int position) { - return getItem(position).hashCode(); - } - - @Override - public View getView(final int position, final View convertView, - final ViewGroup parent) { - TextView tv = (TextView) convertView; - if (tv == null) { - tv = (TextView) LayoutInflater.from(mContext).inflate( - R.layout.item_list_row, parent, false); - } - tv.setText(getItem(position)); - return tv; - } - } -} diff --git a/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/itemmanipulation/DragAndDropActivity.java b/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/itemmanipulation/DragAndDropActivity.java deleted file mode 100644 index 99d033e..0000000 --- a/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/itemmanipulation/DragAndDropActivity.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2013 Niek Haarman - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.example.listviewanimationdemo.itemmanipulation; - -import android.content.Context; -import android.content.Intent; -import android.graphics.Color; -import android.os.Bundle; -import android.view.Gravity; -import android.widget.TextView; -import android.widget.Toast; - -import com.example.listviewanimationdemo.R; -import com.example.listviewanimationdemo.R.id; -import com.example.listviewanimationdemo.R.layout; -import com.example.listviewanimationdemo.base.BaseListActivity; -import com.nhaarman.listviewanimations.ArrayAdapter; -import com.nhaarman.listviewanimations.swinginadapters.prepared.AlphaInAnimationAdapter; -import com.nhaarman.listviewanimations.widget.DynamicListView; - -public class DragAndDropActivity extends BaseListActivity { - - public static void actionToDragAndDrop(Context context) { - Intent intent = new Intent(context, DragAndDropActivity.class); - context.startActivity(intent); - } - - @Override - protected void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setTitle("item拖动"); - setContentView(R.layout.activity_draganddrop); - - DynamicListView listView = (DynamicListView) findViewById(R.id.activity_draganddrop_listview); - listView.setDivider(null); - - TextView headerView =new TextView(this); - headerView.setText("这是头部"); - headerView.setTextColor(Color.RED); - headerView.setGravity(Gravity.CENTER); - listView.addHeaderView(headerView); - - final ArrayAdapter adapter = createListAdapter(); - AlphaInAnimationAdapter animAdapter = new AlphaInAnimationAdapter(adapter); - animAdapter.setInitialDelayMillis(100); - animAdapter.setAbsListView(listView); - listView.setAdapter(animAdapter); - - Toast.makeText(this, "长按item开始拖拽", Toast.LENGTH_LONG).show(); - listView.setOnItemMovedListener(new DynamicListView.OnItemMovedListener() { - @Override - public void onItemMoved(final int newPosition) { - Toast.makeText(getApplicationContext(), adapter.getItem(newPosition) + " 移动到位置" + newPosition, Toast.LENGTH_SHORT).show(); - } - }); - } -} diff --git a/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/itemmanipulation/SwipeToDismissActivity.java b/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/itemmanipulation/SwipeToDismissActivity.java deleted file mode 100644 index fced4f7..0000000 --- a/listview-animations-demo/ListviewAnimationDemo/src/com/example/listviewanimationdemo/itemmanipulation/SwipeToDismissActivity.java +++ /dev/null @@ -1,154 +0,0 @@ -package com.example.listviewanimationdemo.itemmanipulation; - -import java.util.Arrays; - -import com.example.listviewanimationdemo.R; -import com.example.listviewanimationdemo.R.id; -import com.example.listviewanimationdemo.R.layout; -import com.example.listviewanimationdemo.R.menu; -import com.example.listviewanimationdemo.base.BaseListActivity; -import com.nhaarman.listviewanimations.ArrayAdapter; -import com.nhaarman.listviewanimations.itemmanipulation.OnDismissCallback; -import com.nhaarman.listviewanimations.itemmanipulation.swipedismiss.SwipeDismissAdapter; -import com.nhaarman.listviewanimations.itemmanipulation.swipedismiss.contextualundo.ContextualUndoAdapter; -import com.nhaarman.listviewanimations.itemmanipulation.swipedismiss.contextualundo.ContextualUndoAdapter.CountDownFormatter; -import com.nhaarman.listviewanimations.itemmanipulation.swipedismiss.contextualundo.ContextualUndoAdapter.DeleteItemCallback; - -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.support.v4.app.FragmentActivity; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AbsListView; -import android.widget.TextView; -import android.widget.Toast; - -public class SwipeToDismissActivity extends BaseListActivity implements OnDismissCallback, DeleteItemCallback { - - public static void actionToSwipeDismiss(Context context) { - Intent intent = new Intent(context, SwipeToDismissActivity.class); - context.startActivity(intent); - } - - private ArrayAdapter mAdapter; - - @Override - protected void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setTitle("item滑动删除"); - mAdapter = createListAdapter(); - setSwipeDismissAdapter(); - } - - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.menu_swipe_to_dismiss, menu); - return true; - } - - public boolean onMenuItemSelected(int featureId, MenuItem item) { - int id = item.getItemId(); - switch (id) { - case R.id.swipe_menu_main: - setSwipeDismissAdapter(); - break; - case R.id.swipe_menu_with_undo: - setContextualUndoAdapter(); - break; - case R.id.swipe_menu_with_undo_2: - setContextualUndoWithTimedDeleteAdapter(); - break; - case R.id.swipe_menu_with_undo_3: - setContextualUndoWithTimedDeleteAndCountDownAdapter(); - break; - default: - break; - } - return true; - } - - - void initView() { - // findViewById(R.id.home_item_animation_btn).setOnClickListener(this); - // findViewById(R.id.home_item_expend_btn).setOnClickListener(this); - // findViewById(R.id.home_swipe_to_dismiss_btn).setOnClickListener(this); - } - - - private void setSwipeDismissAdapter() { - SwipeDismissAdapter adapter = new SwipeDismissAdapter(mAdapter, this); - adapter.setAbsListView(getListView()); - getListView().setAdapter(adapter); - } - - @Override - public void onDismiss(final AbsListView listView, final int[] reverseSortedPositions) { - for (int position : reverseSortedPositions) { - mAdapter.remove(position); - } - Toast.makeText(this, "Removed positions: " + Arrays.toString(reverseSortedPositions), Toast.LENGTH_SHORT).show(); - } - - private void setContextualUndoAdapter() { - ContextualUndoAdapter adapter = new ContextualUndoAdapter(mAdapter, R.layout.item_undo_row, R.id.undo_row_undobutton, this); - adapter.setAbsListView(getListView()); - getListView().setAdapter(adapter); - } - - @Override - public void deleteItem(final int position) { - mAdapter.remove(position); - mAdapter.notifyDataSetChanged(); - } - - private void setContextualUndoWithTimedDeleteAdapter() { - ContextualUndoAdapter adapter = new ContextualUndoAdapter(mAdapter, R.layout.item_undo_row, R.id.undo_row_undobutton, 3000, this); - adapter.setAbsListView(getListView()); - getListView().setAdapter(adapter); - } - - private void setContextualUndoWithTimedDeleteAndCountDownAdapter() { - ContextualUndoAdapter adapter = new ContextualUndoAdapter(mAdapter, R.layout.item_undo_row, R.id.undo_row_undobutton, 3000, R.id.undo_row_texttv, this, new MyFormatCountDownCallback()); - adapter.setAbsListView(getListView()); - getListView().setAdapter(adapter); - } - - private class MyFormatCountDownCallback implements CountDownFormatter { - - @Override - public String getCountDownString(final long millisUntilFinished) { - int seconds = (int) Math.ceil(millisUntilFinished / 1000.0); - - if (seconds > 0) { - return seconds+"s"; - } - return "..."; - } - } - - - private class AnimSelectionAdapter extends ArrayAdapter { - - public AnimSelectionAdapter() { - addAll("Swipe-To-Dismiss", "Contextual Undo", "CU - Timed Delete", "CU - Count Down"); - } - - @Override - public View getView(final int position, final View convertView, final ViewGroup parent) { - TextView tv = (TextView) convertView; - if (tv == null) { - tv = (TextView) LayoutInflater.from(SwipeToDismissActivity.this).inflate(android.R.layout.simple_list_item_1, parent, false); - } - - tv.setText(getItem(position)); - - return tv; - } - } - -} diff --git a/listview-animations-demo/ListviewAnimationLib/.classpath b/listview-animations-demo/ListviewAnimationLib/.classpath deleted file mode 100644 index 5176974..0000000 --- a/listview-animations-demo/ListviewAnimationLib/.classpath +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/listview-animations-demo/ListviewAnimationLib/.project b/listview-animations-demo/ListviewAnimationLib/.project deleted file mode 100644 index b56e198..0000000 --- a/listview-animations-demo/ListviewAnimationLib/.project +++ /dev/null @@ -1,33 +0,0 @@ - - - Library-ListViewAnimations - - - - - - com.android.ide.eclipse.adt.ResourceManagerBuilder - - - - - com.android.ide.eclipse.adt.PreCompilerBuilder - - - - - org.eclipse.jdt.core.javabuilder - - - - - com.android.ide.eclipse.adt.ApkBuilder - - - - - - com.android.ide.eclipse.adt.AndroidNature - org.eclipse.jdt.core.javanature - - diff --git a/listview-animations-demo/ListviewAnimationLib/.settings/org.eclipse.jdt.core.prefs b/listview-animations-demo/ListviewAnimationLib/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index b080d2d..0000000 --- a/listview-animations-demo/ListviewAnimationLib/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.source=1.6 diff --git a/listview-animations-demo/ListviewAnimationLib/AndroidManifest.xml b/listview-animations-demo/ListviewAnimationLib/AndroidManifest.xml deleted file mode 100644 index 3aa0362..0000000 --- a/listview-animations-demo/ListviewAnimationLib/AndroidManifest.xml +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/listview-animations-demo/ListviewAnimationLib/build.gradle b/listview-animations-demo/ListviewAnimationLib/build.gradle deleted file mode 100644 index 8134bdc..0000000 --- a/listview-animations-demo/ListviewAnimationLib/build.gradle +++ /dev/null @@ -1,44 +0,0 @@ -apply plugin: 'android-library' - - -dependencies { - compile 'com.nineoldandroids:library:2.4.0' - - instrumentTestCompile ('org.mockito:mockito-core:1.9.5') { exclude group: 'org.hamcrest' } - instrumentTestCompile ('com.google.dexmaker:dexmaker-mockito:1.0') { exclude group: 'org.hamcrest' } - instrumentTestCompile ('junit:junit:4.11') { exclude group: 'org.hamcrest' } - instrumentTestCompile 'org.hamcrest:hamcrest-all:1.3' -} - -android { - compileSdkVersion 19 - buildToolsVersion '19.0.1' - - sourceSets { - main { - manifest.srcFile 'AndroidManifest.xml' - java.srcDirs = ['src'] - resources.srcDirs = ['src'] - res.srcDirs = ['res'] - assets.srcDirs = ['assets'] - } - - instrumentTest.setRoot('tests') - instrumentTest { - java.srcDirs = ['tests/java'] - } - } - - defaultConfig { - minSdkVersion 8 - targetSdkVersion 19 - versionName project.VERSION_NAME - versionCode Integer.parseInt(new Date().format('yyyyMMddHH')) - } - - packagingOptions { - exclude 'LICENSE.txt' - } -} - -apply from: '../maven_push.gradle' \ No newline at end of file diff --git a/listview-animations-demo/ListviewAnimationLib/gradle.properties b/listview-animations-demo/ListviewAnimationLib/gradle.properties deleted file mode 100644 index f7d3911..0000000 --- a/listview-animations-demo/ListviewAnimationLib/gradle.properties +++ /dev/null @@ -1,3 +0,0 @@ -POM_NAME=ListViewAnimations Library -POM_ARTIFACT_ID=library -POM_PACKAGING=aar \ No newline at end of file diff --git a/listview-animations-demo/ListviewAnimationLib/lint.xml b/listview-animations-demo/ListviewAnimationLib/lint.xml deleted file mode 100644 index ee0eead..0000000 --- a/listview-animations-demo/ListviewAnimationLib/lint.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/listview-animations-demo/ListviewAnimationLib/pom.xml b/listview-animations-demo/ListviewAnimationLib/pom.xml deleted file mode 100644 index 8e8555e..0000000 --- a/listview-animations-demo/ListviewAnimationLib/pom.xml +++ /dev/null @@ -1,142 +0,0 @@ - - 4.0.0 - - - com.haarman.listviewanimations - parent - 1.0.0-SNAPSHOT - - - listviewanimations - apklib - - ListViewAnimations (Library) - - - - - com.google.android - android - provided - - - - - com.nineoldandroids - library - - - - - junit - junit - test - - - - - src - - - com.jayway.maven.plugins.android.generation2 - android-maven-plugin - true - - - runLint - compile - - lint - - - - - - - org.codehaus.mojo - build-helper-maven-plugin - - - package - - attach-artifact - - - - - jar - ${project.build.directory}/${project.build.finalName}.jar - - - - - - - - - org.apache.maven.plugins - maven-source-plugin - - - attach-sources - - jar - - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - - - attach-javadocs - - jar - - - true - - - - - - - org.apache.maven.plugins - maven-release-plugin - - - - - - - - release - - - performRelease - true - - - - - - org.apache.maven.plugins - maven-gpg-plugin - ${maven-gpg-plugin.version} - - - sign-artifacts - verify - - sign - - - - - - - - - \ No newline at end of file diff --git a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/ArrayAdapter.java b/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/ArrayAdapter.java deleted file mode 100644 index 84e16bb..0000000 --- a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/ArrayAdapter.java +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Copyright 2013 Niek Haarman - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.nhaarman.listviewanimations; - -import android.widget.BaseAdapter; - -import com.nhaarman.listviewanimations.itemmanipulation.AnimateAdditionAdapter; -import com.nhaarman.listviewanimations.widget.DynamicListView; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; - -/** - * A {@code true} {@link ArrayList} adapter providing access to all ArrayList methods. - * Also implements {@link DynamicListView.Swappable} for easy object swapping, and {@link AnimateAdditionAdapter.Insertable} for inserting objects. - */ -@SuppressWarnings("UnusedDeclaration") -public abstract class ArrayAdapter extends BaseAdapter implements List, DynamicListView.Swappable, AnimateAdditionAdapter.Insertable { - - protected List mItems; - - /** - * Creates a new ArrayAdapter with an empty {@code List} . - */ - public ArrayAdapter() { - this(null); - } - - /** - * Creates a new {@link ArrayAdapter} using given {@code List} , or an empty {@code List} if objects == null. - */ - public ArrayAdapter(final List objects) { - this(objects, false); - } - - /** - * Creates a new {@link ArrayAdapter}, using (a copy of) given {@code List} , or an empty {@code List} if objects = null. - * @param copyList {@code true} to create a copy of the {@code List} , {@code false} to reuse the reference. - */ - public ArrayAdapter(final List objects, final boolean copyList) { - if (objects != null) { - if (copyList) { - mItems = new ArrayList(objects); - } else { - mItems = objects; - } - } else { - mItems = new ArrayList(); - } - } - - - @Override - public int getCount() { - return mItems.size(); - } - - @Override - public T getItem(final int location) { - return mItems.get(location); - } - - @Override - public long getItemId(final int location) { - return location; - } - - /** - * Appends the specified element to the end of the {@code List} . - * @param object the object to add. - * @return always true. - */ - @Override - public boolean add(final T object) { - boolean result = mItems.add(object); - notifyDataSetChanged(); - return result; - } - - @Override - public void add(final int location, final T object) { - mItems.add(location, object); - notifyDataSetChanged(); - } - - /** - * Adds the objects in the specified collection to the end of this List. The objects are added in the order in which they are returned from the collection's iterator. - * @param collection the collection of objects. - * @return {@code true} if this {@code List} is modified, {@code false} otherwise. - */ - @Override - public boolean addAll(final Collection collection) { - boolean result = mItems.addAll(collection); - notifyDataSetChanged(); - return result; - } - - /** - * Appends all of the elements in the specified collection to the end of the - * {@code List} , in the order that they are specified. - * @param objects the array of objects. - * @return {@code true} if the collection changed during insertion. - */ - public boolean addAll(final T... objects) { - boolean result = Collections.addAll(mItems, objects); - notifyDataSetChanged(); - return result; - } - - @Override - public boolean addAll(final int location, final Collection objects) { - boolean result = mItems.addAll(location, objects); - notifyDataSetChanged(); - return result; - } - - /** - * Inserts the objects in the specified collection at the specified location in this List. The objects are added in the order that they specified. - * @param location the index at which to insert. - * @param objects the array of objects. - */ - public void addAll(final int location, final T... objects) { - for (int i = location; i < objects.length + location; i++) { - mItems.add(i, objects[i]); - } - notifyDataSetChanged(); - } - - @Override - public void clear() { - mItems.clear(); - notifyDataSetChanged(); - } - - @Override - public boolean contains(final Object object) { - return mItems.contains(object); - } - - @Override - public boolean containsAll(final Collection collection) { - return mItems.containsAll(collection); - } - - @Override - public T get(final int location) { - return mItems.get(location); - } - - @Override - public T set(final int location, final T object) { - T result = mItems.set(location, object); - notifyDataSetChanged(); - return result; - } - - @Override - public int size() { - return mItems.size(); - } - - @Override - public List subList(final int start, final int end) { - return mItems.subList(start, end); - } - - @Override - public Object[] toArray() { - return mItems.toArray(); - } - - @Override - public T1[] toArray(final T1[] array) { - //noinspection SuspiciousToArrayCall - return mItems.toArray(array); - } - - @Override - public boolean remove(final Object object) { - boolean result = mItems.remove(object); - notifyDataSetChanged(); - return result; - } - - @Override - public T remove(final int location) { - T result = mItems.remove(location); - notifyDataSetChanged(); - return result; - } - - /** - * Removes all elements at the specified locations in the {@code List} . - * @param locations the collection of indexes to remove. - * @return a collection containing the removed objects. - */ - public Collection removePositions(final Collection locations) { - ArrayList removedItems = new ArrayList(); - - ArrayList locationsList = new ArrayList(locations); - Collections.sort(locationsList); - Collections.reverse(locationsList); - for (int location : locationsList) { - removedItems.add(mItems.remove(location)); - } - notifyDataSetChanged(); - return removedItems; - } - - @Override - public boolean removeAll(final Collection objects) { - boolean result = mItems.removeAll(objects); - notifyDataSetChanged(); - return result; - } - - @Override - public boolean retainAll(final Collection objects) { - boolean result = mItems.retainAll(objects); - notifyDataSetChanged(); - return result; - } - - @Override - public int indexOf(final Object object) { - return mItems.indexOf(object); - } - - @Override - public Iterator iterator() { - return mItems.iterator(); - } - - @Override - public int lastIndexOf(final Object object) { - return mItems.lastIndexOf(object); - } - - @Override - public ListIterator listIterator() { - return mItems.listIterator(); - } - - @Override - public ListIterator listIterator(final int location) { - return mItems.listIterator(location); - } - - @Override - public void swapItems(final int locationOne, final int locationTwo) { - T temp = getItem(locationOne); - set(locationOne, getItem(locationTwo)); - set(locationTwo, temp); - } - - private BaseAdapter mDataSetChangedSlavedAdapter; - - public void propagateNotifyDataSetChanged(final BaseAdapter slavedAdapter) { - mDataSetChangedSlavedAdapter = slavedAdapter; - } - - @Override - public void notifyDataSetChanged() { - super.notifyDataSetChanged(); - if (mDataSetChangedSlavedAdapter != null) { - mDataSetChangedSlavedAdapter.notifyDataSetChanged(); - } - } -} diff --git a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/BaseAdapterDecorator.java b/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/BaseAdapterDecorator.java deleted file mode 100644 index 44aa2e1..0000000 --- a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/BaseAdapterDecorator.java +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright 2013 Niek Haarman - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.nhaarman.listviewanimations; - -import android.database.DataSetObserver; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AbsListView; -import android.widget.BaseAdapter; -import android.widget.SectionIndexer; - -import com.nhaarman.listviewanimations.widget.DynamicListView; -import com.nhaarman.listviewanimations.widget.DynamicListView.Swappable; - -/** - * A decorator class that enables decoration of an instance of the BaseAdapter - * class. - * - * Classes extending this class can override methods and provide extra - * functionality before or after calling the super method. - */ -public abstract class BaseAdapterDecorator extends BaseAdapter implements SectionIndexer, DynamicListView.Swappable, ListViewSetter { - - protected final BaseAdapter mDecoratedBaseAdapter; - - private AbsListView mListView; - - private boolean mIsParentHorizontalScrollContainer; - private int mResIdTouchChild; - - public BaseAdapterDecorator(final BaseAdapter baseAdapter) { - mDecoratedBaseAdapter = baseAdapter; - } - - @Override - public void setAbsListView(final AbsListView listView) { - mListView = listView; - - if (mDecoratedBaseAdapter instanceof ListViewSetter) { - ((ListViewSetter) mDecoratedBaseAdapter).setAbsListView(listView); - } - - if (mListView instanceof DynamicListView) { - DynamicListView dynListView = (DynamicListView) mListView; - dynListView.setIsParentHorizontalScrollContainer(mIsParentHorizontalScrollContainer); - dynListView.setDynamicTouchChild(mResIdTouchChild); - } - } - - public AbsListView getAbsListView() { - return mListView; - } - - @Override - public int getCount() { - return mDecoratedBaseAdapter.getCount(); - } - - @Override - public Object getItem(final int position) { - return mDecoratedBaseAdapter.getItem(position); - } - - @Override - public long getItemId(final int position) { - return mDecoratedBaseAdapter.getItemId(position); - } - - @Override - public View getView(final int position, final View convertView, final ViewGroup parent) { - return mDecoratedBaseAdapter.getView(position, convertView, parent); - } - - @Override - public boolean areAllItemsEnabled() { - return mDecoratedBaseAdapter.areAllItemsEnabled(); - } - - @Override - public View getDropDownView(final int position, final View convertView, final ViewGroup parent) { - return mDecoratedBaseAdapter.getDropDownView(position, convertView, parent); - } - - @Override - public int getItemViewType(final int position) { - return mDecoratedBaseAdapter.getItemViewType(position); - } - - @Override - public int getViewTypeCount() { - return mDecoratedBaseAdapter.getViewTypeCount(); - } - - @Override - public boolean hasStableIds() { - return mDecoratedBaseAdapter.hasStableIds(); - } - - @Override - public boolean isEmpty() { - return mDecoratedBaseAdapter.isEmpty(); - } - - @Override - public boolean isEnabled(final int position) { - return mDecoratedBaseAdapter.isEnabled(position); - } - - @Override - public void notifyDataSetChanged() { - if (!(mDecoratedBaseAdapter instanceof ArrayAdapter)) { - // fix #35 dirty trick ! - // leads to an infinite loop when trying because ArrayAdapter triggers notifyDataSetChanged itself - mDecoratedBaseAdapter.notifyDataSetChanged(); - } - } - - /** - * Helper function if you want to force notifyDataSetChanged() - */ - @SuppressWarnings("UnusedDeclaration") - public void notifyDataSetChanged(final boolean force) { - if (force || !(mDecoratedBaseAdapter instanceof ArrayAdapter)) { - // leads to an infinite loop when trying because ArrayAdapter triggers notifyDataSetChanged itself - mDecoratedBaseAdapter.notifyDataSetChanged(); - } - } - - @Override - public void notifyDataSetInvalidated() { - mDecoratedBaseAdapter.notifyDataSetInvalidated(); - } - - @Override - public void registerDataSetObserver(final DataSetObserver observer) { - mDecoratedBaseAdapter.registerDataSetObserver(observer); - } - - @Override - public void unregisterDataSetObserver(final DataSetObserver observer) { - mDecoratedBaseAdapter.unregisterDataSetObserver(observer); - } - - @Override - public int getPositionForSection(final int section) { - if (mDecoratedBaseAdapter instanceof SectionIndexer) { - return ((SectionIndexer) mDecoratedBaseAdapter).getPositionForSection(section); - } - return 0; - } - - @Override - public int getSectionForPosition(final int position) { - if (mDecoratedBaseAdapter instanceof SectionIndexer) { - return ((SectionIndexer) mDecoratedBaseAdapter).getSectionForPosition(position); - } - return 0; - } - - @Override - public Object[] getSections() { - if (mDecoratedBaseAdapter instanceof SectionIndexer) { - return ((SectionIndexer) mDecoratedBaseAdapter).getSections(); - } - return null; - } - - public BaseAdapter getDecoratedBaseAdapter() { - return mDecoratedBaseAdapter; - } - - @Override - public void swapItems(final int positionOne, final int positionTwo) { - if (mDecoratedBaseAdapter instanceof Swappable) { - ((Swappable) mDecoratedBaseAdapter).swapItems(positionOne, positionTwo); - } - } - - /** - * If the adapter's list-view is hosted inside a parent(/grand-parent/etc) that can scroll horizontally, horizontal swipes won't - * work, because the parent will prevent touch-events from reaching the list-view. - * - * Call this method with the value 'true' to fix this behavior. - * Note that this will prevent the parent from scrolling horizontally when the user touches anywhere in a list-item. - */ - public void setIsParentHorizontalScrollContainer(final boolean isParentHorizontalScrollContainer) { - mIsParentHorizontalScrollContainer = isParentHorizontalScrollContainer; - if (mListView instanceof DynamicListView) { - DynamicListView dynListView = (DynamicListView) mListView; - dynListView.setIsParentHorizontalScrollContainer(mIsParentHorizontalScrollContainer); - } - } - - public boolean isParentHorizontalScrollContainer() { - return mIsParentHorizontalScrollContainer; - } - - /** - * If the adapter's list-view is hosted inside a parent(/grand-parent/etc) that can scroll horizontally, horizontal swipes won't - * work, because the parent will prevent touch-events from reaching the list-view. - * - * If a list-item view has a child with the given resource-ID, the user can still swipe the list-item by touching that child. - * If the user touches an area outside that child (but inside the list-item view), then the swipe will not happen and the parent - * will do its job instead (scrolling horizontally). - * - * @param childResId The resource-ID of the list-items' child that the user should touch to be able to swipe the list-items. - */ - public void setTouchChild(final int childResId) { - mResIdTouchChild = childResId; - if (mListView instanceof DynamicListView) { - DynamicListView dynListView = (DynamicListView) mListView; - dynListView.setDynamicTouchChild(mResIdTouchChild); - } - } - - public int getTouchChild() { - return mResIdTouchChild; - } -} \ No newline at end of file diff --git a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/ListViewSetter.java b/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/ListViewSetter.java deleted file mode 100644 index a4972ca..0000000 --- a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/ListViewSetter.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.nhaarman.listviewanimations; - -import android.widget.AbsListView; - -public interface ListViewSetter { - - void setAbsListView(AbsListView listView); -} diff --git a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/AnimateAdditionAdapter.java b/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/AnimateAdditionAdapter.java deleted file mode 100644 index 91b5d23..0000000 --- a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/AnimateAdditionAdapter.java +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright 2013 Niek Haarman - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.nhaarman.listviewanimations.itemmanipulation; - -import android.util.Pair; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AbsListView; -import android.widget.BaseAdapter; -import android.widget.ListView; - -import com.nhaarman.listviewanimations.BaseAdapterDecorator; -import com.nineoldandroids.animation.Animator; -import com.nineoldandroids.animation.AnimatorListenerAdapter; -import com.nineoldandroids.animation.AnimatorSet; -import com.nineoldandroids.animation.ObjectAnimator; -import com.nineoldandroids.animation.ValueAnimator; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * An EXPERIMENTAL adapter for inserting rows into the {@link android.widget.ListView} with an animation. The root {@link BaseAdapter} should implement {@link Insertable}, - * otherwise an {@link java.lang.IllegalArgumentException} is thrown. This class only works with an instance of {@code ListView}! - *

- * Usage:
- * - Wrap a new instance of this class around a {@link android.widget.BaseAdapter}.
- * - Set a {@code ListView} to this class using {@link #setListView(android.widget.ListView)}.
- * - Call {@link com.nhaarman.listviewanimations.itemmanipulation.AnimateAdditionAdapter#insert(int, Object)} to animate the addition of an item. - *

- * Extend this class and override {@link com.nhaarman.listviewanimations.itemmanipulation.AnimateAdditionAdapter#getAdditionalAnimators(android.view.View, - * android.view.ViewGroup)} to provide extra {@link com.nineoldandroids.animation.Animator}s. - */ -@SuppressWarnings("unchecked") -public class AnimateAdditionAdapter extends BaseAdapterDecorator { - - private static final long DEFAULT_SCROLLDOWN_ANIMATION_MS = 300; - private static final long DEFAULT_INSERTION_ANIMATION_MS = 300; - private static final String ALPHA = "alpha"; - - private final Insertable mInsertable; - private final InsertQueue mInsertQueue; - - private boolean mShouldAnimateDown = true; - - private long mInsertionAnimationDurationMs = DEFAULT_INSERTION_ANIMATION_MS; - private long mScrolldownAnimationDurationMs = DEFAULT_SCROLLDOWN_ANIMATION_MS; - - /** - * Create a new {@link com.nhaarman.listviewanimations.itemmanipulation.AnimateAdditionAdapter} with given {@link android.widget.BaseAdapter}. - * - * @param baseAdapter should implement {@link com.nhaarman.listviewanimations.itemmanipulation.AnimateAdditionAdapter.Insertable}, - * or be a {@link com.nhaarman.listviewanimations.BaseAdapterDecorator} whose BaseAdapter implements the interface. - */ - public AnimateAdditionAdapter(final BaseAdapter baseAdapter) { - super(baseAdapter); - - BaseAdapter rootAdapter = getRootAdapter(); - if (!(rootAdapter instanceof Insertable)) { - throw new IllegalArgumentException("BaseAdapter should implement Insertable!"); - } - - mInsertable = (Insertable) rootAdapter; - mInsertQueue = new InsertQueue(mInsertable); - } - - private BaseAdapter getRootAdapter() { - BaseAdapter adapter = getDecoratedBaseAdapter(); - while (adapter instanceof BaseAdapterDecorator) { - adapter = ((BaseAdapterDecorator) adapter).getDecoratedBaseAdapter(); - } - - return adapter; - } - - @Override - @Deprecated - /** - * @deprecated AnimateAdditionAdapter requires a ListView instance. Use {@link #setListView(android.widget.ListView)} instead. - */ - public void setAbsListView(final AbsListView listView) { - if (!(listView instanceof ListView)) { - throw new IllegalArgumentException("AnimateAdditionAdapter requires a ListView instance!"); - } - super.setAbsListView(listView); - } - - public void setListView(final ListView listView) { - super.setAbsListView(listView); - } - - /** - * Set whether the list should animate downwards when items are added above the first visible item. - * @param shouldAnimateDown defaults to {@code true}. - */ - @SuppressWarnings("UnusedDeclaration") - public void setShouldAnimateDown(final boolean shouldAnimateDown) { - mShouldAnimateDown = shouldAnimateDown; - } - - /** - * Set the duration of the scrolldown animation per item for when items are inserted above the first visible item. - * @param scrolldownAnimationDurationMs the duration in ms. - */ - @SuppressWarnings("UnusedDeclaration") - public void setScrolldownAnimationDuration(final long scrolldownAnimationDurationMs) { - mScrolldownAnimationDurationMs = scrolldownAnimationDurationMs; - } - - /** - * Set the duration of the insertion animation. - * @param insertionAnimationDurationMs the duration in ms. - */ - @SuppressWarnings("UnusedDeclaration") - public void setInsertionAnimationDuration(final long insertionAnimationDurationMs) { - mInsertionAnimationDurationMs = insertionAnimationDurationMs; - } - - /** - * Insert an item at given index. Will show an entrance animation for the new item if the newly added item is visible. - * Will also call {@link Insertable#add(int, Object)} of the root {@link BaseAdapter}. - * - * @param index the index the new item should be inserted at - * @param item the item to insert - */ - public void insert(final int index, final T item) { - insert(new Pair(index, item)); - } - - /** - * Insert items at given indexes. Will show an entrance animation for the new items if the newly added item is visible. - * Will also call {@link Insertable#add(int, Object)} of the root {@link BaseAdapter}. - * - * @param indexItemPairs the index-item pairs to insert. The first argument of the {@code Pair} is the index, the second argument is the item. - */ - public void insert(final Pair... indexItemPairs) { - insert(Arrays.asList(indexItemPairs)); - } - - /** - * Insert items at given indexes. Will show an entrance animation for the new items if the newly added item is visible. - * Will also call {@link Insertable#add(int, Object)} of the root {@link BaseAdapter}. - * - * @param indexItemPairs the index-item pairs to insert. The first argument of the {@code Pair} is the index, the second argument is the item. - */ - public void insert(final List> indexItemPairs) { - List> visibleViews = new ArrayList>(); - List insertedPositions = new ArrayList(); - List insertedBelowPositions = new ArrayList(); - - int scrollDistance = 0; - int numInsertedAbove = 0; - - for (Pair pair : indexItemPairs) { - if (getAbsListView().getFirstVisiblePosition() > pair.first) { - /* Inserting an item above the first visible position */ - int index = pair.first; - - /* Correct the index for already inserted positions above the first visible view. */ - for (int insertedPosition : insertedPositions) { - if (index >= insertedPosition) { - index++; - } - } - - mInsertable.add(index, pair.second); - insertedPositions.add(index); - numInsertedAbove++; - - if (mShouldAnimateDown) { - View view = getView(pair.first, null, getAbsListView()); - view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)); - scrollDistance -= view.getMeasuredHeight(); - } - } else if (getAbsListView().getLastVisiblePosition() >= pair.first) { - /* Inserting an item that becomes visible on screen */ - int index = pair.first; - - /* Correct the index for already inserted positions above the first visible view */ - for (int insertedPosition : insertedPositions) { - if (index >= insertedPosition) { - index++; - } - } - Pair newPair = new Pair(index, pair.second); - visibleViews.add(newPair); - } else { - /* Inserting an item below the last visible item */ - int index = pair.first; - - /* Correct the index for already inserted positions above the first visible view */ - for (int insertedPosition : insertedPositions) { - if (index >= insertedPosition) { - index++; - } - } - - /* Correct the index for already inserted positions below the last visible view */ - for (int queuedPosition : insertedBelowPositions) { - if (index >= queuedPosition) { - index++; - } - } - - insertedBelowPositions.add(index); - mInsertable.add(index, pair.second); - } - } - - if (mShouldAnimateDown) { - getAbsListView().smoothScrollBy(scrollDistance, (int) (mScrolldownAnimationDurationMs * numInsertedAbove)); - } - - mInsertQueue.insert(visibleViews); - ((ListView) getAbsListView()).setSelectionFromTop(getAbsListView().getFirstVisiblePosition() + numInsertedAbove, getAbsListView().getChildAt(0).getTop()); - } - - - @Override - public View getView(final int position, final View convertView, final ViewGroup parent) { - final View view = super.getView(position, convertView, parent); - - if (mInsertQueue.getActiveIndexes().contains(position)) { - int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(ViewGroup.LayoutParams.MATCH_PARENT, View.MeasureSpec.AT_MOST); - int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(ViewGroup.LayoutParams.WRAP_CONTENT, View.MeasureSpec.AT_MOST); - view.measure(widthMeasureSpec, heightMeasureSpec); - - int originalHeight = view.getMeasuredHeight(); - - ValueAnimator heightAnimator = ValueAnimator.ofInt(1, originalHeight); - heightAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(final ValueAnimator animation) { - ViewGroup.LayoutParams layoutParams = view.getLayoutParams(); - layoutParams.height = (Integer) animation.getAnimatedValue(); - view.setLayoutParams(layoutParams); - } - }); - - ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(view, ALPHA, 0, 1); - - AnimatorSet animatorSet = new AnimatorSet(); - Animator[] customAnimators = getAdditionalAnimators(view, parent); - Animator[] animators = new Animator[customAnimators.length + 2]; - animators[0] = heightAnimator; - animators[1] = alphaAnimator; - System.arraycopy(customAnimators, 0, animators, 2, customAnimators.length); - animatorSet.playTogether(animators); - animatorSet.setDuration(mInsertionAnimationDurationMs); - animatorSet.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(final Animator animation) { - mInsertQueue.removeActiveIndex(position); - } - }); - animatorSet.start(); - } - - return view; - } - - /** - * Override this method to provide additional animators on top of the default height and alpha animation. - * - * @param view The {@link View} that will get animated. - * @param parent The parent that this view will eventually be attached to. - * @return a non-null array of Animators. - */ - @SuppressWarnings("UnusedParameters") - protected Animator[] getAdditionalAnimators(final View view, final ViewGroup parent) { - return new Animator[]{}; - } - - /** - * An interface for inserting items at a certain index. - */ - public interface Insertable { - - /** - * Will be called to insert given {@code item} at given {@code index} in the list. - * - * @param index the index the new item should be inserted at - * @param item the item to insert - */ - public void add(int index, T item); - } -} diff --git a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/AnimateDismissAdapter.java b/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/AnimateDismissAdapter.java deleted file mode 100644 index 1bd84bd..0000000 --- a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/AnimateDismissAdapter.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright 2013 Niek Haarman - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.nhaarman.listviewanimations.itemmanipulation; - -import android.view.View; -import android.view.ViewGroup; -import android.widget.BaseAdapter; - -import com.nhaarman.listviewanimations.BaseAdapterDecorator; -import com.nhaarman.listviewanimations.util.AdapterViewUtil; -import com.nineoldandroids.animation.Animator; -import com.nineoldandroids.animation.AnimatorListenerAdapter; -import com.nineoldandroids.animation.AnimatorSet; -import com.nineoldandroids.animation.ValueAnimator; -import com.nineoldandroids.animation.ValueAnimator.AnimatorUpdateListener; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -/** - * A {@link BaseAdapterDecorator} class that provides animations to the removal - * of items in the given {@link BaseAdapter}. - */ -public class AnimateDismissAdapter extends BaseAdapterDecorator { - - private final OnDismissCallback mCallback; - - /** - * Create a new AnimateDismissAdapter based on the given {@link BaseAdapter}. - * - * @param callback - * The {@link OnDismissCallback} to trigger when the user has - * indicated that she would like to dismiss one or more list - * items. - */ - public AnimateDismissAdapter(final BaseAdapter baseAdapter, final OnDismissCallback callback) { - super(baseAdapter); - mCallback = callback; - } - - /** - * Animate dismissal of the item at given position. - */ - @SuppressWarnings("UnusedDeclaration") - public void animateDismiss(final int position) { - animateDismiss(Arrays.asList(position)); - } - - /** - * Animate dismissal of the items at given positions. - */ - public void animateDismiss(final Collection positions) { - final List positionsCopy = new ArrayList(positions); - if (getAbsListView() == null) { - throw new IllegalStateException("Call setAbsListView() on this AnimateDismissAdapter before calling setAdapter()!"); - } - - List views = getVisibleViewsForPositions(positionsCopy); - - if (!views.isEmpty()) { - List animators = new ArrayList(); - for (final View view : views) { - animators.add(createAnimatorForView(view)); - } - - AnimatorSet animatorSet = new AnimatorSet(); - - Animator[] animatorsArray = new Animator[animators.size()]; - for (int i = 0; i < animatorsArray.length; i++) { - animatorsArray[i] = animators.get(i); - } - - animatorSet.playTogether(animatorsArray); - animatorSet.addListener(new AnimatorListenerAdapter() { - - @Override - public void onAnimationEnd(final Animator animator) { - invokeCallback(positionsCopy); - } - }); - animatorSet.start(); - } else { - invokeCallback(positionsCopy); - } - } - - private void invokeCallback(final Collection positions) { - ArrayList positionsList = new ArrayList(positions); - Collections.sort(positionsList); - - int[] dismissPositions = new int[positionsList.size()]; - for (int i = 0; i < positionsList.size(); i++) { - dismissPositions[i] = positionsList.get(positionsList.size() - 1 - i); - } - mCallback.onDismiss(getAbsListView(), dismissPositions); - } - - private List getVisibleViewsForPositions(final Collection positions) { - List views = new ArrayList(); - for (int i = 0; i < getAbsListView().getChildCount(); i++) { - View child = getAbsListView().getChildAt(i); - if (positions.contains(AdapterViewUtil.getPositionForView(getAbsListView(), child))) { - views.add(child); - } - } - return views; - } - - private Animator createAnimatorForView(final View view) { - final ViewGroup.LayoutParams lp = view.getLayoutParams(); - final int originalHeight = view.getHeight(); - - ValueAnimator animator = ValueAnimator.ofInt(originalHeight, 0); - animator.addListener(new AnimatorListenerAdapter() { - - @Override - public void onAnimationEnd(final Animator animator) { - lp.height = 0; - view.setLayoutParams(lp); - } - }); - - animator.addUpdateListener(new AnimatorUpdateListener() { - - @Override - public void onAnimationUpdate(final ValueAnimator valueAnimator) { - lp.height = (Integer) valueAnimator.getAnimatedValue(); - view.setLayoutParams(lp); - } - }); - - return animator; - } -} diff --git a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/ExpandCollapseListener.java b/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/ExpandCollapseListener.java deleted file mode 100644 index 07bc638..0000000 --- a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/ExpandCollapseListener.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.nhaarman.listviewanimations.itemmanipulation; - -// TODO integrate in ExpandableListItemAdapter -public interface ExpandCollapseListener { - - public void onItemExpanded(int position); - - public void onItemCollapsed(int position); - -} diff --git a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/ExpandableListItemAdapter.java b/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/ExpandableListItemAdapter.java deleted file mode 100644 index 81398f5..0000000 --- a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/ExpandableListItemAdapter.java +++ /dev/null @@ -1,535 +0,0 @@ -package com.nhaarman.listviewanimations.itemmanipulation; - -import android.content.Context; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewGroup.LayoutParams; -import android.widget.AbsListView; -import android.widget.FrameLayout; -import android.widget.LinearLayout; - -import com.nhaarman.listviewanimations.ArrayAdapter; -import com.nhaarman.listviewanimations.ListViewSetter; -import com.nhaarman.listviewanimations.util.AdapterViewUtil; -import com.nineoldandroids.animation.Animator; -import com.nineoldandroids.animation.AnimatorListenerAdapter; -import com.nineoldandroids.animation.ValueAnimator; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * An {@link ArrayAdapter} which allows items to be expanded using an animation. - */ -@SuppressWarnings("UnusedDeclaration") -public abstract class ExpandableListItemAdapter extends ArrayAdapter implements ListViewSetter { - - private static final int DEFAULTTITLEPARENTRESID = 10000; - private static final int DEFAULTCONTENTPARENTRESID = 10001; - - private final Context mContext; - private int mViewLayoutResId; - private final int mTitleParentResId; - private final int mContentParentResId; - private int mActionViewResId; - private final List mExpandedIds; - - private int mLimit; - - private AbsListView mAbsListView; - - private ExpandCollapseListener mExpandCollapseListener; - - /** - * Creates a new ExpandableListItemAdapter with an empty list. - */ - public ExpandableListItemAdapter(final Context context) { - this(context, null); - } - - /** - * Creates a new {@link ExpandableListItemAdapter} with the specified list, - * or an empty list if items == null. - */ - public ExpandableListItemAdapter(final Context context, final List items) { - super(items); - mContext = context; - mTitleParentResId = DEFAULTTITLEPARENTRESID; - mContentParentResId = DEFAULTCONTENTPARENTRESID; - - mExpandedIds = new ArrayList(); - } - - /** - * Creates a new ExpandableListItemAdapter with an empty list. Uses given - * layout resource for the view; titleParentResId and contentParentResId - * should be identifiers for ViewGroups within that layout. - */ - public ExpandableListItemAdapter(final Context context, final int layoutResId, final int titleParentResId, final int contentParentResId) { - this(context, layoutResId, titleParentResId, contentParentResId, null); - } - - /** - * Creates a new ExpandableListItemAdapter with the specified list, or an - * empty list if items == null. Uses given layout resource for the view; - * titleParentResId and contentParentResId should be identifiers for - * ViewGroups within that layout. - */ - public ExpandableListItemAdapter(final Context context, final int layoutResId, final int titleParentResId, final int contentParentResId, final List items) { - super(items); - mContext = context; - mViewLayoutResId = layoutResId; - mTitleParentResId = titleParentResId; - mContentParentResId = contentParentResId; - - mExpandedIds = new ArrayList(); - } - - @Override - public void setAbsListView(final AbsListView listView) { - mAbsListView = listView; - } - - /** - * Set the resource id of the child {@link View} contained in the View - * returned by {@link #getTitleView(int, View, ViewGroup)} that will be the - * actuator of the expand / collapse animations.
- * If there is no View in the title View with given resId, a - * {@link NullPointerException} is thrown.

Default behavior: the whole - * title View acts as the actuator. - * - * @param resId the resource id. - */ - public void setActionViewResId(final int resId) { - mActionViewResId = resId; - } - - /** - * Set the maximum number of items allowed to be expanded. When the - * (limit+1)th item is expanded, the first expanded item will collapse. - * - * @param limit the maximum number of items allowed to be expanded. Use <= 0 - * for no limit. - */ - public void setLimit(final int limit) { - mLimit = limit; - mExpandedIds.clear(); - notifyDataSetChanged(); - } - - /** - * Set the {@link com.nhaarman.listviewanimations.itemmanipulation.ExpandCollapseListener} that should be notified of expand / collapse events. - */ - public void setExpandCollapseListener(final ExpandCollapseListener expandCollapseListener) { - mExpandCollapseListener = expandCollapseListener; - } - - @Override - public View getView(final int position, final View convertView, final ViewGroup parent) { - ViewGroup view = (ViewGroup) convertView; - ViewHolder viewHolder; - - if (view == null) { - view = createView(parent); - - viewHolder = new ViewHolder(); - viewHolder.titleParent = (ViewGroup) view.findViewById(mTitleParentResId); - viewHolder.contentParent = (ViewGroup) view.findViewById(mContentParentResId); - - view.setTag(viewHolder); - } else { - viewHolder = (ViewHolder) view.getTag(); - } - - View titleView = getTitleView(position, viewHolder.titleView, viewHolder.titleParent); - if (titleView != viewHolder.titleView) { - viewHolder.titleParent.removeAllViews(); - viewHolder.titleParent.addView(titleView); - - if (mActionViewResId == 0) { - view.setOnClickListener(new TitleViewOnClickListener(viewHolder.contentParent)); - } else { - view.findViewById(mActionViewResId).setOnClickListener(new TitleViewOnClickListener(viewHolder.contentParent)); - } - } - viewHolder.titleView = titleView; - - View contentView = getContentView(position, viewHolder.contentView, viewHolder.contentParent); - if (contentView != viewHolder.contentView) { - viewHolder.contentParent.removeAllViews(); - viewHolder.contentParent.addView(contentView); - } - viewHolder.contentView = contentView; - - viewHolder.contentParent.setVisibility(mExpandedIds.contains(getItemId(position)) ? View.VISIBLE : View.GONE); - viewHolder.contentParent.setTag(getItemId(position)); - - ViewGroup.LayoutParams layoutParams = viewHolder.contentParent.getLayoutParams(); - layoutParams.height = LayoutParams.WRAP_CONTENT; - viewHolder.contentParent.setLayoutParams(layoutParams); - - return view; - } - - private ViewGroup createView(final ViewGroup parent) { - ViewGroup view; - - if (mViewLayoutResId == 0) { - view = new RootView(mContext); - } else { - view = (ViewGroup) LayoutInflater.from(mContext).inflate(mViewLayoutResId, parent, false); - } - - return view; - } - - /** - * Get a View that displays the title of the data at the specified - * position in the data set. You can either create a View manually or - * inflate it from an XML layout file. When the View is inflated, the parent - * View (GridView, ListView...) will apply default layout parameters unless - * you use - * {@link android.view.LayoutInflater#inflate(int, android.view.ViewGroup, boolean)} - * to specify a root view and to prevent attachment to the root. - * - * @param position The position of the item within the adapter's data set of the - * item whose view we want. - * @param convertView The old view to reuse, if possible. Note: You should check - * that this view is non-null and of an appropriate type before - * using. If it is not possible to convert this view to display - * the correct data, this method can create a new view. - * @param parent The parent that this view will eventually be attached to - * @return A View corresponding to the title of the data at the specified - * position. - */ - public abstract View getTitleView(int position, View convertView, ViewGroup parent); - - /** - * Get a View that displays the content of the data at the specified - * position in the data set. You can either create a View manually or - * inflate it from an XML layout file. When the View is inflated, the parent - * View (GridView, ListView...) will apply default layout parameters unless - * you use - * {@link android.view.LayoutInflater#inflate(int, android.view.ViewGroup, boolean)} - * to specify a root view and to prevent attachment to the root. - * - * @param position The position of the item within the adapter's data set of the - * item whose view we want. - * @param convertView The old view to reuse, if possible. Note: You should check - * that this view is non-null and of an appropriate type before - * using. If it is not possible to convert this view to display - * the correct data, this method can create a new view. - * @param parent The parent that this view will eventually be attached to - * @return A View corresponding to the content of the data at the specified - * position. - */ - public abstract View getContentView(int position, View convertView, ViewGroup parent); - - /** - * Indicates if the item at the specified position is expanded. - * - * @param position Index of the view whose state we want. - * @return true if the view is expanded, false otherwise. - */ - public boolean isExpanded(final int position) { - long itemId = getItemId(position); - return mExpandedIds.contains(itemId); - } - - /** - * Return the title view at the specified position. - * - * @param position Index of the view we want. - * @return the view if it exist, null otherwise. - */ - public View getTitleView(final int position) { - View titleView = null; - - View parentView = findViewForPosition(position); - Object tag = parentView.getTag(); - if (tag instanceof ViewHolder) { - titleView = ((ViewHolder) tag).titleView; - } - - return titleView; - } - - /** - * Return the content view at the specified position. - * - * @param position Index of the view we want. - * @return the view if it exist, null otherwise. - */ - public View getContentView(final int position) { - View contentView = null; - - View parentView = findViewForPosition(position); - if (parentView != null) { - Object tag = parentView.getTag(); - if (tag instanceof ViewHolder) { - contentView = ((ViewHolder) tag).contentView; - } - } - - return contentView; - } - - @Override - public void notifyDataSetChanged() { - super.notifyDataSetChanged(); - - Set removedIds = new HashSet(mExpandedIds); - - for (int i = 0; i < getCount(); ++i) { - long id = getItemId(i); - removedIds.remove(id); - } - - mExpandedIds.removeAll(removedIds); - } - - /** - * Return the content parent at the specified position. - * - * @param position Index of the view we want. - * @return the view if it exist, null otherwise. - */ - private View getContentParent(final int position) { - View contentParent = null; - - View parentView = findViewForPosition(position); - if (parentView != null) { - Object tag = parentView.getTag(); - if (tag instanceof ViewHolder) { - contentParent = ((ViewHolder) tag).contentParent; - } - } - - return contentParent; - } - - /** - * Expand the view at given position. Will do nothing if the view is already expanded. - * - * @param position the position to expand. - */ - public void expand(final int position) { - long itemId = getItemId(position); - if (mExpandedIds.contains(itemId)) { - return; - } - - toggle(position); - } - - /** - * Collapse the view at given position. Will do nothing if the view is already collapsed. - * - * @param position the position to collapse. - */ - public void collapse(final int position) { - long itemId = getItemId(position); - if (!mExpandedIds.contains(itemId)) { - return; - } - - toggle(position); - } - - private View findViewForPosition(final int position) { - View result = null; - for (int i = 0; i < mAbsListView.getChildCount() && result == null; i++) { - View childView = mAbsListView.getChildAt(i); - if (AdapterViewUtil.getPositionForView(mAbsListView, childView) == position) { - result = childView; - } - } - return result; - } - - private int findPositionForId(final long id) { - for (int i = 0; i < getCount(); i++) { - if (getItemId(i) == id) { - return i; - } - } - return -1; - } - - /** - * Toggle the {@link View} at given position, ignores header or footer Views. - * - * @param position the position of the view to toggle. - */ - public void toggle(final int position) { - long itemId = getItemId(position); - boolean isExpanded = mExpandedIds.contains(itemId); - - View contentParent = getContentParent(position); - if (contentParent != null) { - toggle(contentParent); - } - - if (contentParent == null && isExpanded) { - mExpandedIds.remove(itemId); - } else if (contentParent == null && !isExpanded) { - mExpandedIds.add(itemId); - } - } - - private void toggle(final View contentParent) { - boolean isVisible = contentParent.getVisibility() == View.VISIBLE; - boolean shouldCollapseOther = !isVisible && mLimit > 0 && mExpandedIds.size() >= mLimit; - if (shouldCollapseOther) { - Long firstId = mExpandedIds.get(0); - - int firstPosition = findPositionForId(firstId); - View firstEV = getContentParent(firstPosition); - if (firstEV != null) { - ExpandCollapseHelper.animateCollapsing(firstEV); - } - mExpandedIds.remove(firstId); - - if (mExpandCollapseListener != null) { - mExpandCollapseListener.onItemCollapsed(firstPosition); - } - } - - Long id = (Long) contentParent.getTag(); - int position = findPositionForId(id); - if (isVisible) { - ExpandCollapseHelper.animateCollapsing(contentParent); - mExpandedIds.remove(id); - - if (mExpandCollapseListener != null) { - mExpandCollapseListener.onItemCollapsed(position); - } - - } else { - ExpandCollapseHelper.animateExpanding(contentParent, mAbsListView); - mExpandedIds.add(id); - - if (mExpandCollapseListener != null) { - mExpandCollapseListener.onItemExpanded(position); - } - } - } - - private class TitleViewOnClickListener implements View.OnClickListener { - - private final View mContentParent; - - private TitleViewOnClickListener(final View contentParent) { - mContentParent = contentParent; - } - - @Override - public void onClick(final View view) { - toggle(mContentParent); - } - } - - private static class RootView extends LinearLayout { - - private ViewGroup mTitleViewGroup; - private ViewGroup mContentViewGroup; - - public RootView(final Context context) { - super(context); - init(); - } - - private void init() { - setOrientation(VERTICAL); - - mTitleViewGroup = new FrameLayout(getContext()); - mTitleViewGroup.setId(DEFAULTTITLEPARENTRESID); - addView(mTitleViewGroup); - - mContentViewGroup = new FrameLayout(getContext()); - mContentViewGroup.setId(DEFAULTCONTENTPARENTRESID); - addView(mContentViewGroup); - } - } - - private static class ViewHolder { - ViewGroup titleParent; - ViewGroup contentParent; - View titleView; - View contentView; - } - - private static class ExpandCollapseHelper { - - public static void animateCollapsing(final View view) { - int origHeight = view.getHeight(); - - ValueAnimator animator = createHeightAnimator(view, origHeight, 0); - animator.addListener(new AnimatorListenerAdapter() { - - @Override - public void onAnimationEnd(final Animator animator) { - view.setVisibility(View.GONE); - } - }); - animator.start(); - } - - public static void animateExpanding(final View view, final AbsListView listView) { - view.setVisibility(View.VISIBLE); - - View parent = (View) view.getParent(); - final int widthSpec = View.MeasureSpec.makeMeasureSpec(parent.getMeasuredWidth() - parent.getPaddingLeft() - parent.getPaddingRight(), View.MeasureSpec.AT_MOST); - final int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); - view.measure(widthSpec, heightSpec); - - ValueAnimator animator = createHeightAnimator(view, 0, view.getMeasuredHeight()); - animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { - final int listViewHeight = listView.getHeight(); - final int listViewBottomPadding = listView.getPaddingBottom(); - final View v = findDirectChild(view, listView); - - @Override - public void onAnimationUpdate(final ValueAnimator valueAnimator) { - final int bottom = v.getBottom(); - if (bottom > listViewHeight) { - final int top = v.getTop(); - if (top > 0) { - listView.smoothScrollBy(Math.min(bottom - listViewHeight + listViewBottomPadding, top), 0); - } - } - } - }); - animator.start(); - } - - private static View findDirectChild(final View view, final AbsListView listView) { - View result = view; - View parent = (View) result.getParent(); - while (parent != listView) { - result = parent; - parent = (View) result.getParent(); - } - return result; - } - - public static ValueAnimator createHeightAnimator(final View view, final int start, final int end) { - ValueAnimator animator = ValueAnimator.ofInt(start, end); - animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { - - @Override - public void onAnimationUpdate(final ValueAnimator valueAnimator) { - int value = (Integer) valueAnimator.getAnimatedValue(); - - ViewGroup.LayoutParams layoutParams = view.getLayoutParams(); - layoutParams.height = value; - view.setLayoutParams(layoutParams); - } - }); - return animator; - } - } -} diff --git a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/InsertQueue.java b/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/InsertQueue.java deleted file mode 100644 index 2f67bd4..0000000 --- a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/InsertQueue.java +++ /dev/null @@ -1,127 +0,0 @@ -package com.nhaarman.listviewanimations.itemmanipulation; - -import android.util.Pair; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * A class to insert items only when there are no active items. - * A pending index-item pair can have two states: active and pending. When inserting new items, the {@link com.nhaarman.listviewanimations.itemmanipulation.AnimateAdditionAdapter.Insertable#add - * (int, Object)} method will be called directly if there are no active index-item pairs. - * Otherwise, pairs will be queued until the active list is empty. - */ -public class InsertQueue { - - private final AnimateAdditionAdapter.Insertable mInsertable; - - private final Set mActiveIndexes = new HashSet(); - private final List> mPendingItemsToInsert = new ArrayList>(); - - public InsertQueue(final AnimateAdditionAdapter.Insertable insertable) { - mInsertable = insertable; - } - - /** - * Insert an item into the queue at given index. Will directly call {@link com.nhaarman.listviewanimations.itemmanipulation.AnimateAdditionAdapter.Insertable#add(int, - * Object)} if there are no active index-item pairs. Otherwise, the pair will be queued. - * @param index the index at which the item should be inserted. - * @param item the item to insert. - */ - public void insert(final int index, final T item) { - if (mActiveIndexes.isEmpty() && mPendingItemsToInsert.isEmpty()) { - mActiveIndexes.add(new AtomicInteger(index)); - //noinspection unchecked - mInsertable.add(index, item); - } else { - mPendingItemsToInsert.add(new Pair(index, item)); - } - } - - @SuppressWarnings("UnusedDeclaration") - public void insert(final Pair... indexItemPair) { - insert(Arrays.asList(indexItemPair)); - } - - public void insert(final List> indexItemPairs) { - if (mActiveIndexes.isEmpty() && mPendingItemsToInsert.isEmpty()) { - for (Pair pair : indexItemPairs) { - for (AtomicInteger existing : mActiveIndexes) { - if (existing.intValue() >= pair.first) { - existing.incrementAndGet(); - } - } - mActiveIndexes.add(new AtomicInteger(pair.first)); - - mInsertable.add(pair.first, pair.second); - } - } else { - mPendingItemsToInsert.addAll(indexItemPairs); - } - } - - /** - * Clears the active states and inserts any pending pairs if applicable. - */ - public void clearActive() { - mActiveIndexes.clear(); - insertPending(); - } - - /** - * Clear the active state for given index. Will insert any pending pairs if this call leads to a state where there are no active pairs. - * @param index the index to remove. - */ - public void removeActiveIndex(final int index) { - boolean found = false; - for (Iterator iterator = mActiveIndexes.iterator(); iterator.hasNext() && !found; ) { - if (iterator.next().get() == index) { - iterator.remove(); - found = true; - } - } - if (mActiveIndexes.isEmpty()) { - insertPending(); - } - } - - /** - * Inserts pending items into the Insertable, and adds them to the active positions (correctly managing position shifting). Clears the pending items. - */ - private void insertPending() { - for (Pair pi : mPendingItemsToInsert) { - for (AtomicInteger existing : mActiveIndexes) { - if (existing.intValue() >= pi.first) { - existing.incrementAndGet(); - } - } - mActiveIndexes.add(new AtomicInteger(pi.first)); - mInsertable.add(pi.first, pi.second); - } - mPendingItemsToInsert.clear(); - } - - /** - * Returns a collection of currently active indexes. - */ - public Collection getActiveIndexes() { - HashSet result = new HashSet(); - for (AtomicInteger i : mActiveIndexes) { - result.add(i.get()); - } - return result; - } - - /** - * Returns a {@code List} of {@code Pair}s with the index and items that are pending to be inserted, in the order they were requested. - */ - public List> getPendingItemsToInsert() { - return mPendingItemsToInsert; - } -} diff --git a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/OnDismissCallback.java b/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/OnDismissCallback.java deleted file mode 100644 index 752b600..0000000 --- a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/OnDismissCallback.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2013 Niek Haarman - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.nhaarman.listviewanimations.itemmanipulation; - -import android.widget.AbsListView; -import android.widget.ListView; - -/** - * The callback interface used by {@link com.nhaarman.listviewanimations.itemmanipulation.swipedismiss.SwipeDismissListViewTouchListener} to - * inform its client about a successful dismissal of one or more list item - * positions. - */ -public interface OnDismissCallback { - /** - * Called when the user has indicated they she would like to dismiss one or - * more list item positions. - * - * @param listView - * The originating {@link ListView}. - * @param reverseSortedPositions - * An array of positions to dismiss, sorted in descending order - * for convenience. - */ - void onDismiss(AbsListView listView, int[] reverseSortedPositions); -} \ No newline at end of file diff --git a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/swipedismiss/DismissableManager.java b/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/swipedismiss/DismissableManager.java deleted file mode 100644 index 82e2a62..0000000 --- a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/swipedismiss/DismissableManager.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.nhaarman.listviewanimations.itemmanipulation.swipedismiss; - -/** - * An interface to specify whether certain items can or cannot be dismissed. - */ -public interface DismissableManager { - - /** - * Returns whether the item for given id and position can be dismissed. - * @param id the id of the item. - * @param position the position of the item. - * @return true if the item can be dismissed, false otherwise. - */ - public boolean isDismissable(long id, int position); -} \ No newline at end of file diff --git a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/swipedismiss/SwipeDismissAdapter.java b/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/swipedismiss/SwipeDismissAdapter.java deleted file mode 100644 index bb8dffd..0000000 --- a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/swipedismiss/SwipeDismissAdapter.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2013 Niek Haarman - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.nhaarman.listviewanimations.itemmanipulation.swipedismiss; - -import android.widget.AbsListView; -import android.widget.BaseAdapter; - -import com.nhaarman.listviewanimations.ArrayAdapter; -import com.nhaarman.listviewanimations.BaseAdapterDecorator; -import com.nhaarman.listviewanimations.itemmanipulation.OnDismissCallback; - -/** - * Adds an option to swipe items in an AbsListView away. - * Do not call {@link android.widget.AbsListView#setOnTouchListener(android.view.View.OnTouchListener)} or - * {@link android.widget.AbsListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener)} on your AbsListView! To use an {@link android.widget.AbsListView.OnScrollListener}, - * extends {@link SwipeOnScrollListener} and - * pass it in the constructor {@link #SwipeDismissAdapter(android.widget.BaseAdapter, com.nhaarman.listviewanimations.itemmanipulation.OnDismissCallback, SwipeOnScrollListener)}. - */ -public class SwipeDismissAdapter extends BaseAdapterDecorator { - - protected OnDismissCallback mOnDismissCallback; - protected SwipeDismissListViewTouchListener mSwipeDismissListViewTouchListener; - protected SwipeOnScrollListener mSwipeOnScrollListener; - - /** - * Create a new SwipeDismissAdapter. - * - * @param baseAdapter the {@link android.widget.BaseAdapter to use} - * @param onDismissCallback the {@link OnDismissCallback} to be notified of dismissed items. - */ - public SwipeDismissAdapter(final BaseAdapter baseAdapter, final OnDismissCallback onDismissCallback) { - this(baseAdapter, onDismissCallback, new SwipeOnScrollListener()); - } - - /** - * Create a new SwipeDismissAdapter. - * - * @param baseAdapter the {@link android.widget.BaseAdapter to use} - * @param onDismissCallback the {@link OnDismissCallback} to be notified of dismissed items. - * @param swipeOnScrollListener the {@link SwipeOnScrollListener} to use. - */ - public SwipeDismissAdapter(final BaseAdapter baseAdapter, final OnDismissCallback onDismissCallback, final SwipeOnScrollListener swipeOnScrollListener) { - super(baseAdapter); - mOnDismissCallback = onDismissCallback; - mSwipeOnScrollListener = swipeOnScrollListener; - } - - protected SwipeDismissListViewTouchListener createListViewTouchListener(final AbsListView listView) { - return new SwipeDismissListViewTouchListener(listView, mOnDismissCallback, mSwipeOnScrollListener); - } - - @Override - public void setAbsListView(final AbsListView listView) { - super.setAbsListView(listView); - if (mDecoratedBaseAdapter instanceof ArrayAdapter) { - ((ArrayAdapter) mDecoratedBaseAdapter).propagateNotifyDataSetChanged(this); - } - mSwipeDismissListViewTouchListener = createListViewTouchListener(listView); - mSwipeDismissListViewTouchListener.setIsParentHorizontalScrollContainer(isParentHorizontalScrollContainer()); - mSwipeDismissListViewTouchListener.setTouchChild(getTouchChild()); - listView.setOnTouchListener(mSwipeDismissListViewTouchListener); - } - - @Override - public void setIsParentHorizontalScrollContainer(final boolean isParentHorizontalScrollContainer) { - super.setIsParentHorizontalScrollContainer(isParentHorizontalScrollContainer); - if (mSwipeDismissListViewTouchListener != null) { - mSwipeDismissListViewTouchListener.setIsParentHorizontalScrollContainer(isParentHorizontalScrollContainer); - } - } - - @Override - public void notifyDataSetChanged() { - super.notifyDataSetChanged(); - if (mSwipeDismissListViewTouchListener != null) { - mSwipeDismissListViewTouchListener.notifyDataSetChanged(); - } - } - - @Override - public void setTouchChild(final int childResId) { - super.setTouchChild(childResId); - if (mSwipeDismissListViewTouchListener != null) { - mSwipeDismissListViewTouchListener.setTouchChild(childResId); - } - } -} diff --git a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/swipedismiss/SwipeDismissListViewTouchListener.java b/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/swipedismiss/SwipeDismissListViewTouchListener.java deleted file mode 100644 index a5cfbd3..0000000 --- a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/swipedismiss/SwipeDismissListViewTouchListener.java +++ /dev/null @@ -1,469 +0,0 @@ -// THIS IS A BETA! I DON'T RECOMMEND USING IT IN PRODUCTION CODE JUST YET - -/* - * Copyright 2012 Roman Nurik - * Copyright 2013 Niek Haarman - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.nhaarman.listviewanimations.itemmanipulation.swipedismiss; - -import android.annotation.SuppressLint; -import android.graphics.Rect; -import android.view.MotionEvent; -import android.view.VelocityTracker; -import android.view.View; -import android.view.ViewConfiguration; -import android.view.ViewGroup; -import android.widget.AbsListView; -import android.widget.ListView; - -import com.nhaarman.listviewanimations.itemmanipulation.OnDismissCallback; -import com.nhaarman.listviewanimations.util.AdapterViewUtil; -import com.nineoldandroids.animation.Animator; -import com.nineoldandroids.animation.AnimatorListenerAdapter; -import com.nineoldandroids.animation.ValueAnimator; -import com.nineoldandroids.view.ViewHelper; -import com.nineoldandroids.view.ViewPropertyAnimator; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import static com.nineoldandroids.view.ViewPropertyAnimator.animate; - -/** - * A {@link android.view.View.OnTouchListener} that makes the list items in a - * {@link ListView} dismissable. {@link ListView} is given special treatment - * because by default it handles touches for its list items... i.e. it's in - * charge of drawing the pressed state (the list selector), handling list item - * clicks, etc. - * - * For performance reasons, do not use this class directly, but use the {@link com.nhaarman.listviewanimations.itemmanipulation.swipedismiss.SwipeDismissAdapter}. - */ -@SuppressLint("Recycle") -public class SwipeDismissListViewTouchListener implements SwipeOnTouchListener { - - private static final int MIN_FLING_VELOCITY_FACTOR = 16; - // Cached ViewConfiguration and system-wide constant values - private final int mSlop; - private final int mMinFlingVelocity; - private final int mMaxFlingVelocity; - protected long mAnimationTime; - - // Fixed properties - private final AbsListView mListView; - private final OnDismissCallback mCallback; - private int mViewWidth = 1; // 1 and not 0 to prevent dividing by zero - - // Transient properties - protected List mPendingDismisses = new ArrayList(); - private int mDismissAnimationRefCount = 0; - private float mDownX; - private float mDownY; - private boolean mSwiping; - - private VelocityTracker mVelocityTracker; - private PendingDismissData mCurrentDismissData; - - private int mVirtualListCount = -1; - - private boolean mDisallowSwipe; - private boolean mIsParentHorizontalScrollContainer; - private int mResIdOfTouchChild; - private boolean mTouchChildTouched; - - private DismissableManager mDismissableManager; - - /** - * Constructs a new swipe-to-dismiss touch listener for the given list view. - * - * @param listView - * The list view whose items should be dismissable. - * @param callback - * The callback to trigger when the user has indicated that she - * would like to dismiss one or more list items. - */ - public SwipeDismissListViewTouchListener(final AbsListView listView, final OnDismissCallback callback, final SwipeOnScrollListener onScroll) { - ViewConfiguration vc = ViewConfiguration.get(listView.getContext()); - mSlop = vc.getScaledTouchSlop(); - mMinFlingVelocity = vc.getScaledMinimumFlingVelocity() * MIN_FLING_VELOCITY_FACTOR; - mMaxFlingVelocity = vc.getScaledMaximumFlingVelocity(); - mAnimationTime = listView.getContext().getResources().getInteger(android.R.integer.config_shortAnimTime); - mListView = listView; - mCallback = callback; - - onScroll.setTouchListener(this); - mListView.setOnScrollListener(onScroll); - } - - public void disallowSwipe() { - mDisallowSwipe = true; - } - - @SuppressWarnings("UnusedDeclaration") - public void allowSwipe() { - mDisallowSwipe = false; - } - - /** - * Set the {@link com.nhaarman.listviewanimations.itemmanipulation.swipedismiss.DismissableManager} to specify which views can or cannot be swiped. - * @param dismissableManager null for no restrictions. - */ - @SuppressWarnings("UnusedDeclaration") - public void setDismissableManager(final DismissableManager dismissableManager) { - mDismissableManager = dismissableManager; - } - - @Override - public boolean onTouch(final View view, final MotionEvent motionEvent) { - if (mVirtualListCount == -1) { - mVirtualListCount = mListView.getAdapter().getCount(); - } - - if (mViewWidth < 2) { - mViewWidth = mListView.getWidth(); - } - - switch (motionEvent.getActionMasked()) { - case MotionEvent.ACTION_DOWN: - mDisallowSwipe = false; - view.onTouchEvent(motionEvent); - return handleDownEvent(motionEvent); - case MotionEvent.ACTION_MOVE: - return handleMoveEvent(motionEvent); - case MotionEvent.ACTION_CANCEL: - return handleCancelEvent(motionEvent); - case MotionEvent.ACTION_UP: - - mDisallowSwipe = false; - mTouchChildTouched = false; - return handleUpEvent(motionEvent); - - } - return false; - } - - @Override - public boolean isSwiping() { - return mSwiping; - } - - /** - * Factory to allow override of dismiss data - */ - protected PendingDismissData createPendingDismissData(final int position, final View view) { - return new PendingDismissData(position, view); - } - - private boolean handleDownEvent(final MotionEvent motionEvent) { - // Find the child view that was touched (perform a hit test) - Rect rect = new Rect(); - int childCount = mListView.getChildCount(); - int[] listViewCoords = new int[2]; - mListView.getLocationOnScreen(listViewCoords); - int x = (int) motionEvent.getRawX() - listViewCoords[0]; - int y = (int) motionEvent.getRawY() - listViewCoords[1]; - View downView = null; - for (int i = 0; i < childCount && downView == null; i++) { - View child = mListView.getChildAt(i); - child.getHitRect(rect); - if (rect.contains(x, y)) { - downView = child; - } - } - - if (downView != null) { - mDownX = motionEvent.getRawX(); - mDownY = motionEvent.getRawY(); - int downPosition = AdapterViewUtil.getPositionForView(mListView, downView); - - if (mDismissableManager != null) { - long downId = mListView.getAdapter().getItemId(downPosition); - if (!mDismissableManager.isDismissable(downId, downPosition)) { - /* Cancel, not dismissable */ - return false; - } - } - - mCurrentDismissData = createPendingDismissData(downPosition, downView); - - if (mPendingDismisses.contains(mCurrentDismissData) || downPosition >= mVirtualListCount) { - // Cancel, we're already processing this position - mCurrentDismissData = null; - return false; - } else { - mTouchChildTouched = !mIsParentHorizontalScrollContainer && mResIdOfTouchChild == 0; - - if (mResIdOfTouchChild != 0) { - mIsParentHorizontalScrollContainer = false; - - final View childView = downView.findViewById(mResIdOfTouchChild); - if (childView != null) { - final Rect childRect = getChildViewRect(mListView, childView); - if (childRect.contains((int) motionEvent.getX(), (int) motionEvent.getY())) { - mTouchChildTouched = true; - mListView.requestDisallowInterceptTouchEvent(true); - } - } - } - - if (mIsParentHorizontalScrollContainer) { - // Do it now and don't wait until the user moves more than - // the slop factor. - mTouchChildTouched = true; - mListView.requestDisallowInterceptTouchEvent(true); - } - - mVelocityTracker = VelocityTracker.obtain(); - mVelocityTracker.addMovement(motionEvent); - } - } - return true; - } - - private Rect getChildViewRect(final View parentView, View childView) { - final Rect childRect = new Rect(childView.getLeft(), childView.getTop(), childView.getRight(), childView.getBottom()); - if (parentView == childView) { - return childRect; - - } - - ViewGroup parent; - while ((parent = (ViewGroup) childView.getParent()) != parentView) { - childRect.offset(parent.getLeft(), parent.getTop()); - childView = parent; - } - - return childRect; - } - - private boolean handleMoveEvent(final MotionEvent motionEvent) { - if (mVelocityTracker == null) { - return false; - } - - mVelocityTracker.addMovement(motionEvent); - float deltaX = motionEvent.getRawX() - mDownX; - float deltaY = motionEvent.getRawY() - mDownY; - if (mTouchChildTouched && !mDisallowSwipe && Math.abs(deltaX) > mSlop && Math.abs(deltaX) > Math.abs(deltaY)) { - mSwiping = true; - mListView.requestDisallowInterceptTouchEvent(true); - - // Cancel ListView's touch (un-highlighting the item) - MotionEvent cancelEvent = MotionEvent.obtain(motionEvent); - cancelEvent.setAction(MotionEvent.ACTION_CANCEL | motionEvent.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT); - mListView.onTouchEvent(cancelEvent); - } - - if (mSwiping) { - ViewHelper.setTranslationX(mCurrentDismissData.view, deltaX); - //noinspection MagicNumber - ViewHelper.setAlpha(mCurrentDismissData.view, Math.max(0f, Math.min(1f, 1f - 2f * Math.abs(deltaX) / mViewWidth))); - return true; - } - return false; - } - - @SuppressWarnings("UnusedParameters") - private boolean handleCancelEvent(final MotionEvent motionEvent) { - if (mVelocityTracker == null) { - return false; - } - - if (mCurrentDismissData != null && mSwiping) { - ViewPropertyAnimator.animate(mCurrentDismissData.view) - .translationX(0) - .alpha(1) - .setDuration(mAnimationTime) - .setListener(null); - } - mVelocityTracker.recycle(); - mVelocityTracker = null; - mDownX = 0; - mDownY = 0; - mCurrentDismissData = null; - mSwiping = false; - return false; - } - - - private boolean handleUpEvent(final MotionEvent motionEvent) { - if (mVelocityTracker == null) { - return false; - } - - float deltaX = motionEvent.getRawX() - mDownX; - mVelocityTracker.addMovement(motionEvent); - mVelocityTracker.computeCurrentVelocity(1000); - float velocityX = Math.abs(mVelocityTracker.getXVelocity()); - float velocityY = Math.abs(mVelocityTracker.getYVelocity()); - boolean dismiss = false; - boolean dismissRight = false; - if (Math.abs(deltaX) > mViewWidth / 2) { - dismiss = true; - dismissRight = deltaX > 0; - } else if (mMinFlingVelocity <= velocityX && velocityX <= mMaxFlingVelocity && velocityY < velocityX) { - dismiss = true; - dismissRight = mVelocityTracker.getXVelocity() > 0; - } - - if (mSwiping) { - if (dismiss) { - // mDownView gets null'd before animation ends - final PendingDismissData pendingDismissData = mCurrentDismissData; - ++mDismissAnimationRefCount; - - animate(mCurrentDismissData.view).translationX(dismissRight ? mViewWidth : -mViewWidth).alpha(0).setDuration(mAnimationTime).setListener(new AnimatorListenerAdapter() { - - @Override - public void onAnimationEnd(final Animator animation) { - onDismiss(pendingDismissData); - } - }); - - mVirtualListCount--; - mPendingDismisses.add(mCurrentDismissData); - } else { - // cancel - animate(mCurrentDismissData.view).translationX(0).alpha(1).setDuration(mAnimationTime).setListener(null); - } - } - - mVelocityTracker.recycle(); - mVelocityTracker = null; - mDownX = 0; - mDownY = 0; - mCurrentDismissData = null; - mSwiping = false; - return false; - } - - protected class PendingDismissData implements Comparable { - public final int position; - public final View view; - - public PendingDismissData(final int position, final View view) { - this.position = position; - this.view = view; - } - - @Override - public int compareTo(final PendingDismissData other) { - // Sort by descending position - return other.position - position; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + position; - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (((Object) this).getClass() != obj.getClass()) - return false; - PendingDismissData other = (PendingDismissData) obj; - return position == other.position; - } - - } - - protected void onDismiss(final PendingDismissData data) { - // default behaviour - performDismiss(data); - } - - protected void performDismiss(final PendingDismissData data) { - // Animate the dismissed list item to zero-height and fire the - // dismiss callback when all dismissed list item animations have - // completed. - - final ViewGroup.LayoutParams lp = data.view.getLayoutParams(); - final int originalHeight = data.view.getHeight(); - - ValueAnimator animator = ValueAnimator.ofInt(originalHeight, 1).setDuration(mAnimationTime); - - animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(final ValueAnimator valueAnimator) { - lp.height = (Integer) valueAnimator.getAnimatedValue(); - data.view.setLayoutParams(lp); - } - }); - - animator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(final Animator animation) { - finalizeDismiss(); - } - }); - animator.start(); - } - - /** - * Here you can manage dismissed View. - */ - protected void recycleDismissedViewsItems(final List pendingDismisses) { - ViewGroup.LayoutParams lp; - for (final PendingDismissData pendingDismiss : pendingDismisses) { - // Reset view presentation - ViewHelper.setAlpha(pendingDismiss.view, 1f); - ViewHelper.setTranslationX(pendingDismiss.view, 0); - lp = pendingDismiss.view.getLayoutParams(); - lp.height = 0; - pendingDismiss.view.setLayoutParams(lp); - } - } - - protected void finalizeDismiss() { - --mDismissAnimationRefCount; - if (mDismissAnimationRefCount == 0) { - // No active animations, process all pending dismisses. - // Sort by descending position - Collections.sort(mPendingDismisses); - - int[] dismissPositions = new int[mPendingDismisses.size()]; - for (int i = mPendingDismisses.size() - 1; i >= 0; i--) { - dismissPositions[i] = mPendingDismisses.get(i).position; - } - mCallback.onDismiss(mListView, dismissPositions); - - recycleDismissedViewsItems(mPendingDismisses); - - mPendingDismisses.clear(); - } - } - - void setIsParentHorizontalScrollContainer(final boolean isParentHorizontalScrollContainer) { - mIsParentHorizontalScrollContainer = mResIdOfTouchChild == 0 && isParentHorizontalScrollContainer; - } - - void setTouchChild(final int childResId) { - mResIdOfTouchChild = childResId; - if (childResId != 0) { - setIsParentHorizontalScrollContainer(false); - } - } - - public void notifyDataSetChanged() { - mVirtualListCount = mListView.getAdapter().getCount(); - } -} diff --git a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/swipedismiss/SwipeOnScrollListener.java b/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/swipedismiss/SwipeOnScrollListener.java deleted file mode 100644 index f5ea237..0000000 --- a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/swipedismiss/SwipeOnScrollListener.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2013 Niek Haarman - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * External default OnScrollListener allowing to custom onScrollListening events like loading more items. - * Author: David Berlioz - */ - -package com.nhaarman.listviewanimations.itemmanipulation.swipedismiss; - -import android.widget.AbsListView; - -/** - * An {@link android.widget.AbsListView.OnScrollListener} that is used in conjunction with {@link com.nhaarman.listviewanimations.itemmanipulation.swipedismiss.SwipeDismissAdapter}. Override this class to - * provide a custom implementation of the OnScrollListener. Do not forget to call super on the overridden methods! - */ -public class SwipeOnScrollListener implements AbsListView.OnScrollListener { - - private SwipeDismissListViewTouchListener mTouchListener; - - public void setTouchListener(final SwipeDismissListViewTouchListener touchListener) { - mTouchListener = touchListener; - } - - @Override - public void onScrollStateChanged(final AbsListView view, final int scrollState) { - if (scrollState != AbsListView.OnScrollListener.SCROLL_STATE_IDLE) { - mTouchListener.disallowSwipe(); - } - } - - @Override - public void onScroll(final AbsListView view, final int firstVisibleItem, final int visibleItemCount, final int totalItemCount) { - } -} diff --git a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/swipedismiss/SwipeOnTouchListener.java b/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/swipedismiss/SwipeOnTouchListener.java deleted file mode 100644 index c06b29b..0000000 --- a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/swipedismiss/SwipeOnTouchListener.java +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (c) 2013 K–NFB Reading Technology, Inc. - */ - -package com.nhaarman.listviewanimations.itemmanipulation.swipedismiss; - -import android.view.View; - -/** - * An OnTouchListener that should be used when list-view items can be swiped horizontally. - * @author Anton Spaans on 9/12/13. - */ -public interface SwipeOnTouchListener extends View.OnTouchListener { - /** - * @return true if the user is currently swiping a list-item horizontally. - */ - public boolean isSwiping(); -} diff --git a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/swipedismiss/contextualundo/ContextualUndoAdapter.java b/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/swipedismiss/contextualundo/ContextualUndoAdapter.java deleted file mode 100644 index b13965e..0000000 --- a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/swipedismiss/contextualundo/ContextualUndoAdapter.java +++ /dev/null @@ -1,567 +0,0 @@ -/* - * Copyright 2013 Frankie Sardo - * Copyright 2013 Niek Haarman - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.nhaarman.listviewanimations.itemmanipulation.swipedismiss.contextualundo; - -import android.app.Activity; -import android.os.Bundle; -import android.os.Handler; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AbsListView; -import android.widget.BaseAdapter; -import android.widget.ListView; -import android.widget.TextView; - -import com.nhaarman.listviewanimations.BaseAdapterDecorator; -import com.nhaarman.listviewanimations.util.AdapterViewUtil; -import com.nineoldandroids.animation.Animator; -import com.nineoldandroids.animation.AnimatorListenerAdapter; -import com.nineoldandroids.animation.ObjectAnimator; -import com.nineoldandroids.animation.ValueAnimator; -import com.nineoldandroids.view.ViewHelper; - -import static com.nineoldandroids.view.ViewHelper.setAlpha; -import static com.nineoldandroids.view.ViewHelper.setTranslationX; -import static com.nineoldandroids.view.ViewPropertyAnimator.animate; - -/** - * Warning: a stable id for each item in the adapter is required. The decorated - * adapter should not try to cast convertView to a particular view. The - * undoLayout should have the same height as the content row. - *

- * Usage:
- * * Create a new instance of this class providing the {@link BaseAdapter} to wrap, the undo layout, the undo button id and a {@link DeleteItemCallback}, optionally a delay time millis, - * a count down TextView res id, - * , a delay in milliseconds before deleting the item.
- * * Set your {@link ListView} to this ContextualUndoAdapter, and set this ContextualUndoAdapter to your ListView.
- */ -@SuppressWarnings("UnusedDeclaration") -public class ContextualUndoAdapter extends BaseAdapterDecorator implements ContextualUndoListViewTouchListener.Callback { - - private static final int ANIMATION_DURATION = 150; - private static final String EXTRA_ACTIVE_REMOVED_ID = "removedId"; - private static final String X = "x"; - - private final int mUndoLayoutId; - private final int mUndoActionId; - private final int mCountDownTextViewResId; - private final int mAutoDeleteDelayMillis; - - private long mDismissStartMillis; - - private ContextualUndoView mCurrentRemovedView; - private long mCurrentRemovedId; - - private final Handler mHandler; - private final CountDownRunnable mCountDownRunnable; - - private final DeleteItemCallback mDeleteItemCallback; - private final CountDownFormatter mCountDownFormatter; - - private ContextualUndoListViewTouchListener mContextualUndoListViewTouchListener; - - /** - * Create a new ContextualUndoAdapter based on given parameters. - * - * @param baseAdapter The {@link BaseAdapter} to wrap - * @param undoLayoutId The layout resource id to show as undo - * @param undoActionId The id of the component which undoes the dismissal - * @param deleteItemCallback The {@link DeleteItemCallback} which is called when an item should be deleted from your collection. - */ - public ContextualUndoAdapter(final BaseAdapter baseAdapter, final int undoLayoutId, final int undoActionId, final DeleteItemCallback deleteItemCallback) { - this(baseAdapter, undoLayoutId, undoActionId, -1, -1, deleteItemCallback, null); - } - - /** - * Create a new ContextualUndoAdapter based on given parameters. - * Will automatically remove the swiped item after autoDeleteTimeMillis milliseconds. - * - * @param baseAdapter The {@link BaseAdapter} to wrap - * @param undoLayoutResId The layout resource id to show as undo - * @param undoActionResId The id of the component which undoes the dismissal - * @param autoDeleteTimeMillis The time in milliseconds that the adapter will wait for he user to hit undo before automatically deleting the item - * @param deleteItemCallback The {@link DeleteItemCallback} which is called when an item should be deleted from your collection. - */ - public ContextualUndoAdapter(final BaseAdapter baseAdapter, final int undoLayoutResId, final int undoActionResId, final int autoDeleteTimeMillis, final DeleteItemCallback deleteItemCallback) { - this(baseAdapter, undoLayoutResId, undoActionResId, autoDeleteTimeMillis, -1, deleteItemCallback, null); - } - - /** - * Create a new ContextualUndoAdapter based on given parameters. - * Will automatically remove the swiped item after autoDeleteTimeMillis milliseconds. - * - * @param baseAdapter The {@link BaseAdapter} to wrap - * @param undoLayoutResId The layout resource id to show as undo - * @param undoActionResId The resource id of the component which undoes the dismissal - * @param autoDeleteTime The time in milliseconds that adapter will wait for user to hit undo before automatically deleting item - * @param countDownTextViewResId The resource id of the {@link TextView} in the undoLayoutResId that will show the time left - * @param deleteItemCallback The {@link DeleteItemCallback} which is called when an item should be deleted from your collection. - * @param countDownFormatter The {@link CountDownFormatter} which provides text to be shown in the {@link TextView} as specified by countDownTextViewResId - */ - public ContextualUndoAdapter(final BaseAdapter baseAdapter, final int undoLayoutResId, final int undoActionResId, final int autoDeleteTime, final int countDownTextViewResId, - final DeleteItemCallback deleteItemCallback, final CountDownFormatter countDownFormatter) { - super(baseAdapter); - - mHandler = new Handler(); - mCountDownRunnable = new CountDownRunnable(); - - mUndoLayoutId = undoLayoutResId; - mUndoActionId = undoActionResId; - mCurrentRemovedId = -1; - mAutoDeleteDelayMillis = autoDeleteTime; - mCountDownTextViewResId = countDownTextViewResId; - - mDeleteItemCallback = deleteItemCallback; - mCountDownFormatter = countDownFormatter; - } - - @Override - public final View getView(final int position, final View convertView, final ViewGroup parent) { - final ViewHolder vh; - ContextualUndoView contextualUndoView = (ContextualUndoView) convertView; - if (contextualUndoView == null) { - contextualUndoView = new ContextualUndoView(parent.getContext(), mUndoLayoutId, mCountDownTextViewResId); - contextualUndoView.findViewById(mUndoActionId).setOnClickListener(new UndoListener(contextualUndoView)); - vh = new ViewHolder(contextualUndoView); - } else { - vh = ViewHolder.getViewHolder(contextualUndoView); - } - - View contentView = super.getView(position, contextualUndoView.getContentView(), contextualUndoView); - contextualUndoView.updateContentView(contentView); - - long itemId = getItemId(position); - vh.mItemId = itemId; - - if (itemId == mCurrentRemovedId) { - contextualUndoView.displayUndo(); - long millisLeft = mAutoDeleteDelayMillis - (System.currentTimeMillis() - mDismissStartMillis); - if (mCountDownFormatter != null) { - contextualUndoView.updateCountDownTimer(mCountDownFormatter.getCountDownString(millisLeft)); - } - } else { - contextualUndoView.displayContentView(); - } - - contextualUndoView.setItemId(itemId); - return contextualUndoView; - } - - @Override - public void setAbsListView(final AbsListView listView) { - super.setAbsListView(listView); - mContextualUndoListViewTouchListener = new ContextualUndoListViewTouchListener(listView, this); - mContextualUndoListViewTouchListener.setIsParentHorizontalScrollContainer(isParentHorizontalScrollContainer()); - mContextualUndoListViewTouchListener.setTouchChild(getTouchChild()); - listView.setOnTouchListener(mContextualUndoListViewTouchListener); - listView.setOnScrollListener(mContextualUndoListViewTouchListener.makeScrollListener()); - listView.setOnHierarchyChangeListener(new HierarchyChangeListener()); - } - - @Override - public void onViewSwiped(final long dismissViewItemId, final int dismissPosition) { - ContextualUndoView contextualUndoView = getContextualUndoView(dismissViewItemId); - if (contextualUndoView == null) { - removePreviousContextualUndoIfPresent(); - mCurrentRemovedView = null; - mCurrentRemovedId = dismissViewItemId; - } else if (contextualUndoView.isContentDisplayed()) { - restoreViewPosition(contextualUndoView); - contextualUndoView.displayUndo(); - removePreviousContextualUndoIfPresent(); - setCurrentRemovedView(contextualUndoView); - - if (mAutoDeleteDelayMillis > 0) { - startAutoDeleteTimer(); - } - } else { - performRemovalIfNecessary(); - } - } - - private ContextualUndoView getContextualUndoView(final long dismissViewItemId) { - ContextualUndoView contextualUndoView = null; - - AbsListView listView = getAbsListView(); - int childCount = listView.getChildCount(); - for (int i = 0; i < childCount; i++) { - View child = listView.getChildAt(i); - if (child instanceof ContextualUndoView) { - ContextualUndoView listItem = (ContextualUndoView) child; - if (listItem.getItemId() == dismissViewItemId) { - contextualUndoView = listItem; - } - } - } - return contextualUndoView; - } - - private void startAutoDeleteTimer() { - mHandler.removeCallbacks(mCountDownRunnable); - - if (mCountDownFormatter != null) { - mCurrentRemovedView.updateCountDownTimer(mCountDownFormatter.getCountDownString(mAutoDeleteDelayMillis)); - } - - mDismissStartMillis = System.currentTimeMillis(); - mHandler.postDelayed(mCountDownRunnable, Math.min(1000, mAutoDeleteDelayMillis)); - } - - private void restoreViewPosition(final View view) { - setAlpha(view, 1f); - setTranslationX(view, 0); - } - - private void removePreviousContextualUndoIfPresent() { - if (mCurrentRemovedView != null) { - performRemovalIfNecessary(); - } - } - - private void setCurrentRemovedView(final ContextualUndoView currentRemovedView) { - mCurrentRemovedView = currentRemovedView; - mCurrentRemovedId = currentRemovedView.getItemId(); - } - - private void clearCurrentRemovedView() { - mCurrentRemovedView = null; - mCurrentRemovedId = -1; - mHandler.removeCallbacks(mCountDownRunnable); - } - - @Override - public void onListScrolled() { - performRemovalIfNecessary(); - } - - private void performRemovalIfNecessary() { - if (mCurrentRemovedId == -1) { - return; - } - - ContextualUndoView currentRemovedView = getCurrentRemovedView(mCurrentRemovedView, mCurrentRemovedId); - if (currentRemovedView != null) { - ValueAnimator animator = ValueAnimator.ofInt(currentRemovedView.getHeight(), 1).setDuration(ANIMATION_DURATION); - - RemoveViewAnimatorListenerAdapter listener = new RemoveViewAnimatorListenerAdapter(currentRemovedView, mCurrentRemovedId); - RemoveViewAnimatorUpdateListener updateListener = new RemoveViewAnimatorUpdateListener(listener); - - animator.addListener(listener); - animator.addUpdateListener(updateListener); - animator.start(); - } else { - // The hard way. - deleteItemGivenId(mCurrentRemovedId); - } - clearCurrentRemovedView(); - } - - private void deleteItemGivenId(final long deleteItemId) { - int position = -1; - int numItems = getCount(); - for (int i = 0; i < numItems; i++) { - long itemId = getItemId(i); - if (itemId == deleteItemId) { - position = i; - break; - } - } - - if (position >= 0) { - mDeleteItemCallback.deleteItem(position); - } - } - - private ContextualUndoView getCurrentRemovedView(final ContextualUndoView currentRemovedView, final long itemId) { - ContextualUndoView result = currentRemovedView; - if (result == null || - result.getParent() == null || - result.getItemId() != itemId || - AdapterViewUtil.getPositionForView(getAbsListView(), result) < 0) { - result = getContextualUndoView(itemId); - } - return result; - } - - /** - * This method should be called in your {@link Activity}'s {@link Activity#onSaveInstanceState(Bundle)} to remember dismissed statuses. - * @param outState the {@link Bundle} provided by Activity.onSaveInstanceState(Bundle). - */ - public void onSaveInstanceState(final Bundle outState) { - outState.putLong(EXTRA_ACTIVE_REMOVED_ID, mCurrentRemovedId); - } - - /** - * This method should be called in your {@link Activity#onRestoreInstanceState(Bundle)} to remember dismissed statuses. - */ - public void onRestoreInstanceState(final Bundle savedInstanceState) { - if (savedInstanceState != null) { - mCurrentRemovedId = savedInstanceState.getLong(EXTRA_ACTIVE_REMOVED_ID, -1); - } - } - - /** - * Animate the item at given position away and show the undo {@link View}. - * @param position the position. - */ - public void swipeViewAtPosition(final int position) { - mCurrentRemovedId = getItemId(position); - for (int i = 0; i < getAbsListView().getChildCount(); i++) { - AbsListView absListView = getAbsListView(); - View childView = absListView.getChildAt(i); - int positionForView = AdapterViewUtil.getPositionForView(absListView, childView); - if (positionForView == position) { - swipeView(childView, positionForView); - } - } - } - - private void swipeView(final View view, final int dismissPosition) { - ObjectAnimator animator = ObjectAnimator.ofFloat(view, X, view.getMeasuredWidth()); - animator.addListener(new AnimatorListenerAdapter() { - - @Override - public void onAnimationEnd(final Animator animator) { - onViewSwiped(((ContextualUndoView) view).getItemId(), dismissPosition); - } - }); - animator.start(); - } - - @Override - public void setIsParentHorizontalScrollContainer(final boolean isParentHorizontalScrollContainer) { - super.setIsParentHorizontalScrollContainer(isParentHorizontalScrollContainer); - if (mContextualUndoListViewTouchListener != null) { - mContextualUndoListViewTouchListener.setIsParentHorizontalScrollContainer(isParentHorizontalScrollContainer); - } - } - - @Override - public void setTouchChild(final int childResId) { - super.setTouchChild(childResId); - if (mContextualUndoListViewTouchListener != null) { - mContextualUndoListViewTouchListener.setTouchChild(childResId); - } - } - - /** - * Removes any item that was swiped away. - * @param animate If true, animates the removal (collapsing the item). - * If false, removes item immediately without animation. - * @deprecated use {@link #removePendingItem()} or {@link #animateRemovePendingItem()} instead. - */ - @Deprecated - public void removePendingItem(final boolean animate) { - if (animate) { - animateRemovePendingItem(); - } else { - removePendingItem(); - } - } - - /** - * Cancels the count down, and removes any item that was swiped away, without animating. Will cause {@link DeleteItemCallback#deleteItem(int)} to be called. - */ - public void removePendingItem() { - if (mCurrentRemovedView != null || mCurrentRemovedId >= 0) { - new RemoveViewAnimatorListenerAdapter(mCurrentRemovedView, mCurrentRemovedId).onAnimationEnd(null); - clearCurrentRemovedView(); - } - } - - /** - * Removes any item that was swiped away, animating the removal (collapsing the item). {@link DeleteItemCallback#deleteItem(int)} to be called. - */ - public void animateRemovePendingItem() { - removePreviousContextualUndoIfPresent(); - } - - /** - * Cancel the count down. This will not cause the {@link DeleteItemCallback#deleteItem(int)} to be called. Use {@link #removePendingItem()} for that instead. - */ - public void cancelCountDown() { - mHandler.removeCallbacks(mCountDownRunnable); - } - - /** - * A callback interface which is used to notify when items should be removed from the collection. - */ - public interface DeleteItemCallback { - /** - * Called when an item should be removed from the collection. - * - * @param position - * the position of the item that should be removed. - */ - public void deleteItem(int position); - } - - /** - * A callback interface which is used to provide the text to display when counting down. - */ - public interface CountDownFormatter { - /** - * Called each tick of the CountDownTimer - * @param millisLeft time in milliseconds remaining before the item is automatically removed - */ - public String getCountDownString(final long millisLeft); - } - - private class CountDownRunnable implements Runnable { - - @Override - public void run() { - long millisRemaining = mAutoDeleteDelayMillis - (System.currentTimeMillis() - mDismissStartMillis); - if (mCountDownFormatter != null) { - mCurrentRemovedView.updateCountDownTimer(mCountDownFormatter.getCountDownString(millisRemaining)); - } - - if (millisRemaining <= 0) { - performRemovalIfNecessary(); - } else { - mHandler.postDelayed(this, Math.min(millisRemaining, 1000)); - } - } - } - - private class RemoveViewAnimatorListenerAdapter extends AnimatorListenerAdapter { - - private ContextualUndoView mDismissView; - private final long mDismissViewId; - private final int mOriginalHeight; - - public RemoveViewAnimatorListenerAdapter(final ContextualUndoView dismissView, final long dismissViewId) { - mDismissView = dismissView; - mDismissViewId = dismissViewId; - mOriginalHeight = dismissView.getHeight(); - } - - @Override - public void onAnimationEnd(final Animator animation) { - mDismissView = getViewBeingAnimated(); - if (mDismissView == null) { - deleteItemGivenId(mDismissViewId); - return; - } - - restoreViewPosition(mDismissView); - restoreViewDimension(mDismissView); - deleteCurrentItem(mDismissView); - } - - private void restoreViewDimension(final View view) { - ViewGroup.LayoutParams lp; - lp = view.getLayoutParams(); - lp.height = mOriginalHeight; - view.setLayoutParams(lp); - } - - private void deleteCurrentItem(final View view) { - int position = AdapterViewUtil.getPositionForView(getAbsListView(), view); - mDeleteItemCallback.deleteItem(position); - } - - private ContextualUndoView getViewBeingAnimated() { - ContextualUndoView newDismissView = getCurrentRemovedView(mDismissView, mDismissViewId); - if (newDismissView != mDismissView) { - restoreViewPosition(mDismissView); - restoreViewDimension(mDismissView); - - mDismissView = newDismissView; - } - return mDismissView; - } - } - - private class RemoveViewAnimatorUpdateListener implements ValueAnimator.AnimatorUpdateListener { - - final RemoveViewAnimatorListenerAdapter mParentAdapter; - private final ViewGroup.LayoutParams mLayoutParams; - - public RemoveViewAnimatorUpdateListener(final RemoveViewAnimatorListenerAdapter parentAdapter) { - mParentAdapter = parentAdapter; - mLayoutParams = parentAdapter.mDismissView.getLayoutParams(); - } - - @Override - public void onAnimationUpdate(final ValueAnimator valueAnimator) { - ContextualUndoView dismissView = mParentAdapter.getViewBeingAnimated(); - if (dismissView != null) { - mLayoutParams.height = (Integer) valueAnimator.getAnimatedValue(); - dismissView.setLayoutParams(mLayoutParams); - } - } - } - - private class UndoListener implements View.OnClickListener { - - private final ContextualUndoView mContextualUndoView; - - public UndoListener(final ContextualUndoView contextualUndoView) { - mContextualUndoView = contextualUndoView; - } - - @Override - public void onClick(final View v) { - clearCurrentRemovedView(); - mContextualUndoView.displayContentView(); - moveViewOffScreen(); - animateViewComingBack(); - } - - private void moveViewOffScreen() { - ViewHelper.setTranslationX(mContextualUndoView, mContextualUndoView.getWidth()); - } - - private void animateViewComingBack() { - animate(mContextualUndoView).translationX(0).setDuration(ANIMATION_DURATION).setListener(null); - } - } - - private class HierarchyChangeListener implements ViewGroup.OnHierarchyChangeListener { - @Override - public void onChildViewAdded(final View parent, final View child) { - final ViewHolder vh = ViewHolder.getViewHolder(child); - if (vh != null && mCurrentRemovedId > 0 && vh.mItemId == mCurrentRemovedId) { - mCurrentRemovedView = (ContextualUndoView) child; - } - } - - @Override - public void onChildViewRemoved(final View parent, final View child) { - final ViewHolder vh = ViewHolder.getViewHolder(child); - if (vh != null && mCurrentRemovedId > 0 && vh.mItemId == mCurrentRemovedId) { - mCurrentRemovedView = null; - } - } - } - - private static class ViewHolder { - final ContextualUndoView mContextualUndoView; - - long mItemId; - - static ViewHolder getViewHolder(final View view) { - return (ViewHolder) view.getTag(); - } - - ViewHolder(final ContextualUndoView contextualUndoView) { - mContextualUndoView = contextualUndoView; - mContextualUndoView.setTag(this); - } - } -} \ No newline at end of file diff --git a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/swipedismiss/contextualundo/ContextualUndoListViewTouchListener.java b/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/swipedismiss/contextualundo/ContextualUndoListViewTouchListener.java deleted file mode 100644 index 8a82433..0000000 --- a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/swipedismiss/contextualundo/ContextualUndoListViewTouchListener.java +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Copyright 2012 Roman Nurik - * Copyright 2013 Frankie Sardo - * Copyright 2013 Niek Haarman - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.nhaarman.listviewanimations.itemmanipulation.swipedismiss.contextualundo; - -import android.graphics.Rect; -import android.view.MotionEvent; -import android.view.VelocityTracker; -import android.view.View; -import android.view.View.OnTouchListener; -import android.view.ViewConfiguration; -import android.view.ViewGroup; -import android.widget.AbsListView; -import android.widget.AdapterView; -import android.widget.BaseAdapter; - -import com.nhaarman.listviewanimations.itemmanipulation.swipedismiss.DismissableManager; -import com.nhaarman.listviewanimations.itemmanipulation.swipedismiss.SwipeOnTouchListener; -import com.nhaarman.listviewanimations.util.AdapterViewUtil; -import com.nineoldandroids.animation.Animator; -import com.nineoldandroids.animation.AnimatorListenerAdapter; - -import static com.nineoldandroids.view.ViewHelper.setAlpha; -import static com.nineoldandroids.view.ViewHelper.setTranslationX; -import static com.nineoldandroids.view.ViewPropertyAnimator.animate; - -/** - * An {@link OnTouchListener} for the {@link ContextualUndoAdapter}. Don't use - * this class directly, use ContextualUndoAdapter to wrap your - * {@link BaseAdapter}s. - */ -public class ContextualUndoListViewTouchListener implements SwipeOnTouchListener { - // Cached ViewConfiguration and system-wide constant values - private final int mSlop; - private final int mMinFlingVelocity; - private final int mMaxFlingVelocity; - private final long mAnimationTime; - - // Fixed properties - private final AbsListView mListView; - private final Callback mCallback; - private int mViewWidth = 1; // 1 and not 0 to prevent dividing by zero - - // Transient properties - private float mDownX; - private float mDownY; - private boolean mSwiping; - private VelocityTracker mVelocityTracker; - private int mDownPosition; - private View mDownView; - private boolean mPaused; - private boolean mDisallowSwipe; - - private boolean mIsParentHorizontalScrollContainer; - private int mResIdOfTouchChild; - private boolean mTouchChildTouched; - - private DismissableManager mDismissableManager; - - public interface Callback { - - void onViewSwiped(long dismissViewItemId, int dismissPosition); - - void onListScrolled(); - } - - public ContextualUndoListViewTouchListener(final AbsListView listView, final Callback callback) { - ViewConfiguration vc = ViewConfiguration.get(listView.getContext()); - mSlop = vc.getScaledTouchSlop(); - mMinFlingVelocity = vc.getScaledMinimumFlingVelocity(); - mMaxFlingVelocity = vc.getScaledMaximumFlingVelocity(); - mAnimationTime = listView.getContext().getResources().getInteger(android.R.integer.config_shortAnimTime); - mListView = listView; - mCallback = callback; - } - - public void setEnabled(final boolean enabled) { - mPaused = !enabled; - } - - /** - * Set the {@link com.nhaarman.listviewanimations.itemmanipulation.swipedismiss.DismissableManager} to specify which views can or cannot be swiped. - * @param dismissableManager null for no restrictions. - */ - @SuppressWarnings("UnusedDeclaration") - public void setDismissableManager(final DismissableManager dismissableManager) { - mDismissableManager = dismissableManager; - } - - public AbsListView.OnScrollListener makeScrollListener() { - return new AbsListView.OnScrollListener() { - @Override - public void onScrollStateChanged(final AbsListView absListView, final int scrollState) { - setEnabled(scrollState != AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL); - if (mPaused) { - mCallback.onListScrolled(); - } - if (scrollState != AbsListView.OnScrollListener.SCROLL_STATE_IDLE) { - mDisallowSwipe = true; - } - - } - - @Override - public void onScroll(final AbsListView absListView, final int firstVisibleItem, final int visibleItemCount, - final int totalItemCount) { - } - }; - } - - @Override - public boolean onTouch(final View view, final MotionEvent motionEvent) { - if (mViewWidth < 2) { - mViewWidth = mListView.getWidth(); - } - - boolean result; - switch (motionEvent.getActionMasked()) { - case MotionEvent.ACTION_DOWN: - result = handleDownEvent(view, motionEvent); - break; - case MotionEvent.ACTION_MOVE: - result = handleMoveEvent(view, motionEvent); - break; - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_CANCEL: - result = handleUpCancelEvent(view, motionEvent); - break; - default: - result = false; - } - return result; - } - - private boolean handleDownEvent(final View view, final MotionEvent motionEvent) { - mDisallowSwipe = false; - if (mPaused) { - return false; - } - - // Find the child view that was touched (perform a hit test) - Rect rect = new Rect(); - int childCount = mListView.getChildCount(); - int[] listViewCoords = new int[2]; - mListView.getLocationOnScreen(listViewCoords); - int x = (int) motionEvent.getRawX() - listViewCoords[0]; - int y = (int) motionEvent.getRawY() - listViewCoords[1]; - View child; - for (int i = 0; i < childCount; i++) { - child = mListView.getChildAt(i); - child.getHitRect(rect); - if (rect.contains(x, y)) { - mDownView = child; - break; - } - } - - if (mDownView != null && mDownView instanceof ContextualUndoView) { - mDownX = motionEvent.getRawX(); - mDownY = motionEvent.getRawY(); - int downPosition = AdapterViewUtil.getPositionForView(mListView, mDownView); - - if (mDismissableManager != null) { - long downId = mListView.getAdapter().getItemId(downPosition); - if (!mDismissableManager.isDismissable(downId, downPosition)) { - /* Cancel, not dismissable */ - return false; - } - } - - mTouchChildTouched = !mIsParentHorizontalScrollContainer && mResIdOfTouchChild == 0; - - if (mResIdOfTouchChild != 0) { - mIsParentHorizontalScrollContainer = false; - - final View childView = mDownView.findViewById(mResIdOfTouchChild); - if (childView != null) { - final Rect childRect = getChildViewRect(mListView, childView); - if (childRect.contains((int) motionEvent.getX(), (int) motionEvent.getY())) { - mTouchChildTouched = true; - mListView.requestDisallowInterceptTouchEvent(true); - } - } - } - - if (mIsParentHorizontalScrollContainer) { - // Do it now and don't wait until the user moves more than - // the slop factor. - mTouchChildTouched = true; - mListView.requestDisallowInterceptTouchEvent(true); - } - - mDownY = motionEvent.getRawY(); - mDownPosition = AdapterViewUtil.getPositionForView(mListView, mDownView); - - if (mTouchChildTouched) { - mVelocityTracker = VelocityTracker.obtain(); - mVelocityTracker.addMovement(motionEvent); - } else { - mVelocityTracker = null; - } - } - view.onTouchEvent(motionEvent); - return true; - } - - @SuppressWarnings("UnusedParameters") - private boolean handleMoveEvent(final View view, final MotionEvent motionEvent) { - if (mVelocityTracker == null || mPaused) { - return false; - } - - mVelocityTracker.addMovement(motionEvent); - float deltaX = motionEvent.getRawX() - mDownX; - float deltaY = motionEvent.getRawY() - mDownY; - if (mTouchChildTouched && !mDisallowSwipe && Math.abs(deltaX) > mSlop && Math.abs(deltaX) > Math.abs(deltaY)) { - mSwiping = true; - mListView.requestDisallowInterceptTouchEvent(true); - - // Cancel ListView's touch (un-highlighting the item) - MotionEvent cancelEvent = MotionEvent.obtain(motionEvent); - cancelEvent.setAction(MotionEvent.ACTION_CANCEL | motionEvent.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT); - mListView.onTouchEvent(cancelEvent); - cancelEvent.recycle(); - } - - if (mSwiping) { - setTranslationX(mDownView, deltaX); - //noinspection MagicNumber - setAlpha(mDownView, Math.max(0f, Math.min(1f, 1f - 2f * Math.abs(deltaX) / mViewWidth))); - return true; - } - return false; - } - - @SuppressWarnings("UnusedParameters") - private boolean handleUpCancelEvent(final View view, final MotionEvent motionEvent) { - mDisallowSwipe = false; - if (mVelocityTracker == null) { - return false; - } - - float deltaX = motionEvent.getRawX() - mDownX; - mVelocityTracker.addMovement(motionEvent); - mVelocityTracker.computeCurrentVelocity(1000); - float velocityX = Math.abs(mVelocityTracker.getXVelocity()); - float velocityY = Math.abs(mVelocityTracker.getYVelocity()); - boolean dismiss = false; - boolean dismissRight = false; - final float absDeltaX = Math.abs(deltaX); - if (absDeltaX > mViewWidth / 2) { - dismiss = true; - dismissRight = deltaX > 0; - } else if (mMinFlingVelocity <= velocityX && velocityX <= mMaxFlingVelocity && velocityY < velocityX && absDeltaX > mSlop) { - dismiss = true; - dismissRight = mVelocityTracker.getXVelocity() > 0; - } - if (dismiss) { - // dismiss - final long itemId = ((ContextualUndoView) mDownView).getItemId(); - // before animation ends - final int downPosition = mDownPosition; - animate(mDownView).translationX(dismissRight ? mViewWidth : -mViewWidth).alpha(0).setDuration(mAnimationTime).setListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(final Animator animation) { - mCallback.onViewSwiped(itemId, downPosition); - } - }); - } else { - // cancel - animate(mDownView).translationX(0).alpha(1).setDuration(mAnimationTime).setListener(null); - } - - mVelocityTracker.recycle(); - mVelocityTracker = null; - mDownX = 0; - mDownView = null; - mDownPosition = AdapterView.INVALID_POSITION; - mSwiping = false; - return false; - } - - @Override - public boolean isSwiping() { - return mSwiping; - } - - private Rect getChildViewRect(final View parentView, View childView) { - final Rect childRect = new Rect(childView.getLeft(), childView.getTop(), childView.getRight(), childView.getBottom()); - if (parentView == childView) { - return childRect; - - } - - ViewGroup parent; - while ((parent = (ViewGroup) childView.getParent()) != parentView) { - childRect.offset(parent.getLeft(), parent.getTop()); - childView = parent; - } - - return childRect; - } - - void setIsParentHorizontalScrollContainer(final boolean isParentHorizontalScrollContainer) { - mIsParentHorizontalScrollContainer = mResIdOfTouchChild == 0 && isParentHorizontalScrollContainer; - } - - void setTouchChild(final int childResId) { - mResIdOfTouchChild = childResId; - if (childResId != 0) { - setIsParentHorizontalScrollContainer(false); - } - } -} diff --git a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/swipedismiss/contextualundo/ContextualUndoView.java b/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/swipedismiss/contextualundo/ContextualUndoView.java deleted file mode 100644 index 282a613..0000000 --- a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/itemmanipulation/swipedismiss/contextualundo/ContextualUndoView.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2013 Frankie Sardo - * Copyright 2013 Niek Haarman - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.nhaarman.listviewanimations.itemmanipulation.swipedismiss.contextualundo; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.view.View; -import android.widget.FrameLayout; -import android.widget.TextView; - -@SuppressLint("ViewConstructor") -public class ContextualUndoView extends FrameLayout { - - private View mUndoView; - private View mContentView; - private TextView mCountDownTV; - - private long mItemId; - - public ContextualUndoView(final Context context, final int undoLayoutResId, final int countDownTextViewResId) { - super(context); - initUndo(undoLayoutResId, countDownTextViewResId); - } - - private void initUndo(final int undoLayoutResId, final int countDownTextViewResId) { - mUndoView = View.inflate(getContext(), undoLayoutResId, null); - addView(mUndoView); - - if (countDownTextViewResId != -1) { - mCountDownTV = (TextView) mUndoView.findViewById(countDownTextViewResId); - } - } - - public void updateCountDownTimer(final String timerText) { - if (mCountDownTV != null) { - mCountDownTV.setText(timerText); - } - } - - public void updateContentView(final View contentView) { - if (mContentView == null) { - addView(contentView); - } - mContentView = contentView; - } - - public View getContentView() { - return mContentView; - } - - public void setItemId(final long itemId) { - this.mItemId = itemId; - } - - public long getItemId() { - return mItemId; - } - - public boolean isContentDisplayed() { - return mContentView.getVisibility() == View.VISIBLE; - } - - public void displayUndo() { - updateCountDownTimer(""); - mContentView.setVisibility(View.INVISIBLE); - mUndoView.setVisibility(View.VISIBLE); - } - - public void displayContentView() { - mContentView.setVisibility(View.VISIBLE); - mUndoView.setVisibility(View.INVISIBLE); - } -} \ No newline at end of file diff --git a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/swinginadapters/AnimationAdapter.java b/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/swinginadapters/AnimationAdapter.java deleted file mode 100644 index 50925f6..0000000 --- a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/swinginadapters/AnimationAdapter.java +++ /dev/null @@ -1,295 +0,0 @@ -/* - * Copyright 2013 Niek Haarman - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.nhaarman.listviewanimations.swinginadapters; - -import android.annotation.SuppressLint; -import android.os.Build; -import android.util.SparseArray; -import android.view.View; -import android.view.ViewGroup; -import android.widget.BaseAdapter; -import android.widget.GridView; - -import com.nhaarman.listviewanimations.BaseAdapterDecorator; -import com.nineoldandroids.animation.Animator; -import com.nineoldandroids.animation.AnimatorSet; -import com.nineoldandroids.animation.ObjectAnimator; -import com.nineoldandroids.view.ViewHelper; - -/** - * A {@link BaseAdapterDecorator} class which applies multiple {@link Animator}s at once to - * views when they are first shown. The Animators applied include the animations - * specified in {@link #getAnimators(ViewGroup, View)}, plus an alpha transition. - */ -public abstract class AnimationAdapter extends BaseAdapterDecorator { - - protected static final long DEFAULTANIMATIONDELAYMILLIS = 100; - protected static final long DEFAULTANIMATIONDURATIONMILLIS = 300; - private static final long INITIALDELAYMILLIS = 150; - private static final String ALPHA = "alpha"; - - private final SparseArray mAnimators; - private long mAnimationStartMillis; - private int mFirstAnimatedPosition; - private int mLastAnimatedPosition; - private boolean mHasParentAnimationAdapter; - private boolean mShouldAnimate = true; - - private long mInitialDelayMillis = INITIALDELAYMILLIS; - private long mAnimationDelayMillis = DEFAULTANIMATIONDELAYMILLIS; - private long mAnimationDurationMillis = DEFAULTANIMATIONDURATIONMILLIS; - - public AnimationAdapter(final BaseAdapter baseAdapter) { - super(baseAdapter); - mAnimators = new SparseArray(); - - mAnimationStartMillis = -1; - mFirstAnimatedPosition = -1; - mLastAnimatedPosition = -1; - - if (baseAdapter instanceof AnimationAdapter) { - ((AnimationAdapter) baseAdapter).setHasParentAnimationAdapter(true); - } - } - - /** - * Call this method to reset animation status on all views. The next time - * {@link #notifyDataSetChanged()} is called on the base adapter, all views will - * animate again. Will also call {@link #setShouldAnimate(boolean)} with a value of true. - */ - public void reset() { - mAnimators.clear(); - mFirstAnimatedPosition = -1; - mLastAnimatedPosition = -1; - mAnimationStartMillis = -1; - mShouldAnimate = true; - - if (getDecoratedBaseAdapter() instanceof AnimationAdapter) { - ((AnimationAdapter) getDecoratedBaseAdapter()).reset(); - } - } - - /** - * Set whether to animate the {@link View}s or not. - * @param shouldAnimate true if the Views should be animated. - */ - public void setShouldAnimate(final boolean shouldAnimate) { - mShouldAnimate = shouldAnimate; - } - - /** - * Set the starting position for which items should animate. Given position will animate as well. - * Will also call setShouldAnimate(true). - * @param position the position. - */ - @SuppressWarnings("UnusedDeclaration") - public void setShouldAnimateFromPosition(final int position) { - mShouldAnimate = true; - mFirstAnimatedPosition = position - 1; - mLastAnimatedPosition = position - 1; - } - - /** - * Set the starting position for which items should animate as the first position which isn't currently visible on screen. - * This call is also valid when the {@link View}s haven't been drawn yet. - * Will also call setShouldAnimate(true). - */ - @SuppressWarnings("UnusedDeclaration") - public void setShouldAnimateNotVisible() { - if (getAbsListView() == null) { - throw new IllegalStateException("Call setListView() on this AnimationAdapter before setShouldAnimateNotVisible()!"); - } - - mShouldAnimate = true; - mFirstAnimatedPosition = getAbsListView().getLastVisiblePosition(); - mLastAnimatedPosition = getAbsListView().getLastVisiblePosition(); - } - - @Override - public final View getView(final int position, final View convertView, final ViewGroup parent) { - if (!mHasParentAnimationAdapter) { - if (getAbsListView() == null) { - throw new IllegalStateException("Call setListView() on this AnimationAdapter before setAdapter()!"); - } - - if (convertView != null) { - cancelExistingAnimation(convertView); - } - } - - View itemView = super.getView(position, convertView, parent); - - if (!mHasParentAnimationAdapter) { - animateViewIfNecessary(position, itemView, parent); - } - return itemView; - } - - private void cancelExistingAnimation(final View convertView) { - int hashCode = convertView.hashCode(); - Animator animator = mAnimators.get(hashCode); - if (animator != null) { - animator.end(); - mAnimators.remove(hashCode); - } - } - - private void animateViewIfNecessary(final int position, final View view, final ViewGroup parent) { - boolean isMeasuringGridViewItem = getAbsListView() instanceof GridView && parent.getHeight() == 0; - - if (position > mLastAnimatedPosition && mShouldAnimate && !isMeasuringGridViewItem) { - if (mFirstAnimatedPosition == -1) { - mFirstAnimatedPosition = position; - } - - animateView(parent, view); - mLastAnimatedPosition = position; - } - } - - private void animateView(final ViewGroup parent, final View view) { - if (mAnimationStartMillis == -1) { - mAnimationStartMillis = System.currentTimeMillis(); - } - - ViewHelper.setAlpha(view, 0); - - Animator[] childAnimators; - if (mDecoratedBaseAdapter instanceof AnimationAdapter) { - childAnimators = ((AnimationAdapter) mDecoratedBaseAdapter).getAnimators(parent, view); - } else { - childAnimators = new Animator[0]; - } - Animator[] animators = getAnimators(parent, view); - Animator alphaAnimator = ObjectAnimator.ofFloat(view, ALPHA, 0, 1); - - AnimatorSet set = new AnimatorSet(); - set.playTogether(concatAnimators(childAnimators, animators, alphaAnimator)); - set.setStartDelay(calculateAnimationDelay()); - set.setDuration(getAnimationDurationMillis()); - set.start(); - - mAnimators.put(view.hashCode(), set); - } - - private Animator[] concatAnimators(final Animator[] childAnimators, final Animator[] animators, final Animator alphaAnimator) { - Animator[] allAnimators = new Animator[childAnimators.length + animators.length + 1]; - int i; - - for (i = 0; i < animators.length; ++i) { - allAnimators[i] = animators[i]; - } - - for (Animator childAnimator : childAnimators) { - allAnimators[i] = childAnimator; - ++i; - } - - allAnimators[allAnimators.length - 1] = alphaAnimator; - return allAnimators; - } - - @SuppressLint("NewApi") - private long calculateAnimationDelay() { - long delay; - - int lastVisiblePosition = getAbsListView().getLastVisiblePosition(); - int firstVisiblePosition = getAbsListView().getFirstVisiblePosition(); - - int numberOfItemsOnScreen = lastVisiblePosition - firstVisiblePosition; - int numberOfAnimatedItems = mLastAnimatedPosition - mFirstAnimatedPosition; - - if (numberOfItemsOnScreen + 1 < numberOfAnimatedItems) { - delay = getAnimationDelayMillis(); - - if (getAbsListView() instanceof GridView && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - delay += getAnimationDelayMillis() * ((mLastAnimatedPosition + 1) % ((GridView) getAbsListView()).getNumColumns()); - } - } else { - long delaySinceStart = (mLastAnimatedPosition - mFirstAnimatedPosition + 1) * getAnimationDelayMillis(); - delay = mAnimationStartMillis + getInitialDelayMillis() + delaySinceStart - System.currentTimeMillis(); - } - return Math.max(0, delay); - } - - /** - * Set whether this AnimationAdapter is encapsulated by another - * AnimationAdapter. When this is set to true, this AnimationAdapter does - * not apply any animations to the views. Should not be set explicitly, the - * AnimationAdapter class manages this by itself. - */ - public void setHasParentAnimationAdapter(final boolean hasParentAnimationAdapter) { - mHasParentAnimationAdapter = hasParentAnimationAdapter; - } - - /** - * Get the delay in milliseconds before the first animation should start. Defaults to {@value #INITIALDELAYMILLIS}. - */ - protected long getInitialDelayMillis() { - return mInitialDelayMillis; - } - - /** - * Set the delay in milliseconds before the first animation should start. Defaults to {@value #INITIALDELAYMILLIS}. - * @param delayMillis the time in milliseconds. - */ - public void setInitialDelayMillis(final long delayMillis) { - mInitialDelayMillis = delayMillis; - } - - /** - * Get the delay in milliseconds before an animation of a view should start. Defaults to {@value #DEFAULTANIMATIONDELAYMILLIS}. - */ - protected long getAnimationDelayMillis() { - return mAnimationDelayMillis; - } - - /** - * Set the delay in milliseconds before an animation of a view should start. Defaults to {@value #DEFAULTANIMATIONDELAYMILLIS}. - * @param delayMillis the time in milliseconds. - */ - @SuppressWarnings("UnusedDeclaration") - public void setAnimationDelayMillis(final long delayMillis) { - mAnimationDelayMillis = delayMillis; - } - - /** - * Get the duration of the animation in milliseconds. Defaults to {@value #DEFAULTANIMATIONDURATIONMILLIS}. - */ - protected long getAnimationDurationMillis() { - return mAnimationDurationMillis; - } - - /** - * Set the duration of the animation in milliseconds. Defaults to {@value #DEFAULTANIMATIONDURATIONMILLIS}. - * @param durationMillis the time in milliseconds. - */ - @SuppressWarnings("UnusedDeclaration") - public void setAnimationDurationMillis(final long durationMillis) { - mAnimationDurationMillis = durationMillis; - } - - /** - * Get the Animators to apply to the views. In addition to the returned - * Animators, an alpha transition will be applied to the view. - * - * @param parent - * The parent of the view - * @param view - * The view that will be animated, as retrieved by getView() - */ - public abstract Animator[] getAnimators(ViewGroup parent, View view); -} diff --git a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/swinginadapters/ResourceAnimationAdapter.java b/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/swinginadapters/ResourceAnimationAdapter.java deleted file mode 100644 index 17d3903..0000000 --- a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/swinginadapters/ResourceAnimationAdapter.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2013 Niek Haarman - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.nhaarman.listviewanimations.swinginadapters; - -import android.content.Context; -import android.view.View; -import android.view.ViewGroup; -import android.widget.BaseAdapter; - -import com.nineoldandroids.animation.Animator; -import com.nineoldandroids.animation.AnimatorInflater; - -/** - * An implementation of AnimationAdapter which bases the animations on - * resources. - */ -public abstract class ResourceAnimationAdapter extends AnimationAdapter { - - private final Context mContext; - - @SuppressWarnings("UnusedDeclaration") - public ResourceAnimationAdapter(final BaseAdapter baseAdapter, final Context context) { - super(baseAdapter); - mContext = context; - } - - @Override - public Animator[] getAnimators(final ViewGroup parent, final View view) { - return new Animator[]{AnimatorInflater.loadAnimator(mContext, getAnimationResourceId())}; - } - - /** - * Get the resource id of the animation to apply to the views. - */ - protected abstract int getAnimationResourceId(); - -} diff --git a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/swinginadapters/SingleAnimationAdapter.java b/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/swinginadapters/SingleAnimationAdapter.java deleted file mode 100644 index 7d744d4..0000000 --- a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/swinginadapters/SingleAnimationAdapter.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2013 Niek Haarman - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.nhaarman.listviewanimations.swinginadapters; - -import android.view.View; -import android.view.ViewGroup; -import android.widget.BaseAdapter; - -import com.nineoldandroids.animation.Animator; - -/** - * An implementation of AnimationAdapter which applies a single Animator to - * views. - */ -public abstract class SingleAnimationAdapter extends AnimationAdapter { - - public SingleAnimationAdapter(final BaseAdapter baseAdapter) { - super(baseAdapter); - } - - @Override - public Animator[] getAnimators(final ViewGroup parent, final View view) { - Animator animator = getAnimator(parent, view); - return new Animator[]{animator}; - } - - /** - * Get the {@link Animator} to apply to the {@link View}. - * - * @param parent - * the {@link ViewGroup} which is the parent of the View. - * @param view - * the View that will be animated, as retrieved by - * {@link #getView(int, View, ViewGroup)}. - */ - protected abstract Animator getAnimator(ViewGroup parent, View view); - -} diff --git a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/swinginadapters/prepared/AlphaInAnimationAdapter.java b/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/swinginadapters/prepared/AlphaInAnimationAdapter.java deleted file mode 100644 index dac9feb..0000000 --- a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/swinginadapters/prepared/AlphaInAnimationAdapter.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.nhaarman.listviewanimations.swinginadapters.prepared; - -import android.view.View; -import android.view.ViewGroup; -import android.widget.BaseAdapter; - -import com.nhaarman.listviewanimations.swinginadapters.AnimationAdapter; -import com.nineoldandroids.animation.Animator; - -public class AlphaInAnimationAdapter extends AnimationAdapter { - - public AlphaInAnimationAdapter(final BaseAdapter baseAdapter) { - super(baseAdapter); - } - - @Override - protected long getAnimationDelayMillis() { - return DEFAULTANIMATIONDELAYMILLIS; - } - - @Override - protected long getAnimationDurationMillis() { - return DEFAULTANIMATIONDURATIONMILLIS; - } - - @Override - public Animator[] getAnimators(final ViewGroup parent, final View view) { - return new Animator[0]; - } -} diff --git a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/swinginadapters/prepared/ScaleInAnimationAdapter.java b/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/swinginadapters/prepared/ScaleInAnimationAdapter.java deleted file mode 100644 index 90f075a..0000000 --- a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/swinginadapters/prepared/ScaleInAnimationAdapter.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2013 Niek Haarman - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.nhaarman.listviewanimations.swinginadapters.prepared; - -import android.view.View; -import android.view.ViewGroup; -import android.widget.BaseAdapter; - -import com.nhaarman.listviewanimations.swinginadapters.AnimationAdapter; -import com.nineoldandroids.animation.Animator; -import com.nineoldandroids.animation.ObjectAnimator; - -public class ScaleInAnimationAdapter extends AnimationAdapter { - - private static final float DEFAULTSCALEFROM = 0.8f; - private static final String SCALE_X = "scaleX"; - private static final String SCALE_Y = "scaleY"; - - private final float mScaleFrom; - private final long mAnimationDelayMillis; - private final long mAnimationDurationMillis; - - public ScaleInAnimationAdapter(final BaseAdapter baseAdapter) { - this(baseAdapter, DEFAULTSCALEFROM); - } - - public ScaleInAnimationAdapter(final BaseAdapter baseAdapter, final float scaleFrom) { - this(baseAdapter, scaleFrom, DEFAULTANIMATIONDELAYMILLIS, DEFAULTANIMATIONDURATIONMILLIS); - } - - public ScaleInAnimationAdapter(final BaseAdapter baseAdapter, final float scaleFrom, final long animationDelayMillis, final long animationDurationMillis) { - super(baseAdapter); - mScaleFrom = scaleFrom; - mAnimationDelayMillis = animationDelayMillis; - mAnimationDurationMillis = animationDurationMillis; - } - - @Override - protected long getAnimationDelayMillis() { - return mAnimationDelayMillis; - } - - @Override - protected long getAnimationDurationMillis() { - return mAnimationDurationMillis; - } - - @Override - public Animator[] getAnimators(final ViewGroup parent, final View view) { - ObjectAnimator scaleX = ObjectAnimator.ofFloat(view, SCALE_X, mScaleFrom, 1f); - ObjectAnimator scaleY = ObjectAnimator.ofFloat(view, SCALE_Y, mScaleFrom, 1f); - return new ObjectAnimator[]{scaleX, scaleY}; - } -} diff --git a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/swinginadapters/prepared/SwingBottomInAnimationAdapter.java b/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/swinginadapters/prepared/SwingBottomInAnimationAdapter.java deleted file mode 100644 index 8aeecc2..0000000 --- a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/swinginadapters/prepared/SwingBottomInAnimationAdapter.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2013 Niek Haarman - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.nhaarman.listviewanimations.swinginadapters.prepared; - -import android.view.View; -import android.view.ViewGroup; -import android.widget.BaseAdapter; - -import com.nhaarman.listviewanimations.swinginadapters.SingleAnimationAdapter; -import com.nineoldandroids.animation.Animator; -import com.nineoldandroids.animation.ObjectAnimator; - -/** - * An implementation of the AnimationAdapter class which applies a - * swing-in-from-bottom-animation to views. - */ -public class SwingBottomInAnimationAdapter extends SingleAnimationAdapter { - - private static final String TRANSLATION_Y = "translationY"; - private final long mAnimationDelayMillis; - private final long mAnimationDurationMillis; - - public SwingBottomInAnimationAdapter(final BaseAdapter baseAdapter) { - this(baseAdapter, DEFAULTANIMATIONDELAYMILLIS, DEFAULTANIMATIONDURATIONMILLIS); - } - - public SwingBottomInAnimationAdapter(final BaseAdapter baseAdapter, final long animationDelayMillis) { - this(baseAdapter, animationDelayMillis, DEFAULTANIMATIONDURATIONMILLIS); - } - - public SwingBottomInAnimationAdapter(final BaseAdapter baseAdapter, final long animationDelayMillis, final long animationDurationMillis) { - super(baseAdapter); - mAnimationDelayMillis = animationDelayMillis; - mAnimationDurationMillis = animationDurationMillis; - } - - @Override - protected long getAnimationDelayMillis() { - return mAnimationDelayMillis; - } - - @Override - protected long getAnimationDurationMillis() { - return mAnimationDurationMillis; - } - - @Override - protected Animator getAnimator(final ViewGroup parent, final View view) { - // TODO magic number - return ObjectAnimator.ofFloat(view, TRANSLATION_Y, 500, 0); - } - -} diff --git a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/swinginadapters/prepared/SwingLeftInAnimationAdapter.java b/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/swinginadapters/prepared/SwingLeftInAnimationAdapter.java deleted file mode 100644 index cc62944..0000000 --- a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/swinginadapters/prepared/SwingLeftInAnimationAdapter.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2013 Niek Haarman - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.nhaarman.listviewanimations.swinginadapters.prepared; - -import android.view.View; -import android.view.ViewGroup; -import android.widget.BaseAdapter; - -import com.nhaarman.listviewanimations.swinginadapters.SingleAnimationAdapter; -import com.nineoldandroids.animation.Animator; -import com.nineoldandroids.animation.ObjectAnimator; - -/** - * An implementation of the AnimationAdapter class which applies a - * swing-in-from-the-left-animation to views. - */ -@SuppressWarnings("UnusedDeclaration") -public class SwingLeftInAnimationAdapter extends SingleAnimationAdapter { - - private static final String TRANSLATION_X = "translationX"; - private final long mAnimationDelayMillis; - private final long mAnimationDurationMillis; - - public SwingLeftInAnimationAdapter(final BaseAdapter baseAdapter) { - this(baseAdapter, DEFAULTANIMATIONDELAYMILLIS, DEFAULTANIMATIONDURATIONMILLIS); - } - - public SwingLeftInAnimationAdapter(final BaseAdapter baseAdapter, final long animationDelayMillis) { - this(baseAdapter, animationDelayMillis, DEFAULTANIMATIONDURATIONMILLIS); - } - - public SwingLeftInAnimationAdapter(final BaseAdapter baseAdapter, final long animationDelayMillis, final long animationDurationMillis) { - super(baseAdapter); - mAnimationDelayMillis = animationDelayMillis; - mAnimationDurationMillis = animationDurationMillis; - } - - @Override - protected long getAnimationDelayMillis() { - return mAnimationDelayMillis; - } - - @Override - protected long getAnimationDurationMillis() { - return mAnimationDurationMillis; - } - - @Override - protected Animator getAnimator(final ViewGroup parent, final View view) { - return ObjectAnimator.ofFloat(view, TRANSLATION_X, 0 - parent.getWidth(), 0); - } -} diff --git a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/swinginadapters/prepared/SwingRightInAnimationAdapter.java b/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/swinginadapters/prepared/SwingRightInAnimationAdapter.java deleted file mode 100644 index 1e3d00e..0000000 --- a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/swinginadapters/prepared/SwingRightInAnimationAdapter.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2013 Niek Haarman - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.nhaarman.listviewanimations.swinginadapters.prepared; - -import android.view.View; -import android.view.ViewGroup; -import android.widget.BaseAdapter; - -import com.nhaarman.listviewanimations.swinginadapters.SingleAnimationAdapter; -import com.nineoldandroids.animation.Animator; -import com.nineoldandroids.animation.ObjectAnimator; - -/** - * An implementation of the AnimationAdapter class which applies a - * swing-in-from-the-right-animation to views. - */ -public class SwingRightInAnimationAdapter extends SingleAnimationAdapter { - - private static final String TRANSLATION_X = "translationX"; - private final long mAnimationDelayMillis; - private final long mAnimationDurationMillis; - - public SwingRightInAnimationAdapter(final BaseAdapter baseAdapter) { - this(baseAdapter, DEFAULTANIMATIONDELAYMILLIS, DEFAULTANIMATIONDURATIONMILLIS); - } - - public SwingRightInAnimationAdapter(final BaseAdapter baseAdapter, final long animationDelayMillis) { - this(baseAdapter, animationDelayMillis, DEFAULTANIMATIONDURATIONMILLIS); - } - - public SwingRightInAnimationAdapter(final BaseAdapter baseAdapter, final long animationDelayMillis, final long animationDurationMillis) { - super(baseAdapter); - mAnimationDelayMillis = animationDelayMillis; - mAnimationDurationMillis = animationDurationMillis; - } - - @Override - protected long getAnimationDelayMillis() { - return mAnimationDelayMillis; - } - - @Override - protected long getAnimationDurationMillis() { - return mAnimationDurationMillis; - } - - @Override - protected Animator getAnimator(final ViewGroup parent, final View view) { - return ObjectAnimator.ofFloat(view, TRANSLATION_X, parent.getWidth(), 0); - } -} diff --git a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/util/AdapterViewUtil.java b/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/util/AdapterViewUtil.java deleted file mode 100644 index 5b373e6..0000000 --- a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/util/AdapterViewUtil.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2013 Niek Haarman - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.nhaarman.listviewanimations.util; - -import android.view.View; -import android.widget.AdapterView; -import android.widget.ListView; - -public class AdapterViewUtil { - - /** - * Get the position within the adapter's dataset for the view, where view is an adapter item or a descendant of an adapter item. - * Unlike {@link AdapterView#getPositionForView(android.view.View)}, returned position will reflect the position of the item given view is representing, - * by subtracting the header views count. - * @param adapterView the AdapterView containing the view. - * @param view an adapter item or a descendant of an adapter item. This must be visible in given AdapterView at the time of the call. - * @return the position of the item in the AdapterView represented by given view, or {@link AdapterView#INVALID_POSITION} if the view does not - * correspond to a list item (or it is not visible). - */ - public static int getPositionForView(final AdapterView adapterView, final View view) { - int position = adapterView.getPositionForView(view); - - if (adapterView instanceof ListView) { - position -= ((ListView) adapterView).getHeaderViewsCount(); - } - - return position; - } -} diff --git a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/widget/DynamicListView.java b/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/widget/DynamicListView.java deleted file mode 100644 index b45c8f7..0000000 --- a/listview-animations-demo/ListviewAnimationLib/src/com/nhaarman/listviewanimations/widget/DynamicListView.java +++ /dev/null @@ -1,796 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * Copyright 2013 Niek Haarman - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.nhaarman.listviewanimations.widget; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Rect; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.util.AttributeSet; -import android.util.DisplayMetrics; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewConfiguration; -import android.view.ViewGroup; -import android.view.ViewTreeObserver; -import android.widget.AbsListView; -import android.widget.AdapterView; -import android.widget.BaseAdapter; -import android.widget.HeaderViewListAdapter; -import android.widget.ListAdapter; -import android.widget.ListView; - -import com.nhaarman.listviewanimations.itemmanipulation.swipedismiss.SwipeOnTouchListener; -import com.nineoldandroids.animation.Animator; -import com.nineoldandroids.animation.AnimatorListenerAdapter; -import com.nineoldandroids.animation.ObjectAnimator; -import com.nineoldandroids.animation.TypeEvaluator; -import com.nineoldandroids.animation.ValueAnimator; -import com.nineoldandroids.view.ViewHelper; - -/** - * The DynamicListView is an extension of {@link ListView} that supports cell dragging - * and swapping. - *

- * Make sure your adapter has stable ids, and override {@link ListAdapter#hasStableIds()} to return true.
- *

- * This layout is in charge of positioning the hover cell in the correct location - * on the screen in response to user touch events. It uses the position of the - * hover cell to determine when two cells should be swapped. If two cells should - * be swapped, all the corresponding data set and layout changes are handled here. - *

- * If no cell is selected, all the touch events are passed down to the ListView - * and behave normally. If one of the items in the ListView experiences a - * long press event, the contents of its current visible state are captured as - * a bitmap and its visibility is set to INVISIBLE. A hover cell is then created and - * added to this layout as an overlaying BitmapDrawable above the ListView. Once the - * hover cell is translated some distance to signify an item swap, a data set change - * accompanied by animation takes place. When the user releases the hover cell, - * it animates into its corresponding position in the ListView. - *

- * When the hover cell is either above or below the bounds of the ListView, this - * ListView also scrolls on its own so as to reveal additional content. - *

- * See http://youtu.be/_BZIvjMgH-Q - */ -public class DynamicListView extends ListView { - - private int mOriginalTranscriptMode; - - public interface OnHoverCellListener { - public Drawable onHoverCellCreated(Drawable hoverCellDrawable); - } - - /** - * Implement this interface to be notified of ordering changes. Call {@link #setOnItemMovedListener(com.nhaarman.listviewanimations.widget.DynamicListView.OnItemMovedListener)}. - */ - public interface OnItemMovedListener { - /** - * Called after an item is dropped and moved. - * - * @param newPosition the new position of the item. - */ - public void onItemMoved(int newPosition); - } - - private final int SMOOTH_SCROLL_AMOUNT_AT_EDGE = 15; - private final int MOVE_DURATION = 150; - - private int mLastEventY = -1, mLastEventX = -1; - - private int mDownY = -1; - private int mDownX = -1; - - private int mTotalOffset = 0; - - private boolean mCellIsMobile = false; - private boolean mIsMobileScrolling = false; - private int mSmoothScrollAmountAtEdge = 0; - - private final int INVALID_ID = -1; - private long mAboveItemId = INVALID_ID; - private long mMobileItemId = INVALID_ID; - private long mBelowItemId = INVALID_ID; - - private Drawable mHoverCell; - private Rect mHoverCellCurrentBounds; - private Rect mHoverCellOriginalBounds; - - private final int INVALID_POINTER_ID = -1; - private int mActivePointerId = INVALID_POINTER_ID; - - private boolean mIsWaitingForScrollFinish = false; - private int mScrollState = OnScrollListener.SCROLL_STATE_IDLE; - - private OnTouchListener mOnTouchListener; - private boolean mIsParentHorizontalScrollContainer; - private int mResIdOfDynamicTouchChild; - private boolean mDynamicTouchChildTouched; - private int mSlop; - - private boolean mSkipCallingOnTouchListener; - - private OnHoverCellListener mOnHoverCellListener; - - private OnItemMovedListener mOnItemMovedListener; - private int mLastMovedToIndex; - - public DynamicListView(Context context) { - super(context); - init(context); - } - - public DynamicListView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - init(context); - } - - public DynamicListView(Context context, AttributeSet attrs) { - super(context, attrs); - init(context); - } - - public void init(Context context) { - setOnItemLongClickListener(mOnItemLongClickListener); - setOnScrollListener(mScrollListener); - DisplayMetrics metrics = context.getResources().getDisplayMetrics(); - mSmoothScrollAmountAtEdge = (int) (SMOOTH_SCROLL_AMOUNT_AT_EDGE / metrics.density); - ViewConfiguration vc = ViewConfiguration.get(getContext()); - mSlop = vc.getScaledTouchSlop(); - } - - public void setAdapter(BaseAdapter adapter) { - super.setAdapter(adapter); - } - - @Override - @Deprecated - /** - * @deprecated use #setAdapter(BaseAdapter) instead. - */ - public void setAdapter(ListAdapter adapter) { - if (!(adapter instanceof BaseAdapter)) { - throw new IllegalArgumentException("DynamicListView needs a BaseAdapter!"); - } - super.setAdapter(adapter); - } - - /** - * Listens for long clicks on any items in the listview. When a cell has - * been selected, the hover cell is created and set up. - */ - private OnItemLongClickListener mOnItemLongClickListener = new OnItemLongClickListener() { - public boolean onItemLongClick(AdapterView arg0, View arg1, int pos, long id) { - if (mResIdOfDynamicTouchChild == 0) { - mDynamicTouchChildTouched = true; - makeCellMobile(); - return true; - } - return false; - } - }; - - private void makeCellMobile() { - int position = pointToPosition(mDownX, mDownY); - int itemNum = position - getFirstVisiblePosition(); - View selectedView = getChildAt(itemNum); - if (selectedView == null || position < getHeaderViewsCount() || position >= getAdapter().getCount() - getHeaderViewsCount()) { - return; - } - - mOriginalTranscriptMode = getTranscriptMode(); - setTranscriptMode(TRANSCRIPT_MODE_NORMAL); - - - mTotalOffset = 0; - - mMobileItemId = getAdapter().getItemId(position); - mHoverCell = getAndAddHoverView(selectedView); - if (mOnHoverCellListener != null) { - mHoverCell = mOnHoverCellListener.onHoverCellCreated(mHoverCell); - } - selectedView.setVisibility(INVISIBLE); - - mCellIsMobile = true; - getParent().requestDisallowInterceptTouchEvent(true); - - updateNeighborViewsForId(mMobileItemId); - } - - /** - * Creates the hover cell with the appropriate bitmap and of appropriate - * size. The hover cell's BitmapDrawable is drawn on top of the bitmap every - * single time an invalidate call is made. - */ - private BitmapDrawable getAndAddHoverView(View v) { - int w = v.getWidth(); - int h = v.getHeight(); - int top = v.getTop(); - int left = v.getLeft(); - - Bitmap b = getBitmapFromView(v); - - BitmapDrawable drawable = new BitmapDrawable(getResources(), b); - - mHoverCellOriginalBounds = new Rect(left, top, left + w, top + h); - mHoverCellCurrentBounds = new Rect(mHoverCellOriginalBounds); - - drawable.setBounds(mHoverCellCurrentBounds); - - return drawable; - } - - /** - * Returns a bitmap showing a screenshot of the view passed in. - */ - private Bitmap getBitmapFromView(View v) { - Bitmap bitmap = Bitmap.createBitmap(v.getWidth(), v.getHeight(), Bitmap.Config.ARGB_8888); - Canvas canvas = new Canvas(bitmap); - v.draw(canvas); - return bitmap; - } - - /** - * Stores a reference to the views above and below the item currently - * corresponding to the hover cell. It is important to note that if this - * item is either at the top or bottom of the list, mAboveItemId or mBelowItemId - * may be invalid. - */ - private void updateNeighborViewsForId(long itemId) { - int position = getPositionForId(itemId); - ListAdapter adapter = getAdapter(); - if (!adapter.hasStableIds()) { - throw new IllegalStateException("Adapter doesn't have stable ids! Make sure your adapter has stable ids, and override hasStableIds() to return true."); - } - - mAboveItemId = position - 1 >= 0 ? adapter.getItemId(position - 1) : INVALID_ROW_ID; - mBelowItemId = position + 1 < adapter.getCount() ? adapter.getItemId(position + 1) : INVALID_ROW_ID; - } - - /** - * Retrieves the view in the list corresponding to itemId - */ - private View getViewForId(long itemId) { - int firstVisiblePosition = getFirstVisiblePosition(); - ListAdapter adapter = getAdapter(); - if (!adapter.hasStableIds()) { - throw new IllegalStateException("Adapter doesn't have stable ids! Make sure your adapter has stable ids, and override hasStableIds() to return true."); - } - - for (int i = 0; i < getChildCount(); i++) { - View v = getChildAt(i); - int position = firstVisiblePosition + i; - long id = adapter.getItemId(position); - if (id == itemId) { - return v; - } - } - return null; - } - - /** - * Retrieves the position in the list corresponding to itemId - */ - private int getPositionForId(long itemId) { - View v = getViewForId(itemId); - if (v == null) { - return -1; - } else { - return getPositionForView(v); - } - } - - /** - * dispatchDraw gets invoked when all the child views are about to be drawn. - * By overriding this method, the hover cell (BitmapDrawable) can be drawn - * over the listview's items whenever the listview is redrawn. - */ - @Override - protected void dispatchDraw(Canvas canvas) { - super.dispatchDraw(canvas); - if (mHoverCell != null) { - mHoverCell.draw(canvas); - } - } - - @Override - public void setOnTouchListener(OnTouchListener l) { - mOnTouchListener = l; - } - - public void setOnHoverCellListener(OnHoverCellListener onHoverCellListener) { - mOnHoverCellListener = onHoverCellListener; - } - - private Rect getChildViewRect(View parentView, View childView) { - final Rect childRect = new Rect(childView.getLeft(), childView.getTop(), childView.getRight(), childView.getBottom()); - if (parentView == childView) { - return childRect; - } - - ViewGroup parent; - while ((parent = (ViewGroup) childView.getParent()) != parentView) { - childRect.offset(parent.getLeft(), parent.getTop()); - childView = parent; - } - - return childRect; - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - if (mSkipCallingOnTouchListener) { - return super.onTouchEvent(event); - } - - if (mOnTouchListener instanceof SwipeOnTouchListener) { - if (((SwipeOnTouchListener) mOnTouchListener).isSwiping()) { - mSkipCallingOnTouchListener = true; - boolean retVal = mOnTouchListener.onTouch(this, event); - mSkipCallingOnTouchListener = false; - return retVal || super.onTouchEvent(event); - } - } - - switch (event.getAction() & MotionEvent.ACTION_MASK) { - case MotionEvent.ACTION_DOWN: - mDownX = (int) event.getX(); - mDownY = (int) event.getY(); - mActivePointerId = event.getPointerId(0); - - mDynamicTouchChildTouched = false; - if (mResIdOfDynamicTouchChild != 0) { - mIsParentHorizontalScrollContainer = false; - - int position = pointToPosition(mDownX, mDownY); - int childNum = (position != INVALID_POSITION) ? position - getFirstVisiblePosition() : -1; - View itemView = (childNum >= 0) ? getChildAt(childNum) : null; - View childView = (itemView != null) ? itemView.findViewById(mResIdOfDynamicTouchChild) : null; - if (childView != null) { - final Rect childRect = getChildViewRect(this, childView); - if (childRect.contains(mDownX, mDownY)) { - mDynamicTouchChildTouched = true; - getParent().requestDisallowInterceptTouchEvent(true); - } - } - } - - if (mIsParentHorizontalScrollContainer) { - // Do it now and don't wait until the user moves more than the - // slop factor. - getParent().requestDisallowInterceptTouchEvent(true); - } - break; - case MotionEvent.ACTION_MOVE: - if (mActivePointerId == INVALID_POINTER_ID) { - break; - } - - int pointerIndex = event.findPointerIndex(mActivePointerId); - - mLastEventY = (int) event.getY(pointerIndex); - mLastEventX = (int) event.getX(pointerIndex); - int deltaY = mLastEventY - mDownY; - int deltaX = mLastEventX - mDownX; - - if (!mCellIsMobile && mDynamicTouchChildTouched) { - if (Math.abs(deltaY) > mSlop && Math.abs(deltaY) > Math.abs(deltaX)) { - makeCellMobile(); - - // Cancel ListView's touch (un-highlighting the item) - MotionEvent cancelEvent = MotionEvent.obtain(event); - cancelEvent.setAction(MotionEvent.ACTION_CANCEL | (event.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT)); - super.onTouchEvent(cancelEvent); - cancelEvent.recycle(); - } - } - - if (mCellIsMobile) { - mHoverCellCurrentBounds.offsetTo(mHoverCellOriginalBounds.left, mHoverCellOriginalBounds.top + deltaY + mTotalOffset); - mHoverCell.setBounds(mHoverCellCurrentBounds); - invalidate(); - - handleCellSwitch(); - - mIsMobileScrolling = false; - handleMobileCellScroll(); - } - break; - case MotionEvent.ACTION_UP: - mDynamicTouchChildTouched = false; - touchEventsEnded(); - break; - case MotionEvent.ACTION_CANCEL: - mDynamicTouchChildTouched = false; - touchEventsCancelled(); - break; - case MotionEvent.ACTION_POINTER_UP: - /* - * If a multitouch event took place and the original touch dictating - * the movement of the hover cell has ended, then the dragging event - * ends and the hover cell is animated to its corresponding position - * in the listview. - */ - pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; - final int pointerId = event.getPointerId(pointerIndex); - if (pointerId == mActivePointerId) { - mDynamicTouchChildTouched = false; - touchEventsEnded(); - } - break; - default: - break; - } - - if (mCellIsMobile) { - return false; - } else if (mOnTouchListener != null) { - mSkipCallingOnTouchListener = true; - boolean retVal = mOnTouchListener.onTouch(this, event); - mSkipCallingOnTouchListener = false; - if (retVal) { - return true; - } - } - return super.onTouchEvent(event); - } - - /** - * This method determines whether the hover cell has been shifted far enough - * to invoke a cell swap. If so, then the respective cell swap candidate is - * determined and the data set is changed. Upon posting a notification of the - * data set change, a layout is invoked to place the cells in the right place. - * Using a ViewTreeObserver and a corresponding OnPreDrawListener, we can - * offset the cell being swapped to where it previously was and then animate it to - * its new position. - */ - private void handleCellSwitch() { - final int deltaY = mLastEventY - mDownY; - int deltaYTotal = mHoverCellOriginalBounds.top + mTotalOffset + deltaY; - - View belowView = getViewForId(mBelowItemId); - View mobileView = getViewForId(mMobileItemId); - View aboveView = getViewForId(mAboveItemId); - - boolean isBelow = (belowView != null) && (deltaYTotal > belowView.getTop()); - boolean isAbove = (aboveView != null) && (deltaYTotal < aboveView.getTop()); - - if (isBelow || isAbove) { - - final long switchItemId = isBelow ? mBelowItemId : mAboveItemId; - View switchView = isBelow ? belowView : aboveView; - final int originalItem = getPositionForView(mobileView); - - if (switchView == null) { - updateNeighborViewsForId(mMobileItemId); - return; - } - - if (getPositionForView(switchView) < getHeaderViewsCount()) { - return; - } - swapElements(originalItem, getPositionForView(switchView)); - - BaseAdapter adapter; - if (getAdapter() instanceof HeaderViewListAdapter) { - adapter = (BaseAdapter) ((HeaderViewListAdapter) getAdapter()).getWrappedAdapter(); - } else { - adapter = (BaseAdapter) getAdapter(); - } - adapter.notifyDataSetChanged(); - - mDownY = mLastEventY; - mDownX = mLastEventX; - - final int switchViewStartTop = switchView.getTop(); - - mobileView.setVisibility(View.VISIBLE); - switchView.setVisibility(View.INVISIBLE); - - updateNeighborViewsForId(mMobileItemId); - - final ViewTreeObserver observer = getViewTreeObserver(); - observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { - public boolean onPreDraw() { - observer.removeOnPreDrawListener(this); - - View switchView = getViewForId(switchItemId); - - mTotalOffset += deltaY; - - int switchViewNewTop = switchView.getTop(); - int delta = switchViewStartTop - switchViewNewTop; - - ViewHelper.setTranslationY(switchView, delta); - - ObjectAnimator animator = ObjectAnimator.ofFloat(switchView, "translationY", 0); - animator.setDuration(MOVE_DURATION); - animator.start(); - - return true; - } - }); - } - } - - private void swapElements(int indexOne, int indexTwo) { - mLastMovedToIndex = indexTwo; - ListAdapter adapter = getAdapter(); - - if (adapter instanceof HeaderViewListAdapter) { - adapter = ((HeaderViewListAdapter) adapter).getWrappedAdapter(); - } - - if (adapter instanceof Swappable) { - ((Swappable) adapter).swapItems(indexOne - getHeaderViewsCount(), indexTwo - getHeaderViewsCount()); - } - } - - /** - * Resets all the appropriate fields to a default state while also animating - * the hover cell back to its correct location. - */ - private void touchEventsEnded() { - final View mobileView = getViewForId(mMobileItemId); - if (mCellIsMobile || mIsWaitingForScrollFinish) { - mCellIsMobile = false; - mIsWaitingForScrollFinish = false; - mIsMobileScrolling = false; - mActivePointerId = INVALID_POINTER_ID; - - /* Restore the transcript mode */ - setTranscriptMode(mOriginalTranscriptMode); - - // If the autoscroller has not completed scrolling, we need to wait - // for it to - // finish in order to determine the final location of where the - // hover cell - // should be animated to. - if (mScrollState != OnScrollListener.SCROLL_STATE_IDLE) { - mIsWaitingForScrollFinish = true; - return; - } - - mHoverCellCurrentBounds.offsetTo(mHoverCellOriginalBounds.left, mobileView.getTop()); - - ObjectAnimator hoverViewAnimator = ObjectAnimator.ofObject(mHoverCell, "bounds", sBoundEvaluator, mHoverCellCurrentBounds); - hoverViewAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator valueAnimator) { - invalidate(); - } - }); - hoverViewAnimator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationStart(Animator animation) { - setEnabled(false); - } - - @Override - public void onAnimationEnd(Animator animation) { - mAboveItemId = INVALID_ID; - mMobileItemId = INVALID_ID; - mBelowItemId = INVALID_ID; - mobileView.setVisibility(VISIBLE); - mHoverCell = null; - setEnabled(true); - invalidate(); - if (mOnItemMovedListener != null) { - mOnItemMovedListener.onItemMoved(mLastMovedToIndex - getHeaderViewsCount()); - } - } - }); - hoverViewAnimator.start(); - } else { - touchEventsCancelled(); - } - } - - /** - * Resets all the appropriate fields to a default state. - */ - private void touchEventsCancelled() { - View mobileView = getViewForId(mMobileItemId); - if (mCellIsMobile) { - mAboveItemId = INVALID_ID; - mMobileItemId = INVALID_ID; - mBelowItemId = INVALID_ID; - mobileView.setVisibility(VISIBLE); - mHoverCell = null; - invalidate(); - } - mCellIsMobile = false; - mIsMobileScrolling = false; - mActivePointerId = INVALID_POINTER_ID; - } - - /** - * This TypeEvaluator is used to animate the BitmapDrawable back to its - * final location when the user lifts his finger by modifying the - * BitmapDrawable's bounds. - */ - private final static TypeEvaluator sBoundEvaluator = new TypeEvaluator() { - public Rect evaluate(float fraction, Rect startValue, Rect endValue) { - return new Rect(interpolate(startValue.left, endValue.left, fraction), interpolate(startValue.top, endValue.top, fraction), interpolate(startValue.right, endValue.right, fraction), - interpolate(startValue.bottom, endValue.bottom, fraction)); - } - - public int interpolate(int start, int end, float fraction) { - return (int) (start + fraction * (end - start)); - } - }; - - /** - * Determines whether this listview is in a scrolling state invoked - * by the fact that the hover cell is out of the bounds of the listview; - */ - private void handleMobileCellScroll() { - mIsMobileScrolling = handleMobileCellScroll(mHoverCellCurrentBounds); - } - - /** - * This method is in charge of determining if the hover cell is above - * or below the bounds of the listview. If so, the listview does an appropriate - * upward or downward smooth scroll so as to reveal new items. - */ - private boolean handleMobileCellScroll(Rect r) { - int offset = computeVerticalScrollOffset(); - int height = getHeight(); - int extent = computeVerticalScrollExtent(); - int range = computeVerticalScrollRange(); - int hoverViewTop = r.top; - int hoverHeight = r.height(); - - if (hoverViewTop <= 0 && offset > 0) { - smoothScrollBy(-mSmoothScrollAmountAtEdge, 0); - return true; - } - - if (hoverViewTop + hoverHeight >= height && (offset + extent) < range) { - smoothScrollBy(mSmoothScrollAmountAtEdge, 0); - return true; - } - - return false; - } - - public void setIsParentHorizontalScrollContainer(boolean isParentHorizontalScrollContainer) { - mIsParentHorizontalScrollContainer = (mResIdOfDynamicTouchChild == 0) && isParentHorizontalScrollContainer; - } - - public boolean isParentHorizontalScrollContainer() { - return mIsParentHorizontalScrollContainer; - } - - public void setDynamicTouchChild(int childResId) { - mResIdOfDynamicTouchChild = childResId; - if (childResId != 0) { - setIsParentHorizontalScrollContainer(false); - } - } - - /** - * This scroll listener is added to the listview in order to handle cell swapping - * when the cell is either at the top or bottom edge of the listview. If the hover - * cell is at either edge of the listview, the listview will begin scrolling. As - * scrolling takes place, the listview continuously checks if new cells became visible - * and determines whether they are potential candidates for a cell swap. - */ - private OnScrollListener mScrollListener = new OnScrollListener() { - - private int mPreviousFirstVisibleItem = -1; - private int mPreviousVisibleItemCount = -1; - private int mCurrentFirstVisibleItem; - private int mCurrentVisibleItemCount; - private int mCurrentScrollState; - - public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { - mCurrentFirstVisibleItem = firstVisibleItem; - mCurrentVisibleItemCount = visibleItemCount; - - mPreviousFirstVisibleItem = (mPreviousFirstVisibleItem == -1) ? mCurrentFirstVisibleItem : mPreviousFirstVisibleItem; - mPreviousVisibleItemCount = (mPreviousVisibleItemCount == -1) ? mCurrentVisibleItemCount : mPreviousVisibleItemCount; - - checkAndHandleFirstVisibleCellChange(); - checkAndHandleLastVisibleCellChange(); - - mPreviousFirstVisibleItem = mCurrentFirstVisibleItem; - mPreviousVisibleItemCount = mCurrentVisibleItemCount; - } - - @Override - public void onScrollStateChanged(AbsListView view, int scrollState) { - mCurrentScrollState = scrollState; - mScrollState = scrollState; - isScrollCompleted(); - } - - /** - * This method is in charge of invoking 1 of 2 actions. Firstly, if the listview - * is in a state of scrolling invoked by the hover cell being outside the bounds - * of the listview, then this scrolling event is continued. Secondly, if the hover - * cell has already been released, this invokes the animation for the hover cell - * to return to its correct position after the listview has entered an idle scroll - * state. - */ - private void isScrollCompleted() { - if (mCurrentVisibleItemCount > 0 && mCurrentScrollState == SCROLL_STATE_IDLE) { - if (mCellIsMobile && mIsMobileScrolling) { - handleMobileCellScroll(); - } else if (mIsWaitingForScrollFinish) { - touchEventsEnded(); - } - } - } - - /** - * Determines if the listview scrolled up enough to reveal a new cell at the - * top of the list. If so, then the appropriate parameters are updated. - */ - public void checkAndHandleFirstVisibleCellChange() { - if (mCurrentFirstVisibleItem != mPreviousFirstVisibleItem) { - if (mCellIsMobile && mMobileItemId != INVALID_ID) { - updateNeighborViewsForId(mMobileItemId); - handleCellSwitch(); - } - } - } - - /** - * Determines if the listview scrolled down enough to reveal a new cell at the - * bottom of the list. If so, then the appropriate parameters are updated. - */ - public void checkAndHandleLastVisibleCellChange() { - int currentLastVisibleItem = mCurrentFirstVisibleItem + mCurrentVisibleItemCount; - int previousLastVisibleItem = mPreviousFirstVisibleItem + mPreviousVisibleItemCount; - if (currentLastVisibleItem != previousLastVisibleItem) { - if (mCellIsMobile && mMobileItemId != INVALID_ID) { - updateNeighborViewsForId(mMobileItemId); - handleCellSwitch(); - } - } - } - }; - - /** - * Set the {@link com.nhaarman.listviewanimations.widget.DynamicListView.OnItemMovedListener} to be notified when an item is dropped. - */ - public void setOnItemMovedListener(OnItemMovedListener onItemMovedListener) { - this.mOnItemMovedListener = onItemMovedListener; - } - - /** - * Interface, usually implemented by a {@link com.nhaarman.listviewanimations.BaseAdapterDecorator}, - * that indicates that it can swap the visual position of two list items. - * - * @author Anton Spaans on 9/11/13. - */ - public interface Swappable { - - /** - * Swaps the item on the first adapter position with the item on the second adapter position. - * Be sure to call {@link android.widget.BaseAdapter#notifyDataSetChanged()} if appropriate when implementing this method. - * - * @param positionOne First adapter position. - * @param positionTwo Second adapter position. - */ - public void swapItems(int positionOne, int positionTwo); - } -} \ No newline at end of file diff --git a/listview-animations-demo/ListviewAnimationLib/tests/java/com/nhaarman/listviewanimations/itemmanipulation/tests/InsertQueueTest.java b/listview-animations-demo/ListviewAnimationLib/tests/java/com/nhaarman/listviewanimations/itemmanipulation/tests/InsertQueueTest.java deleted file mode 100644 index 39a1ce9..0000000 --- a/listview-animations-demo/ListviewAnimationLib/tests/java/com/nhaarman/listviewanimations/itemmanipulation/tests/InsertQueueTest.java +++ /dev/null @@ -1,189 +0,0 @@ -package com.nhaarman.listviewanimations.itemmanipulation.tests; - -import android.util.Pair; - -import com.nhaarman.listviewanimations.itemmanipulation.AnimateAdditionAdapter; -import com.nhaarman.listviewanimations.itemmanipulation.InsertQueue; - -import junit.framework.TestCase; - -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.List; - -import static org.hamcrest.Matchers.*; -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; -import static com.nhaarman.listviewanimations.itemmanipulation.tests.matchers.Matchers.*; - -public class InsertQueueTest extends TestCase { - - private InsertQueue mInsertQueue; - - @Mock - private AnimateAdditionAdapter.Insertable mInsertable; - - @Override - protected void setUp() throws Exception { - super.setUp(); - - MockitoAnnotations.initMocks(this); - - mInsertQueue = new InsertQueue(mInsertable); - } - - /** - * Test whether an initial insert actually inserts the item and activates the item. - */ - public void testInitialInsert() { - mInsertQueue.insert(0, 0); - verify(mInsertable, times(1)).add(0, 0); - - assertThat(mInsertQueue.getActiveIndexes(), hasItem(0)); - } - - /** - * Test whether a second insert while the first insert is still active: - * - doesn't insert the item - * - doesn't activate the item - * - queues the item. - */ - public void testSecondInsert() { - mInsertQueue.insert(0, 0); - mInsertQueue.insert(0, 1); - - verify(mInsertable, times(0)).add(0, 1); - - assertThat(mInsertQueue.getActiveIndexes(), not(hasItem(1))); - - assertThat(mInsertQueue.getPendingItemsToInsert(), hasItem(pairWithValues(0, 1))); - } - - /** - * Test whether clearing a single activated item actually clears the item. - */ - public void testClearActive() { - mInsertQueue.insert(0, 0); - mInsertQueue.clearActive(); - - assertThat(mInsertQueue.getActiveIndexes(), empty()); - } - - /** - * Test whether inserting two items and then clearing the active items will - * - activate the second inserted item, - * - insert the second item - */ - public void testDequeueOneElement() { - mInsertQueue.insert(0, 0); - mInsertQueue.insert(0, 1); - mInsertQueue.clearActive(); - - verify(mInsertable).add(0, 1); - - assertThat(mInsertQueue.getActiveIndexes(), contains(0)); - } - - - /** - * Test whether adding two items to the queue remain in correct order - */ - public void testQueueOrder() { - mInsertQueue.insert(0, 0); - mInsertQueue.insert(0, 1); - mInsertQueue.insert(0, 2); - - List> pendingItemsToInsert = mInsertQueue.getPendingItemsToInsert(); - assertThat(pendingItemsToInsert.get(0), is(pairWithValues(0, 1))); - assertThat(pendingItemsToInsert.get(1), is(pairWithValues(0, 2))); - - } - - /** - * Test whether inserting three items and then clearing the active items will activate the second and third inserted item - */ - public void testDequeueTwoElements() { - mInsertQueue.insert(0, 0); - mInsertQueue.insert(0, 1); - mInsertQueue.insert(0, 2); - mInsertQueue.clearActive(); - - ArgumentCaptor indexCaptor = ArgumentCaptor.forClass(Integer.class); - ArgumentCaptor itemCaptor = ArgumentCaptor.forClass(Integer.class); - - verify(mInsertable, atLeast(3)).add(indexCaptor.capture(), itemCaptor.capture()); - - List indexValues = indexCaptor.getAllValues(); - List itemValues = itemCaptor.getAllValues(); - - assertThat(indexValues.get(1), is(0)); - assertThat(itemValues.get(1), is(1)); - assertThat(indexValues.get(2), is(0)); - assertThat(itemValues.get(2), is(2)); - - //noinspection unchecked - assertThat(mInsertQueue.getActiveIndexes(), hasItems(0, 1)); - } - - /** - * Test whether inserting three items, clearing, inserting two items yields the correct order. - */ - public void testDequeueTwoElementsTwice() { - mInsertQueue.insert(0, 0); - mInsertQueue.insert(0, 1); - mInsertQueue.insert(0, 2); - mInsertQueue.clearActive(); - mInsertQueue.insert(0, 3); - mInsertQueue.insert(0, 4); - mInsertQueue.clearActive(); - - ArgumentCaptor indexCaptor = ArgumentCaptor.forClass(Integer.class); - ArgumentCaptor itemCaptor = ArgumentCaptor.forClass(Integer.class); - - verify(mInsertable, atLeast(5)).add(indexCaptor.capture(), itemCaptor.capture()); - - List indexValues = indexCaptor.getAllValues(); - List itemValues = itemCaptor.getAllValues(); - - assertThat(indexValues.get(1), is(0)); - assertThat(itemValues.get(1), is(1)); - assertThat(indexValues.get(2), is(0)); - assertThat(itemValues.get(2), is(2)); - assertThat(indexValues.get(3), is(0)); - assertThat(itemValues.get(3), is(3)); - assertThat(indexValues.get(4), is(0)); - assertThat(itemValues.get(4), is(4)); - } - - /** - * Test whether inserting three items, clearing, inserting two items yields the correct order. - */ - public void testDequeueTwoElementsTwiceRandomOrder() { - mInsertQueue.insert(5, 0); - mInsertQueue.insert(2, 1); - mInsertQueue.insert(3, 2); - mInsertQueue.clearActive(); - mInsertQueue.insert(7, 3); - mInsertQueue.insert(1, 4); - mInsertQueue.clearActive(); - - ArgumentCaptor indexCaptor = ArgumentCaptor.forClass(Integer.class); - ArgumentCaptor itemCaptor = ArgumentCaptor.forClass(Integer.class); - - verify(mInsertable, atLeast(5)).add(indexCaptor.capture(), itemCaptor.capture()); - - List indexValues = indexCaptor.getAllValues(); - List itemValues = itemCaptor.getAllValues(); - - assertThat(indexValues.get(1), is(2)); - assertThat(itemValues.get(1), is(1)); - assertThat(indexValues.get(2), is(3)); - assertThat(itemValues.get(2), is(2)); - assertThat(indexValues.get(3), is(7)); - assertThat(itemValues.get(3), is(3)); - assertThat(indexValues.get(4), is(1)); - assertThat(itemValues.get(4), is(4)); - } -} diff --git a/listview-animations-demo/ListviewAnimationLib/tests/java/com/nhaarman/listviewanimations/itemmanipulation/tests/matchers/Matchers.java b/listview-animations-demo/ListviewAnimationLib/tests/java/com/nhaarman/listviewanimations/itemmanipulation/tests/matchers/Matchers.java deleted file mode 100644 index 1f0ab7b..0000000 --- a/listview-animations-demo/ListviewAnimationLib/tests/java/com/nhaarman/listviewanimations/itemmanipulation/tests/matchers/Matchers.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.nhaarman.listviewanimations.itemmanipulation.tests.matchers; - -import android.util.Pair; - -import org.hamcrest.Description; -import org.hamcrest.Factory; -import org.hamcrest.Matcher; -import org.hamcrest.TypeSafeMatcher; - -import java.util.concurrent.atomic.AtomicInteger; - -public class Matchers { - - @Factory - public static Matcher> pairWithValues(T first, F second) { - return new PairWithValues(first, second); - } - - @Factory - public static Matcher atomicIntegerWithValue(int value) { - return new AtomicIntegerWithValue(value); - } - - private static class PairWithValues extends TypeSafeMatcher> { - - private T first; - private F second; - - public PairWithValues(T first, F second) { - this.first = first; - this.second = second; - } - - @Override - public void describeTo(Description description) { - description.appendText("Dunno!"); - } - - @Override - protected boolean matchesSafely(Pair tfPair) { - return tfPair.first.equals(first) && tfPair.second.equals(second); - } - } - - private static class AtomicIntegerWithValue extends TypeSafeMatcher { - - private int mValue; - - public AtomicIntegerWithValue(int value) { - mValue = value; - } - - @Override - public void describeTo(Description description) { - description.appendText(String.valueOf(mValue)); - } - - @Override - protected boolean matchesSafely(AtomicInteger atomicInteger) { - return mValue == atomicInteger.intValue(); - } - } -} diff --git a/listview-animations-demo/README.md b/listview-animations-demo/README.md index 8444261..890331e 100644 --- a/listview-animations-demo/README.md +++ b/listview-animations-demo/README.md @@ -1,8 +1,7 @@ ListviewAnimation demo实例 -本工程为Eclipse工程 +本工程为Android Studio工程 文件夹说明如下 --ListviewAnimationDemo Demo工程 ---ListviewAnimationLib 依赖库 --apk demo工程生成的apk -原理分析[https://github.com/android-cn/android-open-project-analysis/tree/master/listview-animations](https://github.com/android-cn/android-open-project-analysis/tree/master/listview-animations) \ No newline at end of file +原理分析[https://github.com/android-cn/android-open-project-analysis/tree/master/listview-animations](https://github.com/android-cn/android-open-project-analysis/tree/master/listview-animations) diff --git a/nineoldanimations-demo/AndroidManifest.xml b/nineoldanimations-demo/AndroidManifest.xml new file mode 100755 index 0000000..853e102 --- /dev/null +++ b/nineoldanimations-demo/AndroidManifest.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nineoldanimations-demo/README.md b/nineoldanimations-demo/README.md new file mode 100644 index 0000000..b48ace2 --- /dev/null +++ b/nineoldanimations-demo/README.md @@ -0,0 +1,10 @@ +NineoldAnimations Demo +==================== +###1. Demo Download +[本地下载](apk/nineoldanimations-demo.apk?raw=true "点击下载到本地") + +###2. Screenshot +![Screenshot](apk/nineoldanimations.gif) + +###3. Document +[How to Use NineoldAnimations](http://nineoldandroids.com/) diff --git a/nineoldanimations-demo/apk/nineoldanimations-demo.apk b/nineoldanimations-demo/apk/nineoldanimations-demo.apk new file mode 100644 index 0000000..f55c89e Binary files /dev/null and b/nineoldanimations-demo/apk/nineoldanimations-demo.apk differ diff --git a/nineoldanimations-demo/apk/nineoldanimations.gif b/nineoldanimations-demo/apk/nineoldanimations.gif new file mode 100644 index 0000000..0638f8b Binary files /dev/null and b/nineoldanimations-demo/apk/nineoldanimations.gif differ diff --git a/listview-animations-demo/ListviewAnimationDemo/libs/android-support-v4.jar b/nineoldanimations-demo/libs/android-support-v4.jar old mode 100644 new mode 100755 similarity index 100% rename from listview-animations-demo/ListviewAnimationDemo/libs/android-support-v4.jar rename to nineoldanimations-demo/libs/android-support-v4.jar diff --git a/listview-animations-demo/ListviewAnimationLib/libs/nineoldandroids-2.4.0.jar b/nineoldanimations-demo/libs/nineoldandroids-2.4.0.jar old mode 100644 new mode 100755 similarity index 90% rename from listview-animations-demo/ListviewAnimationLib/libs/nineoldandroids-2.4.0.jar rename to nineoldanimations-demo/libs/nineoldandroids-2.4.0.jar index 43ee45f..d6964d7 Binary files a/listview-animations-demo/ListviewAnimationLib/libs/nineoldandroids-2.4.0.jar and b/nineoldanimations-demo/libs/nineoldandroids-2.4.0.jar differ diff --git a/nineoldanimations-demo/proguard-project.txt b/nineoldanimations-demo/proguard-project.txt new file mode 100755 index 0000000..f2fe155 --- /dev/null +++ b/nineoldanimations-demo/proguard-project.txt @@ -0,0 +1,20 @@ +# To enable ProGuard in your project, edit project.properties +# to define the proguard.config property as described in that file. +# +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in ${sdk.dir}/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the ProGuard +# include property in project.properties. +# +# 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/nineoldanimations-demo/project.properties b/nineoldanimations-demo/project.properties new file mode 100755 index 0000000..b7c2081 --- /dev/null +++ b/nineoldanimations-demo/project.properties @@ -0,0 +1,14 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system edit +# "ant.properties", and override values to adapt the script to your +# project structure. +# +# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): +#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt + +# Project target. +target=android-10 diff --git a/nineoldanimations-demo/res/drawable-hdpi/circle1.png b/nineoldanimations-demo/res/drawable-hdpi/circle1.png new file mode 100755 index 0000000..4a2c931 Binary files /dev/null and b/nineoldanimations-demo/res/drawable-hdpi/circle1.png differ diff --git a/nineoldanimations-demo/res/drawable-hdpi/circle2.png b/nineoldanimations-demo/res/drawable-hdpi/circle2.png new file mode 100755 index 0000000..303a5b4 Binary files /dev/null and b/nineoldanimations-demo/res/drawable-hdpi/circle2.png differ diff --git a/nineoldanimations-demo/res/drawable-hdpi/circle3.png b/nineoldanimations-demo/res/drawable-hdpi/circle3.png new file mode 100755 index 0000000..5c5e6a1 Binary files /dev/null and b/nineoldanimations-demo/res/drawable-hdpi/circle3.png differ diff --git a/nineoldanimations-demo/res/drawable-hdpi/circle4.png b/nineoldanimations-demo/res/drawable-hdpi/circle4.png new file mode 100755 index 0000000..7e5ad1c Binary files /dev/null and b/nineoldanimations-demo/res/drawable-hdpi/circle4.png differ diff --git a/nineoldanimations-demo/res/drawable-hdpi/circle5.png b/nineoldanimations-demo/res/drawable-hdpi/circle5.png new file mode 100755 index 0000000..f1ce6e9 Binary files /dev/null and b/nineoldanimations-demo/res/drawable-hdpi/circle5.png differ diff --git a/nineoldanimations-demo/res/drawable-hdpi/menu.png b/nineoldanimations-demo/res/drawable-hdpi/menu.png new file mode 100755 index 0000000..af5913b Binary files /dev/null and b/nineoldanimations-demo/res/drawable-hdpi/menu.png differ diff --git a/nineoldanimations-demo/res/drawable-xhdpi/image.png b/nineoldanimations-demo/res/drawable-xhdpi/image.png new file mode 100644 index 0000000..9c15fbd Binary files /dev/null and b/nineoldanimations-demo/res/drawable-xhdpi/image.png differ diff --git a/nineoldanimations-demo/res/layout/activity_main.xml b/nineoldanimations-demo/res/layout/activity_main.xml new file mode 100755 index 0000000..4200651 --- /dev/null +++ b/nineoldanimations-demo/res/layout/activity_main.xml @@ -0,0 +1,50 @@ + + + + + + +