Swipe menu impl

This commit is contained in:
Tariel Hlontsi 2016-07-16 12:50:18 +03:00
parent acfef2495c
commit a89d5ee1bc
46 changed files with 1947 additions and 1218 deletions

View File

@ -37,7 +37,7 @@
<ConfirmationsSetting value="0" id="Add" /> <ConfirmationsSetting value="0" id="Add" />
<ConfirmationsSetting value="0" id="Remove" /> <ConfirmationsSetting value="0" id="Remove" />
</component> </component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" /> <output url="file://$PROJECT_DIR$/build/classes" />
</component> </component>
<component name="ProjectType"> <component name="ProjectType">

View File

@ -6,6 +6,7 @@ import android.app.FragmentManager;
import android.app.FragmentTransaction; import android.app.FragmentTransaction;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log; import android.util.Log;
import android.view.MenuItem;
import com.hikapro.backpack.model.AddModel; import com.hikapro.backpack.model.AddModel;
import com.hikapro.backpack.model.DetailModel; import com.hikapro.backpack.model.DetailModel;
@ -40,6 +41,21 @@ public class MainActivity extends Activity implements View.ActivityCallback {
// life cycle --> // life cycle -->
@Override
public boolean onOptionsItemSelected(MenuItem item) {
boolean ret;
switch (item.getItemId()) {
case android.R.id.home:
this.getFragmentManager().popBackStack();
ret = true;
break;
default:
ret = super.onOptionsItemSelected(item);
}
return ret;
}
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -48,7 +64,6 @@ public class MainActivity extends Activity implements View.ActivityCallback {
stateMaintainer.init(); stateMaintainer.init();
if (fragmentManager.getBackStackEntryCount() == 0 && savedInstanceState == null) { if (fragmentManager.getBackStackEntryCount() == 0 && savedInstanceState == null) {
startSetListFragment(); startSetListFragment();
} else { } else {
@ -229,9 +244,9 @@ public class MainActivity extends Activity implements View.ActivityCallback {
} }
@Override @Override
public void startItemDetailFragment(Item item) { public void startItemDetailFragment(Item item, int setId) {
ItemDetailFragment view = ItemDetailFragment.newFromItem(item); ItemDetailFragment view = ItemDetailFragment.newInstance(item, setId);
ItemDetailPresenter presenter = new ItemDetailPresenter(); ItemDetailPresenter presenter = new ItemDetailPresenter();
DetailModel model = new DetailModel(); DetailModel model = new DetailModel();

View File

@ -79,7 +79,6 @@ public class StateMaintainer {
public void put(String key, Object obj) { public void put(String key, Object obj) {
data.put(key, obj); data.put(key, obj);
Log.i(this.toString(), String.format("Put object %s Total count %d", key, data.size()));
} }

View File

@ -2,13 +2,17 @@ package com.hikapro.backpack.model;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.os.Message; import android.os.Message;
import android.widget.Toast;
import com.hikapro.backpack.App;
import com.hikapro.backpack.model.dao.Command; import com.hikapro.backpack.model.dao.Command;
import com.hikapro.backpack.model.dao.DAO; import com.hikapro.backpack.model.dao.DAO;
import com.hikapro.backpack.model.dao.Event; import com.hikapro.backpack.model.dao.Event;
import com.hikapro.backpack.model.entities.Item; import com.hikapro.backpack.model.entities.Item;
import com.hikapro.backpack.presenter.Presenter; import com.hikapro.backpack.presenter.Presenter;
import java.util.Collections;
/** /**
* Created by tariel on 23/04/16. * Created by tariel on 23/04/16.
*/ */
@ -18,10 +22,10 @@ public class DetailModel implements Model.Detail {
private Item item; private Item item;
private DAO dao; private DAO dao;
private Bitmap pic; private Bitmap pic;
private int currentSet;
public DetailModel() { public DetailModel() {
this.dao = DAO.getInstance(); this.dao = DAO.getInstance();
dao.registerObserver(this);
} }
// detail --> // detail -->
@ -45,6 +49,7 @@ public class DetailModel implements Model.Detail {
@Override @Override
public void notifyDataSetChanged() { public void notifyDataSetChanged() {
if (presenter != null)
presenter.notifyDataSetChanged(); presenter.notifyDataSetChanged();
} }
@Override @Override
@ -52,10 +57,7 @@ public class DetailModel implements Model.Detail {
if ( !isConfigurationChanging ) { if ( !isConfigurationChanging ) {
presenter = null; presenter = null;
} }
} dao.unregisterObserver(this);
private void sendMessage(String message) {
presenter.showMessage(message);
} }
// events <-- // events <--
@ -63,15 +65,64 @@ public class DetailModel implements Model.Detail {
// process --> // process -->
@Override @Override
public void executeQuery() { public void executeQuery() {
dao.registerObserver(this);
Message command = Message.obtain();
command.what = Command.ITEM_READ;
command.arg1 = currentSet;
command.arg2 = item.getId();
dao.executeCommand(command);
notifyDataSetChanged();
Message command;
command = Message.obtain(); command = Message.obtain();
command.what = Command.ITEM_GET_IMAGE; command.what = Command.ITEM_GET_IMAGE;
command.arg1 = item.getId(); command.arg1 = item.getId();
dao.executeCommand(command); dao.executeCommand(command);
} }
@Override
public void pendingRemove(Item item) {
if (item != null) {
Message command = Message.obtain();
command.what = Command.ITEM_PENDING_REMOVAL;
command.arg1 = currentSet;
command.arg2 = item.getId();
dao.executeCommand(command);
}
}
@Override
public void pendingRemoveCancel(Item item) {
if (item != null) {
Message command = Message.obtain();
command.what = Command.ITEM_REMOVAL_CANCEL;
command.arg1 = currentSet;
command.arg2 = item.getId();
dao.executeCommand(command);
}
}
@Override
public void packItem(Item item) {
if (item != null) {
Message command = Message.obtain();
command.what = Command.ITEM_PACK;
command.arg1 = currentSet;
command.arg2 = item.getId();
dao.executeCommand(command);
}
}
@Override
public void unpackItem(Item item) {
if (item != null) {
Message command = Message.obtain();
command.what = Command.ITEM_UNPACK;
command.arg1 = currentSet;
command.arg2 = item.getId();
dao.executeCommand(command);
}
}
// process <-- // process <--
@ -79,6 +130,7 @@ public class DetailModel implements Model.Detail {
public void setPresenter(Presenter.ItemDetail presenter) { public void setPresenter(Presenter.ItemDetail presenter) {
this.presenter = presenter; this.presenter = presenter;
this.item = presenter.getCurrentItem(); this.item = presenter.getCurrentItem();
this.currentSet = presenter.getSetId();
} }
@Override @Override
@ -90,10 +142,40 @@ public class DetailModel implements Model.Detail {
public void onEvent(Message event) { public void onEvent(Message event) {
switch (event.what) { switch (event.what) {
case Event.ITEM_IMAGE_LOAD_ERROR :
case Event.ITEM_IMAGE_LOAD_ERROR:
pic = null;
if (presenter != null)
presenter.notifyPictureChanged();
break; break;
case Event.ITEM_IMAGE_LOAD_COMPLETED : case Event.ITEM_READ_ERROR:
Toast.makeText(App.getAppContext(), "Item read error", Toast.LENGTH_SHORT).show();
break;
case Event.ITEM_PACK_ERROR:
break;
case Event.ITEM_UNPACK_ERROR:
break;
case Event.ITEM_PENDING_REMOVAL_ERROR:
break;
case Event.ITEM_REMOVAL_CANCEL_ERROR:
break;
case Event.ITEM_IMAGE_LOAD_COMPLETED:
pic = (Bitmap) event.obj; pic = (Bitmap) event.obj;
if (presenter != null)
presenter.notifyPictureChanged();
break;
case Event.ITEM_PACKED:
executeQuery();
break;
case Event.ITEM_UNPACKED:
executeQuery();
case Event.ITEM_PENDING_REMOVAL_COMPLETED:
executeQuery();
case Event.ITEM_REMOVAL_CANCELED:
executeQuery();
break;
case Event.ITEM_READ_COMPLETED:
item = (Item) event.obj;
notifyDataSetChanged(); notifyDataSetChanged();
break; break;
} }

View File

@ -23,35 +23,133 @@ import com.hikapro.backpack.presenter.Presenter;
public class ItemModel implements Model.Item { public class ItemModel implements Model.Item {
protected Presenter.ItemList presenter; protected Presenter.ItemList presenter;
private List<Category> rawCategories;
private List<Category> sortedCategories;
private List<Item> rawItems;
protected DAO dao; protected DAO dao;
protected int currentSet; protected int currentSet;
protected int currentSetActiveItemsQty; protected int currentSetActiveItemsQty;
protected int packedQty; protected int packedQty;
protected Hashtable<Integer, Category> categoriesCache; protected Hashtable<Integer, Category> categoriesCache;
private List<Item> itemsCache; protected List<Item> itemsCache;
private List<Item> itemsDiscardCache;
private Hashtable<Category, List<Item>> items; protected Hashtable<Category, List<Item>> items;
protected Hashtable<Integer, List<Item>> cache;
public ItemModel() { public ItemModel() {
this.rawCategories = new ArrayList<>();
this.rawItems = new ArrayList<>();
this.sortedCategories = new ArrayList<>();
this.categoriesCache = new Hashtable<>(20, 0.9f); this.categoriesCache = new Hashtable<>(20, 0.9f);
this.itemsCache = new ArrayList<>(256);
this.packedQty = -1; this.packedQty = -1;
this.itemsCache = new ArrayList<>();
this.itemsDiscardCache = new ArrayList<>();
this.cache = new Hashtable<>(12, 0.9f);
this.dao = DAO.getInstance(); this.dao = DAO.getInstance();
}
@Override
public void onEvent(Message event) {
switch (event.what) {
case Event.SET_ITEMS_LOAD_ERROR : // TODO check
if (presenter != null) {
if (packedQty == -1)
packedQty = presenter.getCurrentSet().getPackedQty();
presenter.notifyItemPackStatusChanged();
}
break;
case Event.SET_UNPACK_ERROR :
break;
case Event.SET_RESTORE_ERROR :
break;
case Event.SET_GET_STAT_ERROR:
break;
case Event.ITEM_FROM_SET_ERROR :
break;
case Event.ITEM_DELETE_ERROR :
break;
case Event.ITEM_PACK_ERROR :
break;
case Event.ITEM_UNPACK_ERROR :
break;
case Event.ITEM_INSERT_ERROR :
break;
case Event.ITEM_PENDING_REMOVAL_ERROR:
break;
case Event.ITEM_REMOVAL_CANCEL_ERROR:
break;
case Event.ITEM_CATEGORY_LOAD_ERROR :
break;
case Event.SET_ITEMS_LOAD_COMPLETED :
itemsCache = (List<Item>) event.obj;
notifyDataSetChanged();
break;
case Event.SET_GET_STAT_COMPLETED:
currentSetActiveItemsQty = event.arg1;
packedQty = event.arg2;
if (presenter != null)
presenter.notifyItemPackStatusChanged();
break;
case Event.ITEM_PENDING_REMOVAL_COMPLETED:
executeQuery();
break;
case Event.ITEM_REMOVAL_CANCELED:
executeQuery();
break;
case Event.ITEM_READ_COMPLETED:
itemsCache.add((Item) event.obj);
Collections.sort(itemsCache);
notifyDataSetChanged();
break;
case Event.SET_UNPACK_COMPLETED:
packedQty = 0;
if (presenter != null) {
presenter.notifyItemPackStatusChanged();
}
break;
case Event.ITEM_CATEGORY_LOAD_COMPLETED:
categoriesCache = (Hashtable<Integer, Category>)event.obj;
break;
case Event.ITEM_FROM_SET_DELETED:
executeQuery();
break;
case Event.ITEM_DELETED :
break;
case Event.ITEM_PACKED :
executeQuery();
break;
case Event.ITEM_UNPACKED :
executeQuery();
break;
case Event.ITEM_INSERTED :
break;
case Event.SET_RESTORE_COMPLETED :
if (presenter != null) {
presenter.notifyDataSetChanged();
}
Toast.makeText(App.getAppContext(), "Restore completed", Toast.LENGTH_SHORT).show();
break;
}
}
@Override
public void executeQuery() {
Message command;
dao.registerObserver(this); dao.registerObserver(this);
command = Message.obtain();
command.what = Command.SET_CLEAN_PACKED;
command.arg1 = currentSet;
dao.executeCommand(command);
if (categoriesCache.isEmpty()) {
command = Message.obtain();
command.what = Command.ITEM_GET_CATEGORIES;
dao.executeCommand(command);
}
command = Message.obtain();
command.what = Command.SET_GET_ITEMS;
command.arg1 = currentSet;
dao.executeCommand(command);
command = Message.obtain();
command.what = Command.SET_GET_STAT;
command.arg1 = presenter.getCurrentSet().getId();
dao.executeCommand(command);
} }
// categories --> // categories -->
@ -59,8 +157,7 @@ public class ItemModel implements Model.Item {
@Override @Override
public Category getCategoryByPosition(int position) { public Category getCategoryByPosition(int position) {
Category ret = null; Category ret = null;
if (cache.containsKey(currentSet)) ret = categoriesCache.get(itemsCache.get(position).getCategory());
ret = categoriesCache.get(cache.get(currentSet).get(position).getCategory());
return ret; return ret;
} }
@ -68,51 +165,24 @@ public class ItemModel implements Model.Item {
// items --> // items -->
@Override
public int insertItem(Item item) {
List<Item> iList = cache.get(currentSet);
iList.add(item);
Collections.sort(iList);
cache.put(currentSet, iList);
++currentSetActiveItemsQty;
// TODO write to database
return 0;
}
@Override
public boolean deleteItem(Item item) {
if (isPendingRemoval(item))
itemsDiscardCache.remove(item);
cache.get(currentSet).remove(item);
--currentSetActiveItemsQty;
//TODO write to ds
return false;
}
@Override @Override
public Item findItem(int id) { public Item findItem(int id) {
List<Item> items = cache.get(currentSet);
Item item = null; Item item = null;
if (items != null) for (Item i : itemsCache) {
{
for (Item i : items) {
if (i.getId() == id) { if (i.getId() == id) {
item = i; item = i;
break; break;
} }
} }
}
return item; return item;
} }
@Override @Override
public Item getItemByPosition(int position) { public Item getItemByPosition(int position) {
Item ret = null; Item ret = null;
if (cache.containsKey(currentSet)) ret = itemsCache.get(position);
ret = cache.get(currentSet).get(position);
return ret; return ret;
} }
@Override @Override
public void filter(String query) { public void filter(String query) {
@ -125,53 +195,29 @@ public class ItemModel implements Model.Item {
query = query.toLowerCase(); query = query.toLowerCase();
String name; String name;
List<Item> newList = new ArrayList<>(20); List<Item> newList = new ArrayList<>(20);
List<Item> oldList = cache.get(currentSet); for (Item item : itemsCache) {
for (Item item : oldList) {
name = item.getName().toLowerCase(); name = item.getName().toLowerCase();
if (name.contains(query)) { if (name.contains(query)) {
newList.add(item); newList.add(item);
} }
} }
cache.put(currentSet, newList); itemsCache = newList;
} }
} }
@Override @Override
public int getHeaderId(int position) { public int getHeaderId(int position) {
return cache.containsKey(currentSet) ? cache.get(currentSet).get(position).getCategory() : -1; return itemsCache.get(position).getCategory();
} }
@Override @Override
public int getItemId(int position) { public int getItemId(int position) {
return cache.containsKey(currentSet) ? cache.get(currentSet).get(position).getId() : -1; return itemsCache.get(position).getId();
}
@Override
public void clear() {
if (cache.containsKey(currentSet))
cache.get(currentSet).clear();
}
@Override
public boolean isPendingRemoval(Item item) {
return itemsDiscardCache.contains(item);
}
@Override
public void pendingRemoveCancel(Item item) {
if (itemsDiscardCache.contains(item))
itemsDiscardCache.remove(item);
}
@Override
public void pendingRemove(Item item) {
itemsDiscardCache.add(item);
} }
@Override @Override
public int getItemsCount() { public int getItemsCount() {
boolean is = cache.containsKey(currentSet); return itemsCache.size();
return is ? cache.get(currentSet).size() : 0;
} }
@Override @Override
@ -189,6 +235,7 @@ public class ItemModel implements Model.Item {
@Override @Override
public void notifyDataSetChanged() { public void notifyDataSetChanged() {
if (presenter != null)
presenter.notifyDataSetChanged(); presenter.notifyDataSetChanged();
} }
@ -197,31 +244,62 @@ public class ItemModel implements Model.Item {
if ( !isConfigurationChanging ) { if ( !isConfigurationChanging ) {
presenter = null; presenter = null;
} }
dao.unregisterObserver(this);
} }
private void sendMessage(String message) {
presenter.showMessage(message);
}
// events <-- // events <--
// process --> // process -->
@Override @Override
public void packItem(int itemId) { public void pendingRemove(Item item) {
Item item = findItem(itemId); if (item != null) {
if (item != null)
cache.get(currentSet).remove(item);
Message command = Message.obtain(); Message command = Message.obtain();
command.what = Command.ITEM_PACK; command.what = Command.ITEM_PENDING_REMOVAL;
command.arg1 = currentSet; command.arg1 = currentSet;
command.arg2 = itemId; command.arg2 = item.getId();
dao.executeCommand(command); dao.executeCommand(command);
//itemsCache.remove(item);// TODO check nn
}
} }
@Override @Override
public void unpackItem(int itemId) { public void pendingRemoveCancel(Item item) {
if (item != null) {
Message command = Message.obtain();
command.what = Command.ITEM_REMOVAL_CANCEL;
command.arg1 = currentSet;
command.arg2 = item.getId();
dao.executeCommand(command);
//itemsCache.remove(item);
}
}
@Override
public void remove(Item item) {
if (item != null) {
Message command = Message.obtain();
command.what = Command.ITEM_DELETE_FROM_SET;
command.arg1 = currentSet;
command.arg2 = item.getId();
dao.executeCommand(command);
//itemsCache.remove(item);
}
}
// TODO use item itself?
@Override
public void packItem(com.hikapro.backpack.model.entities.Item item) {
if (item != null) {
itemsCache.remove(item);
Message command = Message.obtain();
command.what = Command.ITEM_PACK;
command.arg1 = currentSet;
command.arg2 = item.getId();
dao.executeCommand(command);
}
}
@Override
public void unpackItem(com.hikapro.backpack.model.entities.Item item) {
// nothing // nothing
} }
@ -239,98 +317,6 @@ public class ItemModel implements Model.Item {
dao.executeCommand(command); dao.executeCommand(command);
} }
@Override
public void executeQuery() {
Message command;
if (cache.contains(currentSet)) {
notifyDataSetChanged();
} else {
if (categoriesCache.isEmpty()) {
command = Message.obtain();
command.what = Command.ITEM_GET_CATEGORIES;
dao.executeCommand(command);
}
command = Message.obtain();
command.what = Command.SET_GET_ITEMS;
command.arg1 = presenter.getCurrentSet().getId();
dao.executeCommand(command);
}
}
@Override
public void onEvent(Message event) {
switch (event.what) {
case Event.SET_ITEMS_LOAD_ERROR : // TODO check
if (presenter != null) {
if (packedQty == -1)
packedQty = presenter.getCurrentSet().getPackedQty();
presenter.notifyItemPackStatusChanged();
}
break;
case Event.SET_UNPACK_ERROR :
break;
case Event.SET_RESTORE_ERROR :
break;
case Event.ITEM_FROM_SET_ERROR :
break;
case Event.ITEM_DELETE_ERROR :
break;
case Event.ITEM_PACK_ERROR :
break;
case Event.ITEM_UNPACK_ERROR :
break;
case Event.ITEM_INSERT_ERROR :
break;
case Event.ITEM_CATEGORY_LOAD_ERROR :
break;
case Event.SET_ITEMS_LOAD_COMPLETED :
List<Item> res = (List<Item>) event.obj;
cache.put(event.arg1, res);
notifyDataSetChanged();
if (presenter != null) {
if (packedQty == -1)
packedQty = presenter.getCurrentSet().getPackedQty();
presenter.notifyItemPackStatusChanged();
}
break;
case Event.SET_UNPACK_COMPLETED :
packedQty = 0;
if (presenter != null) {
presenter.notifyItemPackStatusChanged();
}
break;
case Event.ITEM_CATEGORY_LOAD_COMPLETED :
categoriesCache = (Hashtable<Integer, Category>)event.obj;
break;
case Event.ITEM_FROM_SET_DELETED :
break;
case Event.ITEM_DELETED :
break;
case Event.ITEM_PACKED :
//TODO something
++packedQty;
if (presenter != null) {
presenter.notifyItemPackStatusChanged();
}
break;
case Event.ITEM_UNPACKED :
--packedQty;
if (presenter != null) {
presenter.notifyItemPackStatusChanged();
}
break;
case Event.ITEM_INSERTED :
break;
case Event.SET_RESTORE_COMPLETED :
if (presenter != null) {
presenter.notifyDataSetChanged();
}
Toast.makeText(App.getAppContext(), "Restore completed", Toast.LENGTH_SHORT).show();
break;
}
}
// process <-- // process <--
// other --> // other -->
@ -341,6 +327,7 @@ public class ItemModel implements Model.Item {
this.presenter = presenter; this.presenter = presenter;
this.currentSet = presenter.getCurrentSet().getId(); this.currentSet = presenter.getCurrentSet().getId();
this.currentSetActiveItemsQty = presenter.getCurrentSet().getActiveQty(); this.currentSetActiveItemsQty = presenter.getCurrentSet().getActiveQty();
//dao.registerObserver(this);
} }
@Override @Override
@ -348,16 +335,5 @@ public class ItemModel implements Model.Item {
return presenter; return presenter;
} }
private Category findCategory(int categoryId) {
Category category = null;
for (Category c : rawCategories) {
if (c.getId() == categoryId) {
category = c;
break;
}
}
return category;
}
// other <-- // other <--
} }

View File

@ -34,15 +34,13 @@ public interface Model {
} }
interface Item extends Base { interface Item extends Base {
int insertItem(com.hikapro.backpack.model.entities.Item item);
boolean deleteItem(com.hikapro.backpack.model.entities.Item item);
void filter(String query); void filter(String query);
int getHeaderId(int position);//TODO review int getHeaderId(int position);//TODO review
int getItemId(int position);//TODO review int getItemId(int position);//TODO review
void clear(); // leave at home
boolean isPendingRemoval(com.hikapro.backpack.model.entities.Item item);
void pendingRemove(com.hikapro.backpack.model.entities.Item item); void pendingRemove(com.hikapro.backpack.model.entities.Item item);
void pendingRemoveCancel(com.hikapro.backpack.model.entities.Item item); void pendingRemoveCancel(com.hikapro.backpack.model.entities.Item item);
void remove(com.hikapro.backpack.model.entities.Item item);
int getItemsCount(); int getItemsCount();
int getActiveItemsCount(); int getActiveItemsCount();
int getPackedQty(); int getPackedQty();
@ -54,8 +52,8 @@ public interface Model {
void setPresenter(Presenter.ItemList presenter); void setPresenter(Presenter.ItemList presenter);
Presenter.ItemList getPresenter(); Presenter.ItemList getPresenter();
void packItem(int itemId); void packItem(com.hikapro.backpack.model.entities.Item item);
void unpackItem(int itemId); void unpackItem(com.hikapro.backpack.model.entities.Item item);
void unpackSet(int setId); void unpackSet(int setId);
void restoreSet(int setId); void restoreSet(int setId);
} }
@ -66,6 +64,10 @@ public interface Model {
Bitmap getPicture(); Bitmap getPicture();
void setPresenter(Presenter.ItemDetail presenter); void setPresenter(Presenter.ItemDetail presenter);
Presenter.ItemDetail getPresenter(); Presenter.ItemDetail getPresenter();
void pendingRemove(com.hikapro.backpack.model.entities.Item item);
void pendingRemoveCancel(com.hikapro.backpack.model.entities.Item item);
void packItem(com.hikapro.backpack.model.entities.Item item);
void unpackItem(com.hikapro.backpack.model.entities.Item item);
} }
interface Share extends Base { interface Share extends Base {

View File

@ -2,6 +2,7 @@ package com.hikapro.backpack.model;
import android.os.Message; import android.os.Message;
import java.util.Collections;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.List; import java.util.List;
@ -22,10 +23,7 @@ public class PackedModel extends ItemModel {
@Override @Override
public void executeQuery() { public void executeQuery() {
Message command; Message command;
dao.registerObserver(this);
if (cache.contains(currentSet)) {
notifyDataSetChanged();
} else {
if (categoriesCache.isEmpty()) { if (categoriesCache.isEmpty()) {
command = Message.obtain(); command = Message.obtain();
command.what = Command.ITEM_GET_CATEGORIES; command.what = Command.ITEM_GET_CATEGORIES;
@ -33,10 +31,14 @@ public class PackedModel extends ItemModel {
} }
command = Message.obtain(); command = Message.obtain();
command.what = Command.SET_GET_PACKED_ITEMS; command.what = Command.SET_GET_PACKED_ITEMS;
command.arg1 = currentSet;
dao.executeCommand(command);
command = Message.obtain();
command.what = Command.SET_GET_STAT;
command.arg1 = presenter.getCurrentSet().getId(); command.arg1 = presenter.getCurrentSet().getId();
dao.executeCommand(command); dao.executeCommand(command);
} }
}
@Override @Override
public void onEvent(Message event) { public void onEvent(Message event) {
@ -47,24 +49,45 @@ public class PackedModel extends ItemModel {
break; break;
case Event.SET_UNPACK_ERROR : case Event.SET_UNPACK_ERROR :
break; break;
case Event.SET_GET_STAT_ERROR:
break;
case Event.ITEM_CATEGORY_LOAD_ERROR : case Event.ITEM_CATEGORY_LOAD_ERROR :
break; break;
case Event.ITEM_PACK_ERROR : case Event.ITEM_PACK_ERROR :
break; break;
case Event.ITEM_UNPACK_ERROR : case Event.ITEM_UNPACK_ERROR :
break; break;
case Event.ITEM_PENDING_REMOVAL_ERROR:
break;
case Event.ITEM_REMOVAL_CANCEL_ERROR:
break;
case Event.SET_PACKED_LOAD_COMPLETED : case Event.SET_PACKED_LOAD_COMPLETED :
List<Item> res = (List<Item>) event.obj; itemsCache = (List<Item>) event.obj;
cache.put(event.arg1, res);
notifyDataSetChanged(); notifyDataSetChanged();
packedQty = res.size(); break;
if (presenter != null) { case Event.SET_GET_STAT_COMPLETED:
currentSetActiveItemsQty = event.arg1;
packedQty = event.arg2;
if (presenter != null)
presenter.notifyItemPackStatusChanged(); presenter.notifyItemPackStatusChanged();
} break;
case Event.ITEM_FROM_SET_DELETED:
executeQuery();
break;
case Event.ITEM_PENDING_REMOVAL_COMPLETED:// TODO DEL
executeQuery();
break;
case Event.ITEM_REMOVAL_CANCELED:
executeQuery();
break;
case Event.ITEM_READ_COMPLETED:
itemsCache.add((Item) event.obj);
Collections.sort(itemsCache);
notifyDataSetChanged();
break; break;
case Event.SET_UNPACK_COMPLETED : case Event.SET_UNPACK_COMPLETED :
packedQty = 0; packedQty = 0;
cache.get(event.arg2).clear(); itemsCache.clear();
if (presenter != null) { if (presenter != null) {
presenter.notifyItemPackStatusChanged(); presenter.notifyItemPackStatusChanged();
} }
@ -73,37 +96,36 @@ public class PackedModel extends ItemModel {
categoriesCache = (Hashtable<Integer, Category>)event.obj; categoriesCache = (Hashtable<Integer, Category>)event.obj;
break; break;
case Event.ITEM_PACKED : case Event.ITEM_PACKED :
//TODO something executeQuery();
++packedQty;
if (presenter != null) {
presenter.notifyItemPackStatusChanged();
}
break; break;
case Event.ITEM_UNPACKED : case Event.ITEM_UNPACKED :
--packedQty; executeQuery();
if (presenter != null) {
presenter.notifyItemPackStatusChanged();
}
break; break;
} }
} }
@Override @Override
public void unpackItem(int itemId) { public void unpackItem(com.hikapro.backpack.model.entities.Item item) {
Message command; if (item != null) {
command = Message.obtain(); Message command = Message.obtain();
command.what = Command.ITEM_UNPACK; command.what = Command.ITEM_UNPACK;
command.arg1 = currentSet; command.arg1 = currentSet;
command.arg2 = itemId; command.arg2 = item.getId();
dao.executeCommand(command); dao.executeCommand(command);
Item item = findItem(itemId); itemsCache.remove(item); // TODO check nn
if (item != null) }
cache.get(currentSet).remove(item);
} }
@Override @Override
public void packItem(int itemId) { public void packItem(com.hikapro.backpack.model.entities.Item item) {
// nothing if (item != null) {
Message command = Message.obtain();
command.what = Command.ITEM_REMOVAL_CANCEL;
command.arg1 = currentSet;
command.arg2 = item.getId();
dao.executeCommand(command);
itemsCache.remove(item);
}
} }
@Override @Override

View File

@ -16,6 +16,8 @@ public interface Command {
int SET_GET_PACKED_ITEMS = 0x67; int SET_GET_PACKED_ITEMS = 0x67;
int SET_UNPACK_ITEMS = 0x68; int SET_UNPACK_ITEMS = 0x68;
int SET_RESTORE_DEFAULT = 0x69; int SET_RESTORE_DEFAULT = 0x69;
int SET_GET_STAT = 0x70;
int SET_CLEAN_PACKED = 0x71;
int ITEM_DELETE_FROM_SET = 0x78; int ITEM_DELETE_FROM_SET = 0x78;
int ITEM_INSERT = 0x79; int ITEM_INSERT = 0x79;
@ -24,6 +26,9 @@ public interface Command {
int ITEM_GET_CATEGORIES = 0x7C; int ITEM_GET_CATEGORIES = 0x7C;
int ITEM_GET_IMAGE = 0x7D; int ITEM_GET_IMAGE = 0x7D;
int ITEM_GET_LIKE = 0x7E; int ITEM_GET_LIKE = 0x7E;
int ITEM_PENDING_REMOVAL = 0x7F;
int ITEM_REMOVAL_CANCEL = 0x80;
int ITEM_READ = 0x81;
int MY_LIST_POST = 0x8C; int MY_LIST_POST = 0x8C;
int MY_LIST_ITEM_ADD = 0x8D; int MY_LIST_ITEM_ADD = 0x8D;

View File

@ -85,6 +85,10 @@ public class DAO {
observers.put(o.getClass().getName(), o); observers.put(o.getClass().getName(), o);
} }
public void unregisterObserver(Model.Base o) {
observers.remove(o.getClass().getName());
}
private ThreadPoolExecutor initPool (BlockingQueue<Runnable> taskQueue) { private ThreadPoolExecutor initPool (BlockingQueue<Runnable> taskQueue) {
ThreadPoolExecutor ret = new ThreadPoolExecutor( ThreadPoolExecutor ret = new ThreadPoolExecutor(
CORE_POOL_SIZE CORE_POOL_SIZE
@ -158,6 +162,20 @@ public class DAO {
threadPool.execute(setTask); threadPool.execute(setTask);
break; break;
case Command.SET_GET_STAT :
setTask = new SetTask(Command.SET_GET_STAT,
Process.THREAD_PRIORITY_MORE_FAVORABLE);
setTask.setId = command.arg1;
threadPool.execute(setTask);
break;
case Command.SET_CLEAN_PACKED :
setTask = new SetTask(Command.SET_CLEAN_PACKED,
Process.THREAD_PRIORITY_MORE_FAVORABLE);
setTask.setId = command.arg1;
threadPool.execute(setTask);
break;
case Command.ITEM_GET_CATEGORIES : case Command.ITEM_GET_CATEGORIES :
itemTask = new ItemTask(Command.ITEM_GET_CATEGORIES, itemTask = new ItemTask(Command.ITEM_GET_CATEGORIES,
Process.THREAD_PRIORITY_MORE_FAVORABLE); Process.THREAD_PRIORITY_MORE_FAVORABLE);
@ -172,6 +190,14 @@ public class DAO {
threadPool.execute(itemTask); threadPool.execute(itemTask);
break; break;
case Command.ITEM_READ:
itemTask = new ItemTask(Command.ITEM_READ,
Process.THREAD_PRIORITY_DEFAULT);
itemTask.setId = command.arg1;
itemTask.itemId = command.arg2;
threadPool.execute(itemTask);
break;
case Command.ITEM_DELETE_FROM_SET : case Command.ITEM_DELETE_FROM_SET :
itemTask = new ItemTask(Command.ITEM_DELETE_FROM_SET, itemTask = new ItemTask(Command.ITEM_DELETE_FROM_SET,
Process.THREAD_PRIORITY_BACKGROUND); Process.THREAD_PRIORITY_BACKGROUND);
@ -180,6 +206,22 @@ public class DAO {
threadPool.execute(itemTask); threadPool.execute(itemTask);
break; break;
case Command.ITEM_PENDING_REMOVAL:
itemTask = new ItemTask(Command.ITEM_PENDING_REMOVAL,
Process.THREAD_PRIORITY_BACKGROUND);
itemTask.setId = command.arg1;
itemTask.itemId = command.arg2;
threadPool.execute(itemTask);
break;
case Command.ITEM_REMOVAL_CANCEL:
itemTask = new ItemTask(Command.ITEM_REMOVAL_CANCEL,
Process.THREAD_PRIORITY_BACKGROUND);
itemTask.setId = command.arg1;
itemTask.itemId = command.arg2;
threadPool.execute(itemTask);
break;
case Command.ITEM_PACK : case Command.ITEM_PACK :
itemTask = new ItemTask(Command.ITEM_PACK, itemTask = new ItemTask(Command.ITEM_PACK,
Process.THREAD_PRIORITY_BACKGROUND); Process.THREAD_PRIORITY_BACKGROUND);
@ -462,13 +504,11 @@ public class DAO {
return ret; return ret;
} }
private List<Item> readItems(int setId, boolean packed) { private Item readItem(SQLiteDatabase db, int setId, int itemId) {
List<Item> ret = new ArrayList<>(256); Item ret = null;
Cursor cursor = null; Cursor cursor = null;
SQLiteDatabase db = null;
Item item;
String query = String.format( String query = String.format(
"SELECT a.%s, a.%s, a.%s, a.%s, a.%s, a.%s, a.%s, a.%s, a.%s, a.%s FROM %s a INNER JOIN %s b ON a.%s = b.%s WHERE b.%s = ? AND b.%s <> 1 AND b.%s %s 1", "SELECT a.%s, a.%s, a.%s, a.%s, a.%s, a.%s, a.%s, a.%s, a.%s, a.%s, %s, %s FROM %s a INNER JOIN %s b ON a.%s = b.%s WHERE b.%s = ? AND b.%s = ? LIMIT 1",
Db.ItemsTable.COLUMN_ID, Db.ItemsTable.COLUMN_ID,
Db.ItemsTable.COLUMN_NAME, Db.ItemsTable.COLUMN_NAME,
@ -480,6 +520,102 @@ public class DAO {
Db.ItemsTable.COLUMN_PHOTO_LOCAL, Db.ItemsTable.COLUMN_PHOTO_LOCAL,
Db.ItemsTable.COLUMN_PHOTO_THUMB_LOCAL, Db.ItemsTable.COLUMN_PHOTO_THUMB_LOCAL,
Db.ItemsTable.COLUMN_USER_DEFINED, Db.ItemsTable.COLUMN_USER_DEFINED,
Db.SetItemsTable.COLUMN_PENDING_REMOVAL,
Db.SetItemsTable.COLUMN_PACKED,
Db.ItemsTable.TABLE_NAME,
Db.SetItemsTable.TABLE_NAME,
Db.ItemsTable.COLUMN_ID,
Db.SetItemsTable.COLUMN_ITEM,
Db.SetItemsTable.COLUMN_SET,
Db.SetItemsTable.COLUMN_ITEM);
try {
cursor = db.rawQuery(query, new String[]{String.valueOf(setId), String.valueOf(itemId)});
if (cursor.moveToNext()) {
ret = Db.ItemsTable.parseCursor(cursor);
}
} catch (SQLiteException e) {
//TODO write to log here
} catch (Exception e) {
//TODO write to log here
} finally {
if (cursor != null)
cursor.close();
}
return ret;
}
private Item readItem(int setId, int itemId) {
Item ret = null;
Cursor cursor = null;
SQLiteDatabase db = null;
String query = String.format(
"SELECT a.%s, a.%s, a.%s, a.%s, a.%s, a.%s, a.%s, a.%s, a.%s, a.%s, %s, %s FROM %s a INNER JOIN %s b ON a.%s = b.%s WHERE b.%s = ? AND b.%s = ? LIMIT 1",
Db.ItemsTable.COLUMN_ID,
Db.ItemsTable.COLUMN_NAME,
Db.ItemsTable.COLUMN_CATEGORY,
Db.ItemsTable.COLUMN_DESCRIPTION,
Db.ItemsTable.COLUMN_BUY_URLS,
Db.ItemsTable.COLUMN_PHOTO_URL,
Db.ItemsTable.COLUMN_PHOTO_THUMB_URL,
Db.ItemsTable.COLUMN_PHOTO_LOCAL,
Db.ItemsTable.COLUMN_PHOTO_THUMB_LOCAL,
Db.ItemsTable.COLUMN_USER_DEFINED,
Db.SetItemsTable.COLUMN_PENDING_REMOVAL,
Db.SetItemsTable.COLUMN_PACKED,
Db.ItemsTable.TABLE_NAME,
Db.SetItemsTable.TABLE_NAME,
Db.ItemsTable.COLUMN_ID,
Db.SetItemsTable.COLUMN_ITEM,
Db.SetItemsTable.COLUMN_SET,
Db.SetItemsTable.COLUMN_ITEM);
try {
db = getReadDB();
cursor = db.rawQuery(query, new String[]{String.valueOf(setId), String.valueOf(itemId)});
if (cursor.moveToNext()) {
ret = Db.ItemsTable.parseCursor(cursor);
}
} catch (SQLiteException e) {
//TODO write to log here
} catch (Exception e) {
//TODO write to log here
} finally {
if (cursor != null)
cursor.close();
if (db != null)
db.close();
}
return ret;
}
private List<Item> readItems(int setId, boolean packed) {
List<Item> ret = new ArrayList<>(256);
Cursor cursor = null;
SQLiteDatabase db = null;
Item item;
String query = String.format(
"SELECT a.%s, a.%s, a.%s, a.%s, a.%s, a.%s, a.%s, a.%s, a.%s, a.%s, %s, %s FROM %s a INNER JOIN %s b ON a.%s = b.%s WHERE b.%s = ? AND b.%s <> 1 AND b.%s %s 1",
Db.ItemsTable.COLUMN_ID,
Db.ItemsTable.COLUMN_NAME,
Db.ItemsTable.COLUMN_CATEGORY,
Db.ItemsTable.COLUMN_DESCRIPTION,
Db.ItemsTable.COLUMN_BUY_URLS,
Db.ItemsTable.COLUMN_PHOTO_URL,
Db.ItemsTable.COLUMN_PHOTO_THUMB_URL,
Db.ItemsTable.COLUMN_PHOTO_LOCAL,
Db.ItemsTable.COLUMN_PHOTO_THUMB_LOCAL,
Db.ItemsTable.COLUMN_USER_DEFINED,
Db.SetItemsTable.COLUMN_PENDING_REMOVAL,
Db.SetItemsTable.COLUMN_PACKED,
Db.ItemsTable.TABLE_NAME, Db.ItemsTable.TABLE_NAME,
Db.SetItemsTable.TABLE_NAME, Db.SetItemsTable.TABLE_NAME,
@ -494,14 +630,14 @@ public class DAO {
cursor = db.rawQuery(query, new String[]{String.valueOf(setId)}); cursor = db.rawQuery(query, new String[]{String.valueOf(setId)});
while (cursor.moveToNext()) { while (cursor.moveToNext()) {
item = Db.ItemsTable.parseCursor(cursor); item = Db.ItemsTable.parseCursor(cursor);
// if (!packed && item.isPendingRemoval())
// continue;
ret.add(item); ret.add(item);
} }
} catch (SQLiteException e) { } catch (SQLiteException e) {
//TODO write to log here //TODO write to log here
} catch (Exception e) { } catch (Exception e) {
int i = 0;
String s = null;
//TODO write to log here //TODO write to log here
} finally { } finally {
if (cursor != null) if (cursor != null)
@ -628,6 +764,26 @@ public class DAO {
return ret; return ret;
} }
private Set readSet(int setId) {
Set ret = null;
SQLiteDatabase db = null;
Cursor cursor = null;
try {
db = getReadDB();
String query = String.format("SELECT * FROM %s a WHERE a.%s = %d LIMIT 1",
Db.SetsTable.TABLE_NAME, Db.SetsTable.COLUMN_ID, setId);
cursor = db.rawQuery(query, null);
if (cursor.moveToNext())
ret = Db.SetsTable.parseCursor(cursor);
} finally {
if (cursor != null)
cursor.close();
if (db != null)
db.close();
}
return ret;
}
private List<Set> readSets() { private List<Set> readSets() {
List<Set> ret = new ArrayList<>(12); List<Set> ret = new ArrayList<>(12);
Cursor cursor = null; Cursor cursor = null;
@ -712,7 +868,98 @@ public class DAO {
return ret; return ret;
} }
private int updateSetItemPendingRemoval(int setId, int itemId, boolean remove) {
int ret = 0;
SQLiteDatabase db = null;
ContentValues values;
Set set;
Item item;
try {
db = getWriteDB();
db.beginTransaction();
item = readItem(db, setId, itemId);
values = new ContentValues();
values.put(Db.SetItemsTable.COLUMN_PENDING_REMOVAL, remove);
ret = db.update(Db.SetItemsTable.TABLE_NAME, values, String.format("%s = ? AND %s = ?",
Db.SetItemsTable.COLUMN_SET, Db.SetItemsTable.COLUMN_ITEM ),
new String[]{String.valueOf(setId), String.valueOf(itemId)});
set = readSet(db, setId);
if (set != null) {
values = new ContentValues();
values.put(Db.SetsTable.COLUMN_ACTIVE_QTY, remove ? set.getActiveQty()-1 : set.getActiveQty()+1);
if (item.isPacked() ) {
if (remove)
values.put(Db.SetsTable.COLUMN_PACKED_QTY, set.getPackedQty()-1);
else
values.put(Db.SetsTable.COLUMN_PACKED_QTY, set.getPackedQty()+1);
}
ret += db.update(Db.SetsTable.TABLE_NAME, values, String.format("%s = ?",
Db.SetsTable.COLUMN_ID),
new String[]{String.valueOf(setId)});
}
db.setTransactionSuccessful();
} catch (SQLiteException e) {
//TODO write to log here
} catch (Exception e) {
//TODO write to log here
} finally {
if (db != null) {
db.endTransaction();
db.close();
}
}
return ret;
}
private int updateSetItemDeleted(int setId, int itemId, boolean del) { private int updateSetItemDeleted(int setId, int itemId, boolean del) {
int ret = 0;
SQLiteDatabase db = null;
ContentValues values;
Set set;
Item item;
try {
db = getWriteDB();
db.beginTransaction();
item = readItem(db, setId, itemId);
values = new ContentValues();
values.put(Db.SetItemsTable.COLUMN_DELETED, del);
values.put(Db.SetItemsTable.COLUMN_PENDING_REMOVAL, false);
values.put(Db.SetItemsTable.COLUMN_PACKED, false);
ret = db.update(Db.SetItemsTable.TABLE_NAME, values, String.format("%s = ? AND %s = ?",
Db.SetItemsTable.COLUMN_SET, Db.SetItemsTable.COLUMN_ITEM ),
new String[]{String.valueOf(setId), String.valueOf(itemId)});
set = readSet(db, setId);
if (set != null) {
values = new ContentValues();
if (del) {
if (!item.isPendingRemoval())
values.put(Db.SetsTable.COLUMN_ACTIVE_QTY, set.getActiveQty()-1);
} else
values.put(Db.SetsTable.COLUMN_ACTIVE_QTY, set.getActiveQty()+1);
values.put(Db.SetsTable.COLUMN_PACKED_QTY, item.isPacked() ? set.getPackedQty()-1 :set.getPackedQty());
ret += db.update(Db.SetsTable.TABLE_NAME, values, String.format("%s = ?",
Db.SetsTable.COLUMN_ID),
new String[]{String.valueOf(setId)});
}
db.setTransactionSuccessful();
} catch (SQLiteException e) {
//TODO write to log here
} catch (Exception e) {
//TODO write to log here
} finally {
if (db != null) {
db.endTransaction();
db.close();
}
}
return ret;
}
private int updateSetItemsCleanPacked(int setId) {
int ret = 0; int ret = 0;
SQLiteDatabase db = null; SQLiteDatabase db = null;
ContentValues values; ContentValues values;
@ -720,15 +967,17 @@ public class DAO {
db = getWriteDB(); db = getWriteDB();
db.beginTransaction(); db.beginTransaction();
values = new ContentValues(); values = new ContentValues();
values.put(Db.SetItemsTable.COLUMN_DELETED, del); values.put(Db.SetItemsTable.COLUMN_PACKED, 0);
ret = db.update(Db.SetItemsTable.TABLE_NAME, values, String.format("%s = ? AND %s = ?", ret = db.update(Db.SetItemsTable.TABLE_NAME, values, String.format("%s = ? AND %s = ?",
Db.SetItemsTable.COLUMN_SET, Db.SetItemsTable.COLUMN_ITEM ), Db.SetItemsTable.COLUMN_SET,
new String[]{String.valueOf(setId), String.valueOf(itemId)}); Db.SetItemsTable.COLUMN_PENDING_REMOVAL),
new String[]{String.valueOf(setId), "1"});
db.setTransactionSuccessful(); db.setTransactionSuccessful();
} catch (SQLiteException e) { } catch (SQLiteException e) {
ret = -1;
//TODO write to log here //TODO write to log here
} catch (Exception e) { } catch (Exception e) {
ret = -1;
//TODO write to log here //TODO write to log here
} finally { } finally {
if (db != null) { if (db != null) {
@ -781,12 +1030,14 @@ public class DAO {
SQLiteDatabase db = null; SQLiteDatabase db = null;
ContentValues values; ContentValues values;
Set set; Set set;
Item item;
try { try {
db = getWriteDB(); db = getWriteDB();
db.beginTransaction(); db.beginTransaction();
item = readItem(db, setId, itemId);
values = new ContentValues(); values = new ContentValues();
values.put(Db.SetItemsTable.COLUMN_PACKED, pack); values.put(Db.SetItemsTable.COLUMN_PACKED, pack);
values.put(Db.SetItemsTable.COLUMN_PENDING_REMOVAL, 0);
ret = db.update(Db.SetItemsTable.TABLE_NAME, values, String.format("%s = ? AND %s = ?", ret = db.update(Db.SetItemsTable.TABLE_NAME, values, String.format("%s = ? AND %s = ?",
Db.SetItemsTable.COLUMN_SET, Db.SetItemsTable.COLUMN_ITEM ), Db.SetItemsTable.COLUMN_SET, Db.SetItemsTable.COLUMN_ITEM ),
new String[]{String.valueOf(setId), String.valueOf(itemId)}); new String[]{String.valueOf(setId), String.valueOf(itemId)});
@ -794,7 +1045,18 @@ public class DAO {
set = readSet(db, setId); set = readSet(db, setId);
if (set != null) { if (set != null) {
values = new ContentValues(); values = new ContentValues();
values.put(Db.SetsTable.COLUMN_PACKED_QTY, pack ? set.getPackedQty() + 1 : set.getPackedQty() - 1); if (pack) {
values.put(Db.SetsTable.COLUMN_PACKED_QTY, set.getPackedQty() + 1);
if (item.isPendingRemoval())
values.put(Db.SetsTable.COLUMN_ACTIVE_QTY, set.getActiveQty()+1 );
} else {
if (!item.isPendingRemoval()) {
values.put(Db.SetsTable.COLUMN_PACKED_QTY, set.getPackedQty() - 1);
} else {
values.put(Db.SetsTable.COLUMN_ACTIVE_QTY, set.getActiveQty()+1);
}
}
ret += db.update(Db.SetsTable.TABLE_NAME, values, String.format("%s = ?", ret += db.update(Db.SetsTable.TABLE_NAME, values, String.format("%s = ?",
Db.SetsTable.COLUMN_ID), Db.SetsTable.COLUMN_ID),
new String[]{String.valueOf(setId)}); new String[]{String.valueOf(setId)});
@ -825,6 +1087,7 @@ public class DAO {
values = new ContentValues(); values = new ContentValues();
values.put(Db.SetItemsTable.COLUMN_PACKED, false); values.put(Db.SetItemsTable.COLUMN_PACKED, false);
values.put(Db.SetItemsTable.COLUMN_DELETED, false); values.put(Db.SetItemsTable.COLUMN_DELETED, false);
values.put(Db.SetItemsTable.COLUMN_PENDING_REMOVAL, false);
ret = db.update(Db.SetItemsTable.TABLE_NAME, ret = db.update(Db.SetItemsTable.TABLE_NAME,
values, values,
String.format("%s = ?", String.format("%s = ?",
@ -1027,6 +1290,16 @@ public class DAO {
Message message = Message.obtain(); Message message = Message.obtain();
switch (currentCommand) { switch (currentCommand) {
case Command.ITEM_READ:
message.obj = readItem(setId, itemId);
if (message.obj != null)
message.what = Event.ITEM_READ_COMPLETED;
else
message.what = Event.ITEM_READ_ERROR;
message.arg1 = setId;
message.arg2 = itemId;
break;
case Command.ITEM_DELETE_FROM_SET : case Command.ITEM_DELETE_FROM_SET :
message.arg1 = updateSetItemDeleted(setId, itemId, true); message.arg1 = updateSetItemDeleted(setId, itemId, true);
if (message.arg1 > 0) if (message.arg1 > 0)
@ -1035,6 +1308,26 @@ public class DAO {
message.what = Event.ITEM_FROM_SET_ERROR; message.what = Event.ITEM_FROM_SET_ERROR;
break; break;
case Command.ITEM_PENDING_REMOVAL:
message.arg1 = updateSetItemPendingRemoval(setId, itemId, true);
if (message.arg1 > 0)
message.what = Event.ITEM_PENDING_REMOVAL_COMPLETED;
else
message.what = Event.ITEM_PENDING_REMOVAL_ERROR;
message.arg1 = setId;
message.arg2 = itemId;
break;
case Command.ITEM_REMOVAL_CANCEL:
message.arg1 = updateSetItemPendingRemoval(setId, itemId, false);
if (message.arg1 > 0)
message.what = Event.ITEM_REMOVAL_CANCELED;
else
message.what = Event.ITEM_REMOVAL_CANCEL_ERROR;
message.arg1 = setId;
message.arg2 = itemId;
break;
case Command.ITEM_INSERT : case Command.ITEM_INSERT :
if (insertItem(item) > 0) { if (insertItem(item) > 0) {
insertSetItem(setId, item.getId(), item.isUserDefined()); insertSetItem(setId, item.getId(), item.isUserDefined());
@ -1052,6 +1345,8 @@ public class DAO {
message.what = Event.ITEM_PACKED; message.what = Event.ITEM_PACKED;
else else
message.what = Event.ITEM_PACK_ERROR; message.what = Event.ITEM_PACK_ERROR;
message.arg1 = setId;
message.arg2 = itemId;
break; break;
case Command.ITEM_UNPACK : case Command.ITEM_UNPACK :
@ -1060,6 +1355,8 @@ public class DAO {
message.what = Event.ITEM_UNPACKED; message.what = Event.ITEM_UNPACKED;
else else
message.what = Event.ITEM_UNPACK_ERROR; message.what = Event.ITEM_UNPACK_ERROR;
message.arg1 = setId;
message.arg2 = itemId;
break; break;
case Command.ITEM_GET_CATEGORIES : case Command.ITEM_GET_CATEGORIES :
@ -1164,6 +1461,21 @@ public class DAO {
else else
message.what = Event.SET_RESTORE_ERROR; message.what = Event.SET_RESTORE_ERROR;
break; break;
case Command.SET_GET_STAT:
Set set = readSet(setId);
message.arg1 = set.getActiveQty();
message.arg2 = set.getPackedQty();
message.what = Event.SET_GET_STAT_COMPLETED;
break;
case Command.SET_CLEAN_PACKED:
message.arg1 = updateSetItemsCleanPacked(setId);
if (message.arg1 > -1)
message.what = Event.SET_PACKED_CLEANED;
else
message.what = Event.SET_CLEAN_PACKED_ERROR;
break;
} }
handler.sendMessage(message); handler.sendMessage(message);
} }

View File

@ -127,8 +127,18 @@ public class Db {
item.setPhotoUrl(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_PHOTO_URL))); item.setPhotoUrl(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_PHOTO_URL)));
item.setPhotoThumbUrl(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_PHOTO_THUMB_URL))); item.setPhotoThumbUrl(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_PHOTO_THUMB_URL)));
item.setPhotoLocal(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_PHOTO_LOCAL))); item.setPhotoLocal(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_PHOTO_LOCAL)));
short ud = cursor.getShort(cursor.getColumnIndexOrThrow(COLUMN_USER_DEFINED)); short buf = cursor.getShort(cursor.getColumnIndexOrThrow(COLUMN_USER_DEFINED));
item.setUserDefined(ud != 0); item.setUserDefined(buf != 0);
int check = cursor.getColumnIndex(SetItemsTable.COLUMN_PENDING_REMOVAL);
if (check != -1) {
buf = cursor.getShort(check);
item.setPendingRemoval(buf != 0);
}
check = cursor.getColumnIndex(SetItemsTable.COLUMN_PACKED);
if (check != -1) {
buf = cursor.getShort(check);
item.setPacked(buf != 0);
}
return item; return item;
} }
@ -258,6 +268,7 @@ public class Db {
public static final String COLUMN_SET = "setId"; public static final String COLUMN_SET = "setId";
public static final String COLUMN_ITEM = "itemId"; public static final String COLUMN_ITEM = "itemId";
public static final String COLUMN_DELETED = "deleted"; public static final String COLUMN_DELETED = "deleted";
public static final String COLUMN_PENDING_REMOVAL = "pending_removal";
public static final String COLUMN_PACKED = "packed"; public static final String COLUMN_PACKED = "packed";
public static final String COLUMN_USER_DEFINED = "user_defined"; public static final String COLUMN_USER_DEFINED = "user_defined";
@ -266,6 +277,7 @@ public class Db {
COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
COLUMN_SET + " INTEGER NOT NULL, " + COLUMN_SET + " INTEGER NOT NULL, " +
COLUMN_DELETED + " NUMERIC, " + COLUMN_DELETED + " NUMERIC, " +
COLUMN_PENDING_REMOVAL + " NUMERIC, " +
COLUMN_PACKED + " NUMERIC, " + COLUMN_PACKED + " NUMERIC, " +
COLUMN_USER_DEFINED + " NUMERIC, " + COLUMN_USER_DEFINED + " NUMERIC, " +
COLUMN_ITEM + " INTEGER NOT NULL" + COLUMN_ITEM + " INTEGER NOT NULL" +
@ -276,6 +288,7 @@ public class Db {
values.put(COLUMN_SET, setId); values.put(COLUMN_SET, setId);
values.put(COLUMN_ITEM, itemId); values.put(COLUMN_ITEM, itemId);
values.put(COLUMN_DELETED, 0); values.put(COLUMN_DELETED, 0);
values.put(COLUMN_PENDING_REMOVAL, 0);
values.put(COLUMN_PACKED, 0); values.put(COLUMN_PACKED, 0);
values.put(COLUMN_USER_DEFINED, 0); values.put(COLUMN_USER_DEFINED, 0);
return values; return values;
@ -286,6 +299,7 @@ public class Db {
values.put(COLUMN_SET, setId); values.put(COLUMN_SET, setId);
values.put(COLUMN_ITEM, itemId); values.put(COLUMN_ITEM, itemId);
values.put(COLUMN_DELETED, 0); values.put(COLUMN_DELETED, 0);
values.put(COLUMN_PENDING_REMOVAL, 0);
values.put(COLUMN_PACKED, 0); values.put(COLUMN_PACKED, 0);
values.put(COLUMN_USER_DEFINED, userDefined); values.put(COLUMN_USER_DEFINED, userDefined);
return values; return values;

View File

@ -15,6 +15,8 @@ public interface Event {
int SET_PACKED_LOAD_ERROR = -0x4; int SET_PACKED_LOAD_ERROR = -0x4;
int SET_UNPACK_ERROR = -0x5; int SET_UNPACK_ERROR = -0x5;
int SET_RESTORE_ERROR = -0x6; int SET_RESTORE_ERROR = -0x6;
int SET_GET_STAT_ERROR = -0x7;
int SET_CLEAN_PACKED_ERROR = -0x8;
int SET_LOAD_COMPLETED = 0x1; int SET_LOAD_COMPLETED = 0x1;
@ -23,7 +25,8 @@ public interface Event {
int SET_PACKED_LOAD_COMPLETED = 0x4; int SET_PACKED_LOAD_COMPLETED = 0x4;
int SET_UNPACK_COMPLETED = 0x5; int SET_UNPACK_COMPLETED = 0x5;
int SET_RESTORE_COMPLETED = 0x6; int SET_RESTORE_COMPLETED = 0x6;
int SET_GET_STAT_COMPLETED = 0x7;
int SET_PACKED_CLEANED = 0x8;
int ITEM_FROM_SET_ERROR = -0x14; int ITEM_FROM_SET_ERROR = -0x14;
int ITEM_INSERT_ERROR = -0x15; int ITEM_INSERT_ERROR = -0x15;
@ -33,6 +36,9 @@ public interface Event {
int ITEM_CATEGORY_LOAD_ERROR = -0x19; int ITEM_CATEGORY_LOAD_ERROR = -0x19;
int ITEM_IMAGE_LOAD_ERROR = -0x1A; int ITEM_IMAGE_LOAD_ERROR = -0x1A;
int ITEM_LIKE_LOAD_ERROR = -0x1B; int ITEM_LIKE_LOAD_ERROR = -0x1B;
int ITEM_PENDING_REMOVAL_ERROR = -0x1C;
int ITEM_REMOVAL_CANCEL_ERROR = -0x1D;
int ITEM_READ_ERROR = -0x1E;
int ITEM_FROM_SET_DELETED = 0x14; int ITEM_FROM_SET_DELETED = 0x14;
int ITEM_INSERTED = 0x15; int ITEM_INSERTED = 0x15;
@ -42,7 +48,9 @@ public interface Event {
int ITEM_CATEGORY_LOAD_COMPLETED = 0x19; int ITEM_CATEGORY_LOAD_COMPLETED = 0x19;
int ITEM_IMAGE_LOAD_COMPLETED = 0x1A; int ITEM_IMAGE_LOAD_COMPLETED = 0x1A;
int ITEM_LIKE_LOAD_COMPLETED = 0x1B; int ITEM_LIKE_LOAD_COMPLETED = 0x1B;
int ITEM_PENDING_REMOVAL_COMPLETED = 0x1C;
int ITEM_REMOVAL_CANCELED = 0x1D;
int ITEM_READ_COMPLETED = 0x1E;
int MY_LIST_POST_ERROR = -0x28; int MY_LIST_POST_ERROR = -0x28;
int MY_LIST_ITEM_ADD_ERROR = -0x29; int MY_LIST_ITEM_ADD_ERROR = -0x29;

View File

@ -38,6 +38,10 @@ public class Item implements Comparable<Item>, Serializable {
private boolean userDefined; private boolean userDefined;
private boolean pendingRemoval;
private boolean packed;
public boolean InList; public boolean InList;
public Item() { public Item() {
@ -132,6 +136,22 @@ public class Item implements Comparable<Item>, Serializable {
this.userDefined = userDefined; this.userDefined = userDefined;
} }
public boolean isPendingRemoval() {
return pendingRemoval;
}
public void setPendingRemoval(boolean pendingRemoval) {
this.pendingRemoval = pendingRemoval;
}
public boolean isPacked() {
return packed;
}
public void setPacked(boolean packed) {
this.packed = packed;
}
@Override @Override
public int hashCode() { public int hashCode() {
int result = name != null ? name.hashCode() : 0; int result = name != null ? name.hashCode() : 0;
@ -154,7 +174,16 @@ public class Item implements Comparable<Item>, Serializable {
@Override @Override
public int compareTo(Item another) { public int compareTo(Item another) {
/*
int cmp = Integer.valueOf(category).compareTo(Integer.valueOf(another.category)); int cmp = Integer.valueOf(category).compareTo(Integer.valueOf(another.category));
return (cmp != 0 ? cmp : name.compareTo(another.name)); return (cmp != 0 ? cmp : name.compareTo(another.name));
*/
int cmp = Integer.valueOf(category).compareTo(Integer.valueOf(another.category));
if (cmp != 0)
return cmp;
else {
cmp = Boolean.valueOf(pendingRemoval).compareTo(Boolean.valueOf(another.pendingRemoval));
return (cmp != 0 ? cmp : name.compareTo(another.name));
}
} }
} }

View File

@ -1,13 +1,20 @@
package com.hikapro.backpack.presenter; package com.hikapro.backpack.presenter;
import android.app.ActionBar;
import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.support.v7.widget.DefaultItemAnimator; import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.webkit.URLUtil;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
@ -16,6 +23,7 @@ import com.hikapro.backpack.R;
import com.hikapro.backpack.model.Model; import com.hikapro.backpack.model.Model;
import com.hikapro.backpack.model.entities.Item; import com.hikapro.backpack.model.entities.Item;
import com.hikapro.backpack.presenter.adapters.ItemDetailAdapter; import com.hikapro.backpack.presenter.adapters.ItemDetailAdapter;
import com.hikapro.backpack.presenter.adapters.helper.items.DividerDecoration;
import com.hikapro.backpack.view.View; import com.hikapro.backpack.view.View;
/** /**
@ -27,6 +35,10 @@ public class ItemDetailPresenter implements Presenter.ItemDetail {
private Model.Detail model; private Model.Detail model;
private ItemDetailAdapter adapter; private ItemDetailAdapter adapter;
private Item item; private Item item;
private int setId;
private ImageView itemPhoto;
private TextView itemDescription;
private TextView itemLink;
public ItemDetailPresenter() { public ItemDetailPresenter() {
this.adapter = new ItemDetailAdapter(this); this.adapter = new ItemDetailAdapter(this);
@ -46,12 +58,33 @@ public class ItemDetailPresenter implements Presenter.ItemDetail {
public android.view.View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public android.view.View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
android.view.View view = inflater.inflate(R.layout.fragment_item_detail, container, false); android.view.View view = inflater.inflate(R.layout.fragment_item_detail, container, false);
itemPhoto = (ImageView) view.findViewById(R.id.item_photo);
itemDescription = (TextView) view.findViewById(R.id.item_description);
itemLink = (TextView) view.findViewById(R.id.item_link);
LinearLayoutManager llm = new LinearLayoutManager(getActivityContext()); LinearLayoutManager llm = new LinearLayoutManager(getActivityContext());
RecyclerView detailRecycler = (RecyclerView) view.findViewById(R.id.item_detail_recycler); RecyclerView detailRecycler = (RecyclerView) view.findViewById(R.id.item_detail_recycler);
detailRecycler.setLayoutManager(llm); detailRecycler.setLayoutManager(llm);
detailRecycler.setAdapter(adapter); detailRecycler.setAdapter(adapter);
detailRecycler.setItemAnimator(new DefaultItemAnimator()); detailRecycler.setItemAnimator(new DefaultItemAnimator());
detailRecycler.addItemDecoration(new DividerDecoration(getActivityContext()));
detailRecycler.setHasFixedSize(true);
model.executeQuery(); model.executeQuery();
Activity activity = (Activity) getActivityContext();
if (activity != null) {
activity.invalidateOptionsMenu();
ActionBar actionBar = activity.getActionBar();
if (actionBar != null) {
actionBar.show();
actionBar.setTitle(R.string.what_is_it);
actionBar.setDisplayShowHomeEnabled(false);
actionBar.setDisplayShowTitleEnabled(true);
actionBar.setDisplayShowCustomEnabled(false);
actionBar.setDisplayHomeAsUpEnabled(true);
}
}
return view; return view;
} }
@Override @Override
@ -65,6 +98,28 @@ public class ItemDetailPresenter implements Presenter.ItemDetail {
@Override @Override
public void notifyDataSetChanged() { public void notifyDataSetChanged() {
adapter.notifyDataSetChanged(); adapter.notifyDataSetChanged();
item = model.findItem(0);
itemDescription.setText(item.getDescription());
if (item.getBuyUrls() != null && !item.getBuyUrls().isEmpty()) {
itemLink.setVisibility(android.view.View.VISIBLE);
itemLink.setOnClickListener(new android.view.View.OnClickListener() {
@Override
public void onClick(android.view.View v) {
if (URLUtil.isValidUrl(item.getBuyUrls().get(0))) {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(item.getBuyUrls().get(0)));
Activity activity = (Activity) getActivityContext();
if (activity != null) {
if (browserIntent.resolveActivity(activity.getPackageManager()) != null)
activity.startActivity(browserIntent);
}
}
}
});
} else {
itemLink.setVisibility(android.view.View.GONE);
itemLink.setOnClickListener(null);
}
} }
// process <-- // process <--
@ -75,6 +130,7 @@ public class ItemDetailPresenter implements Presenter.ItemDetail {
public void setView(View.ItemDetail view) { public void setView(View.ItemDetail view) {
this.view = new WeakReference<>(view); this.view = new WeakReference<>(view);
this.item = getView().getItem(); this.item = getView().getItem();
this.setId = view.getSetId();
} }
@Override @Override
public void setModel(Model.Detail model) { public void setModel(Model.Detail model) {
@ -107,15 +163,10 @@ public class ItemDetailPresenter implements Presenter.ItemDetail {
return null; return null;
} }
} }
@Override
public void showMessage(String message) {
Toast.makeText(getView().getAppContext(), message, Toast.LENGTH_SHORT).show();
}
@Override @Override
public void displayPicture(Bitmap bitmap) { public void notifyPictureChanged() {
itemPhoto.setImageBitmap(model.getPicture());
} }
// other impl <-- // other impl <--
@ -125,4 +176,8 @@ public class ItemDetailPresenter implements Presenter.ItemDetail {
else else
throw new NullPointerException("View is unavailable"); throw new NullPointerException("View is unavailable");
} }
public int getSetId() {
return setId;
}
} }

View File

@ -59,9 +59,10 @@ public class ItemListPresenter implements Presenter.ItemList {
model = null; model = null;
} }
} }
@Override @Override
public android.view.View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public android.view.View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// TODO check nn
if (savedInstanceState != null) if (savedInstanceState != null)
set = (Set) savedInstanceState.getSerializable(BUNDLE_SET_LIST_KEY); set = (Set) savedInstanceState.getSerializable(BUNDLE_SET_LIST_KEY);
else else
@ -81,12 +82,7 @@ public class ItemListPresenter implements Presenter.ItemList {
decoration.invalidateHeaders(); decoration.invalidateHeaders();
} }
}); });
ItemSwipeCallback itemSwipeCallback = new ItemSwipeCallback(0, ItemTouchHelper.LEFT, adapter, getActivityContext()); recycler.setHasFixedSize(true);
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(itemSwipeCallback);
itemTouchHelper.attachToRecyclerView(recycler);
adapter.setUndoOn(true);
model.executeQuery(); model.executeQuery();
footer = (LinearLayout) view.findViewById(R.id.item_list_footer); footer = (LinearLayout) view.findViewById(R.id.item_list_footer);
packedCount = (TextView) footer.findViewById(R.id.footer_packed_count); packedCount = (TextView) footer.findViewById(R.id.footer_packed_count);
@ -110,15 +106,7 @@ public class ItemListPresenter implements Presenter.ItemList {
actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setDisplayHomeAsUpEnabled(true);
} }
} }
/*
if ( model.getPackedQty() > 0) {
footer.setVisibility(android.view.View.VISIBLE);
String str = String.format("%s %d / %d",
getActivityContext().getResources().getString(R.string.packed), model.getPackedQty(),
model.getActiveItemsCount());
packedCount.setText(str);
}
*/
return view; return view;
} }
@Override @Override
@ -172,7 +160,7 @@ public class ItemListPresenter implements Presenter.ItemList {
public void showDetails(int itemId) { public void showDetails(int itemId) {
Item item = model.findItem(itemId); Item item = model.findItem(itemId);
if (item != null) if (item != null)
getView().showItemDetail(item); getView().showItemDetail(item, set.getId());
else else
showMessage(String.format("Item with Id %d is not found.", itemId)); showMessage(String.format("Item with Id %d is not found.", itemId));

View File

@ -56,18 +56,14 @@ public class PackedListPresenter extends ItemListPresenter {
decoration.invalidateHeaders(); decoration.invalidateHeaders();
} }
}); });
ItemSwipeCallback itemSwipeCallback = new ItemSwipeCallback(0, ItemTouchHelper.LEFT, adapter, getActivityContext()); recycler.setHasFixedSize(true);
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(itemSwipeCallback);
itemTouchHelper.attachToRecyclerView(recycler);
adapter.setUndoOn(true);
model.executeQuery(); model.executeQuery();
backToList = (TextView) view.findViewById(R.id.back_to_list); backToList = (TextView) view.findViewById(R.id.back_to_list);
packedCount = (TextView) view.findViewById(R.id.header_packed_count); packedCount = (TextView) view.findViewById(R.id.header_packed_count);
unpackButton = (Button) view.findViewById(R.id.unpack_button); unpackButton = (Button) view.findViewById(R.id.unpack_button);
/*
if (model.getPackedQty() == model.getActiveItemsCount()) { if (model.getPackedQty() == model.getActiveItemsCount()) {
backToList.setVisibility(View.INVISIBLE); backToList.setVisibility(View.INVISIBLE);
packedCount.setVisibility(View.INVISIBLE); packedCount.setVisibility(View.INVISIBLE);
@ -78,7 +74,8 @@ public class PackedListPresenter extends ItemListPresenter {
unpackButton.setVisibility(View.INVISIBLE); unpackButton.setVisibility(View.INVISIBLE);
} }
*/
setVisibility();
unpackButton.setOnClickListener(new View.OnClickListener() { unpackButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
@ -95,12 +92,7 @@ public class PackedListPresenter extends ItemListPresenter {
} }
}); });
/*
String str = String.format("%s %d / %d",
getActivityContext().getResources().getString(R.string.packed),
model.getPackedQty(), model.getActiveItemsCount());
packedCount.setText(str);
*/
Activity activity = (Activity) getActivityContext(); Activity activity = (Activity) getActivityContext();
if (activity != null) { if (activity != null) {
activity.invalidateOptionsMenu(); activity.invalidateOptionsMenu();

View File

@ -67,12 +67,12 @@ public interface Presenter {
void setModel(Model.Detail model); void setModel(Model.Detail model);
Model.Detail getModel(); Model.Detail getModel();
void notifyDataSetChanged(); void notifyDataSetChanged();
void showMessage(String message); void notifyPictureChanged();
void onDestroy(boolean isChangingConfiguration); void onDestroy(boolean isChangingConfiguration);
android.view.View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState); android.view.View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState);
void onSaveInstanceState(Bundle outState); void onSaveInstanceState(Bundle outState);
Item getCurrentItem(); Item getCurrentItem();
void displayPicture(Bitmap bitmap); int getSetId();
} }
interface Share extends Base { interface Share extends Base {

View File

@ -1,22 +1,36 @@
package com.hikapro.backpack.presenter.adapters; package com.hikapro.backpack.presenter.adapters;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.Toast;
import com.hikapro.backpack.R; import com.hikapro.backpack.R;
import com.hikapro.backpack.model.entities.Item;
import com.hikapro.backpack.presenter.Presenter; import com.hikapro.backpack.presenter.Presenter;
import com.hikapro.backpack.presenter.adapters.helper.Util;
import com.hikapro.backpack.presenter.adapters.helper.items.swipe2.SwipableElement;
import com.hikapro.backpack.presenter.adapters.helper.items.swipe2.SwipeMenu;
import com.hikapro.backpack.presenter.adapters.helper.items.swipe2.SwipeMenuItem;
import com.hikapro.backpack.presenter.adapters.helper.items.swipe2.SwipeMenuLayout;
import com.hikapro.backpack.view.recycler.DetailViewHolder; import com.hikapro.backpack.view.recycler.DetailViewHolder;
import com.hikapro.backpack.view.recycler.ItemViewHolder;
/** /**
* Created by tariel on 23/04/16. * Created by tariel on 23/04/16.
*/ */
public class ItemDetailAdapter extends RecyclerView.Adapter<DetailViewHolder> { public class ItemDetailAdapter extends RecyclerView.Adapter<ItemViewHolder> {
private Presenter.ItemDetail presenter; private Presenter.ItemDetail presenter;
public ItemDetailAdapter(Presenter.ItemDetail presenter) { public ItemDetailAdapter(Presenter.ItemDetail presenter) {
this.presenter = presenter; this.presenter = presenter;
} }
@ -26,29 +40,143 @@ public class ItemDetailAdapter extends RecyclerView.Adapter<DetailViewHolder> {
} }
@Override @Override
public void onBindViewHolder(DetailViewHolder holder, int position) { public void onBindViewHolder(final ItemViewHolder holder, final int position) {
com.hikapro.backpack.model.entities.Item item = presenter.getModel().findItem(position); final Item item = presenter.getModel().findItem(position);
holder.title.setText(item.getName()); holder.cb_item.setChecked(item.isPacked());
holder.description.setText(item.getDescription()); holder.tv_text.setText(item.getName() + " " + item.getId() + " pos " + position);
Bitmap bitmap = presenter.getModel().getPicture(); holder.im_info.setVisibility(View.GONE);
if (bitmap != null) if (item.isPendingRemoval()) {
holder.photo.setImageBitmap(bitmap); holder.tv_text.setPaintFlags(holder.tv_text.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
holder.title.setOnClickListener(new android.view.View.OnClickListener() { holder.cb_item.setVisibility(View.GONE);
} else {
holder.cb_item.setVisibility(View.VISIBLE);
holder.tv_text.setPaintFlags(holder.tv_text.getPaintFlags() & ~Paint.STRIKE_THRU_TEXT_FLAG);
}
holder.cb_item.setOnClickListener(new android.view.View.OnClickListener() {
@Override @Override
public void onClick(android.view.View view) { public void onClick(View v) {
presenter.showMessage("On detail click"); if (holder.cb_item.isChecked()) {
pack(item);
} else {
unpack(item);
}
}
});
SwipeMenuLayout menuLayout = (SwipeMenuLayout)holder.menu;
SwipeMenu menu = new SwipeMenu(presenter.getActivityContext());
menuLayout.removeAllViews();
// create menu items here
if (!item.isPendingRemoval()) {
// create "leave at home" item
SwipeMenuItem leaveAtHomeItem = new SwipeMenuItem(menu.getContext());
// set id
leaveAtHomeItem.setId(ItemListAdapter.ID_LEAVE_AT_HOME);
// set item background
leaveAtHomeItem.setBackground(R.color.colorLeaveAtHomeBtnBackground);
// set item width
leaveAtHomeItem.setWidth(Util.dp2px(presenter.getActivityContext(), 120));
// set item title
leaveAtHomeItem.setTitle(R.string.leave_at_home_button);
// set item title font size
leaveAtHomeItem.setTitleSize(14);
// set item title font color
leaveAtHomeItem.setTitleColor(Color.WHITE);
// add to menu
menu.addMenuItem(leaveAtHomeItem);
} else {
// create "add to bag" item
SwipeMenuItem addToBagItem = new SwipeMenuItem(menu.getContext());
// set id
addToBagItem.setId(ItemListAdapter.ID_ADD_TO_BAG);
// set item background
addToBagItem.setBackground(R.color.colorAddToBagBtnBackground);
// set item width
addToBagItem.setWidth(Util.dp2px(presenter.getActivityContext(), 120));
// set item title
addToBagItem.setTitle(R.string.add_to_bag_button);
// set item title font size
addToBagItem.setTitleSize(14);
// set item title font color
addToBagItem.setTitleColor(Color.WHITE);
// add to menu
menu.addMenuItem(addToBagItem);
// create "return to list" item
SwipeMenuItem returnToListItem = new SwipeMenuItem(menu.getContext());
// set id
returnToListItem.setId(ItemListAdapter.ID_RETURN_TO_LIST);
// set item background
returnToListItem.setBackground(R.color.colorReturnToListBtnBackground);
// set item width
returnToListItem.setWidth(Util.dp2px(presenter.getActivityContext(), 120));
// set item title
returnToListItem.setTitle(R.string.return_to_list_button);
// set item title font size
returnToListItem.setTitleSize(14);
// set item title font color
returnToListItem.setTitleColor(Color.WHITE);
// add to menu
menu.addMenuItem(returnToListItem);
}
menuLayout.addMenu(menu);
menuLayout.setMenuItemClickListener(new SwipeMenuLayout.OnMenuItemClickListener() {
@Override
public void onMenuItemClick(View v) {
switch (v.getId()) {
case ItemListAdapter.ID_DELETE:
// no delete
break;
case ItemListAdapter.ID_LEAVE_AT_HOME:
leave(item);
break;
case ItemListAdapter.ID_RETURN_TO_LIST:
leaveCancel(item);
break;
case ItemListAdapter.ID_ADD_TO_BAG:
pack(item);
break;
}
} }
}); });
} }
@Override @Override
public DetailViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
DetailViewHolder viewHolder; ItemViewHolder viewHolder;
android.view.View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_detail, View content = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_element, parent, false);
parent, false); SwipeMenuLayout menu = new SwipeMenuLayout(parent.getContext());
viewHolder = new DetailViewHolder(v); menu.setId(R.id.menu);
SwipableElement container = new SwipableElement(parent.getContext(), content, menu);
container.setSwipeDirection(SwipableElement.DIRECTION_LEFT);
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, Util.dp2px(parent.getContext(),66));
container.setOrientation(LinearLayout.HORIZONTAL);
container.setLayoutParams(params);
viewHolder = new ItemViewHolder(container);
return viewHolder; return viewHolder;
} }
public void leave(Item item) {
presenter.getModel().pendingRemove(item);
}
public void pack(Item item) {
presenter.getModel().packItem(item);
}
public void unpack(Item item) {
presenter.getModel().unpackItem(item);
}
public void leaveCancel(Item item) {
presenter.getModel().pendingRemoveCancel(item);
}
} }

View File

@ -1,12 +1,16 @@
package com.hikapro.backpack.presenter.adapters; package com.hikapro.backpack.presenter.adapters;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface; import android.graphics.Typeface;
import android.graphics.drawable.ColorDrawable;
import android.os.Handler; import android.os.Handler;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.Toast;
import java.util.HashMap; import java.util.HashMap;
@ -14,7 +18,12 @@ import com.hikapro.backpack.R;
import com.hikapro.backpack.model.entities.Category; import com.hikapro.backpack.model.entities.Category;
import com.hikapro.backpack.model.entities.Item; import com.hikapro.backpack.model.entities.Item;
import com.hikapro.backpack.presenter.Presenter; import com.hikapro.backpack.presenter.Presenter;
import com.hikapro.backpack.presenter.adapters.helper.Util;
import com.hikapro.backpack.presenter.adapters.helper.items.StickyHeaderAdapter; import com.hikapro.backpack.presenter.adapters.helper.items.StickyHeaderAdapter;
import com.hikapro.backpack.presenter.adapters.helper.items.swipe2.SwipableElement;
import com.hikapro.backpack.presenter.adapters.helper.items.swipe2.SwipeMenu;
import com.hikapro.backpack.presenter.adapters.helper.items.swipe2.SwipeMenuItem;
import com.hikapro.backpack.presenter.adapters.helper.items.swipe2.SwipeMenuLayout;
import com.hikapro.backpack.view.recycler.HeaderViewHolder; import com.hikapro.backpack.view.recycler.HeaderViewHolder;
import com.hikapro.backpack.view.recycler.ItemViewHolder; import com.hikapro.backpack.view.recycler.ItemViewHolder;
@ -23,14 +32,14 @@ import com.hikapro.backpack.view.recycler.ItemViewHolder;
*/ */
public class ItemListAdapter extends RecyclerView.Adapter<ItemViewHolder> implements StickyHeaderAdapter<HeaderViewHolder> { public class ItemListAdapter extends RecyclerView.Adapter<ItemViewHolder> implements StickyHeaderAdapter<HeaderViewHolder> {
private static final int PENDING_REMOVAL_TIMEOUT = 4000; // 4sec protected static final int ID_DELETE = 1;
protected static final int ID_LEAVE_AT_HOME = 2;
protected static final int ID_ADD_TO_BAG = 3;
protected static final int ID_RETURN_TO_LIST = 4;
boolean undoOn; // is undo on, you can turn it on from the toolbar menu protected Presenter.ItemList presenter;
private Handler handler = new Handler(); // hanlder for running delayed runnables protected boolean checkAll;
HashMap<Item, Runnable> pendingRunables = new HashMap<>(); // map of items to pending runnables, so we can cancel a removal if need be protected Typeface mainFace;
private Presenter.ItemList presenter;
private boolean checkAll;
private Typeface mainFace;
public ItemListAdapter(Presenter.ItemList presenter) { public ItemListAdapter(Presenter.ItemList presenter) {
this.presenter = presenter; this.presenter = presenter;
@ -52,87 +61,151 @@ public class ItemListAdapter extends RecyclerView.Adapter<ItemViewHolder> implem
public void onBindViewHolder(final ItemViewHolder holder, final int position) { public void onBindViewHolder(final ItemViewHolder holder, final int position) {
final Item item = presenter.getModel().getItemByPosition(position); final Item item = presenter.getModel().getItemByPosition(position);
if (presenter.getModel().isPendingRemoval(item)) { holder.cb_item.setChecked(checkAll);
// we need to show the "undo" state of the row holder.tv_text.setText(item.getName() + " " + item.getId() + " pos " + position);
holder.itemView.setBackgroundColor(Color.RED); //holder.tv_text.setTypeface(mainFace);
holder.checkBox.setVisibility(View.GONE); if (item.isPendingRemoval()) {
holder.swipeGroup.setVisibility(View.VISIBLE); holder.tv_text.setPaintFlags(holder.tv_text.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
holder.deleteButton.setOnClickListener(new View.OnClickListener() { holder.cb_item.setVisibility(View.GONE);
@Override
public void onClick(View v) {
// user wants to undo the removal, let's cancel the pending task
Runnable pendingRemovalRunnable = pendingRunables.get(item);
pendingRunables.remove(item);
if (pendingRemovalRunnable != null) handler.removeCallbacks(pendingRemovalRunnable);
presenter.getModel().pendingRemoveCancel(item);
// this will rebind the row in "normal" state
notifyItemChanged(position);
}
});
} else { } else {
/* holder.cb_item.setVisibility(View.VISIBLE);
if (mainFace == null) holder.tv_text.setPaintFlags(holder.tv_text.getPaintFlags() & ~Paint.STRIKE_THRU_TEXT_FLAG);
mainFace = Typeface.createFromAsset(presenter.getAppContext().getAssets(), }
"fonts/Ubuntu-B.ttf");*/
holder.checkBox.setVisibility(View.VISIBLE); holder.cb_item.setOnClickListener(new android.view.View.OnClickListener() {
holder.checkBox.setChecked(checkAll);
holder.checkBox.setText(item.getName() + " " + item.getId() + " pos " + position);//TODO del
holder.checkBox.setTypeface(mainFace);
holder.swipeGroup.setVisibility(View.GONE);
holder.id = item.getId();
holder.checkBox.setOnClickListener(new android.view.View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
if (holder.checkBox.isChecked()) { if (holder.cb_item.isChecked()) {
pack(holder.id, position); pack(item);
// presenter.packItem(); TODO wtf
} else { } else {
unpack(holder.id, position); unpack(item);
// presenter.unpackItem(); TODO wtf
} }
} }
}); });
holder.infoButton.setOnClickListener(new View.OnClickListener() { holder.im_info.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
presenter.showDetails(holder.id); presenter.showDetails(item.getId());
} }
}); });
holder.itemView.setBackgroundColor(0x33FF99);
holder.deleteButton.setOnClickListener(null); SwipeMenuLayout menuLayout = (SwipeMenuLayout)holder.menu;
SwipeMenu menu = new SwipeMenu(presenter.getActivityContext());
menuLayout.removeAllViews();
// create menu items here
if (!item.isPendingRemoval()) {
// create "leave at home" item
SwipeMenuItem leaveAtHomeItem = new SwipeMenuItem(menu.getContext());
// set id
leaveAtHomeItem.setId(ID_LEAVE_AT_HOME);
// set item background
leaveAtHomeItem.setBackground(R.color.colorLeaveAtHomeBtnBackground);
// set item width
leaveAtHomeItem.setWidth(Util.dp2px(presenter.getActivityContext(), 120));
// set item title
leaveAtHomeItem.setTitle(R.string.leave_at_home_button);
// set item title font size
leaveAtHomeItem.setTitleSize(14);
// set item title font color
leaveAtHomeItem.setTitleColor(Color.WHITE);
// add to menu
menu.addMenuItem(leaveAtHomeItem);
} else {
// create "add to bag" item
SwipeMenuItem addToBagItem = new SwipeMenuItem(menu.getContext());
// set id
addToBagItem.setId(ID_ADD_TO_BAG);
// set item background
addToBagItem.setBackground(R.color.colorAddToBagBtnBackground);
// set item width
addToBagItem.setWidth(Util.dp2px(presenter.getActivityContext(), 120));
// set item title
addToBagItem.setTitle(R.string.add_to_bag_button);
// set item title font size
addToBagItem.setTitleSize(14);
// set item title font color
addToBagItem.setTitleColor(Color.WHITE);
// add to menu
menu.addMenuItem(addToBagItem);
// create "return to list" item
SwipeMenuItem returnToListItem = new SwipeMenuItem(menu.getContext());
// set id
returnToListItem.setId(ID_RETURN_TO_LIST);
// set item background
returnToListItem.setBackground(R.color.colorReturnToListBtnBackground);
// set item width
returnToListItem.setWidth(Util.dp2px(presenter.getActivityContext(), 120));
// set item title
returnToListItem.setTitle(R.string.return_to_list_button);
// set item title font size
returnToListItem.setTitleSize(14);
// set item title font color
returnToListItem.setTitleColor(Color.WHITE);
// add to menu
menu.addMenuItem(returnToListItem);
} }
// create "delete" item
SwipeMenuItem deleteItem = new SwipeMenuItem(menu.getContext());
// set id
deleteItem.setId(ID_DELETE);
// set item background
deleteItem.setBackground(R.color.colorDeleteBtnBackground);
// set item width
deleteItem.setWidth(Util.dp2px(presenter.getActivityContext(),120));
// set item title
deleteItem.setTitle(R.string.delete_button);
// set item title font size
deleteItem.setTitleSize(14);
// set item title font color
deleteItem.setTitleColor(Color.WHITE);
// add to menu
menu.addMenuItem(deleteItem);
menuLayout.addMenu(menu);
menuLayout.setMenuItemClickListener(new SwipeMenuLayout.OnMenuItemClickListener() {
@Override
public void onMenuItemClick(View v) {
switch (v.getId()) {
case ID_DELETE:
remove(item);
break;
case ID_LEAVE_AT_HOME:
leave(item);
break;
case ID_RETURN_TO_LIST:
leaveCancel(item);
break;
case ID_ADD_TO_BAG:
pack(item);
break;
}
}
});
} }
@Override @Override
public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
ItemViewHolder viewHolder; ItemViewHolder viewHolder;
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_item, View content = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_element, parent, false);
parent, false); SwipeMenuLayout menu = new SwipeMenuLayout(parent.getContext());
viewHolder = new ItemViewHolder(v); menu.setId(R.id.menu);
SwipableElement container = new SwipableElement(parent.getContext(), content, menu);
container.setSwipeDirection(SwipableElement.DIRECTION_LEFT);
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, Util.dp2px(parent.getContext(),66));
container.setOrientation(LinearLayout.HORIZONTAL);
container.setLayoutParams(params);
viewHolder = new ItemViewHolder(container);
return viewHolder; return viewHolder;
} }
public void setUndoOn(boolean undoOn) {
this.undoOn = undoOn;
}
public boolean isUndoOn() {
return undoOn;
}
public void add(Item item) {
presenter.getModel().insertItem(item);
notifyDataSetChanged();
}
public void clear() {
presenter.getModel().clear();
notifyDataSetChanged();
}
public void filter(String query) { public void filter(String query) {
presenter.getModel().filter(query); presenter.getModel().filter(query);
notifyDataSetChanged(); notifyDataSetChanged();
@ -164,58 +237,31 @@ public class ItemListAdapter extends RecyclerView.Adapter<ItemViewHolder> implem
holder.title.setBackgroundColor(0x2B1E15); holder.title.setBackgroundColor(0x2B1E15);
} }
public void pendingRemoval(final int position) { public void leave(Item item) {
final Item item = presenter.getModel().getItemByPosition(position);
if (! presenter.getModel().isPendingRemoval(item)) {
presenter.getModel().pendingRemove(item); presenter.getModel().pendingRemove(item);
// this will redraw row in "undo" state
notifyItemChanged(position);
// let's create, store and post a runnable to remove the item
Runnable pendingRemovalRunnable = new Runnable() {
@Override
public void run() {
remove(item, position);
}
};
handler.postDelayed(pendingRemovalRunnable, PENDING_REMOVAL_TIMEOUT);
pendingRunables.put(item, pendingRemovalRunnable);
}
} }
public void remove(Item item, int position) { public void leaveCancel(Item item) {
presenter.getModel().deleteItem(item); presenter.getModel().pendingRemoveCancel(item);
notifyItemRemoved(position);
} }
public void remove(int position) { public void remove(Item item) {
Item item = presenter.getModel().getItemByPosition(position); presenter.getModel().remove(item);
presenter.getModel().deleteItem(item);
notifyItemRemoved(position);
} }
public boolean isPendingRemoval(int position) { public void pack(Item item) {
Item item = presenter.getModel().getItemByPosition(position); presenter.getModel().packItem(item);
return presenter.getModel().isPendingRemoval(item); //notifyDataSetChanged(); // TODO check nn
}
public void pack(int itemId, int position) {
presenter.getModel().packItem(itemId);
notifyDataSetChanged();
/* /*
notifyItemRemoved(position); notifyItemRemoved(position);
notifyItemRangeRemoved(position, getItemCount()); notifyItemRangeRemoved(position, getItemCount());
*/ */
} }
public void unpack(int itemId, int position) { public void unpack(Item item) {
presenter.getModel().unpackItem(itemId); presenter.getModel().unpackItem(item);
//notifyItemRemoved(position); //notifyItemRemoved(position);
notifyDataSetChanged(); //notifyDataSetChanged(); // TODO check nn
}
public void unpackAll() {
} }
public void setCheckAll(boolean checkAll) { public void setCheckAll(boolean checkAll) {

View File

@ -1,6 +1,18 @@
package com.hikapro.backpack.presenter.adapters; package com.hikapro.backpack.presenter.adapters;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.View;
import android.widget.Toast;
import com.hikapro.backpack.R;
import com.hikapro.backpack.model.entities.Item;
import com.hikapro.backpack.presenter.Presenter; import com.hikapro.backpack.presenter.Presenter;
import com.hikapro.backpack.presenter.adapters.helper.Util;
import com.hikapro.backpack.presenter.adapters.helper.items.swipe2.SwipeMenu;
import com.hikapro.backpack.presenter.adapters.helper.items.swipe2.SwipeMenuItem;
import com.hikapro.backpack.presenter.adapters.helper.items.swipe2.SwipeMenuLayout;
import com.hikapro.backpack.view.recycler.ItemViewHolder;
/** /**
* Created by tariel on 12/05/16. * Created by tariel on 12/05/16.
@ -10,4 +22,151 @@ public class PackedListAdapter extends ItemListAdapter {
public PackedListAdapter(Presenter.ItemList presenter) { public PackedListAdapter(Presenter.ItemList presenter) {
super(presenter); super(presenter);
} }
@Override
public void onBindViewHolder(final ItemViewHolder holder, final int position) {
final Item item = presenter.getModel().getItemByPosition(position);
holder.cb_item.setChecked(checkAll);
holder.tv_text.setText(item.getName() + " " + item.getId() + " pos " + position);
if (item.isPendingRemoval()) {
holder.tv_text.setPaintFlags(holder.tv_text.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
holder.cb_item.setVisibility(View.GONE);
} else {
holder.cb_item.setVisibility(View.VISIBLE);
holder.tv_text.setPaintFlags(holder.tv_text.getPaintFlags() & ~Paint.STRIKE_THRU_TEXT_FLAG);
}
holder.cb_item.setOnClickListener(new android.view.View.OnClickListener() {
@Override
public void onClick(View v) {
if (holder.cb_item.isChecked()) {
pack(item);
} else {
unpack(item);
}
}
});
holder.im_info.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
presenter.showDetails(item.getId());
}
});
SwipeMenuLayout menuLayout = (SwipeMenuLayout)holder.menu;
SwipeMenu menu = new SwipeMenu(presenter.getActivityContext());
menuLayout.removeAllViews();
// create menu items here
if (!item.isPendingRemoval()) {
// create "leave at home" item
SwipeMenuItem leaveAtHomeItem = new SwipeMenuItem(menu.getContext());
// set id
leaveAtHomeItem.setId(ID_LEAVE_AT_HOME);
// set item background
leaveAtHomeItem.setBackground(R.color.colorLeaveAtHomeBtnBackground);
// set item width
leaveAtHomeItem.setWidth(Util.dp2px(presenter.getActivityContext(), 120));
// set item title
leaveAtHomeItem.setTitle(R.string.leave_at_home_button);
// set item title font size
leaveAtHomeItem.setTitleSize(14);
// set item title font color
leaveAtHomeItem.setTitleColor(Color.WHITE);
// add to menu
menu.addMenuItem(leaveAtHomeItem);
} else {
// create "add to bag" item
SwipeMenuItem addToBagItem = new SwipeMenuItem(menu.getContext());
// set id
addToBagItem.setId(ID_ADD_TO_BAG);
// set item background
addToBagItem.setBackground(R.color.colorAddToBagBtnBackground);
// set item width
addToBagItem.setWidth(Util.dp2px(presenter.getActivityContext(), 120));
// set item title
addToBagItem.setTitle(R.string.add_to_bag_button);
// set item title font size
addToBagItem.setTitleSize(14);
// set item title font color
addToBagItem.setTitleColor(Color.WHITE);
// add to menu
menu.addMenuItem(addToBagItem);
// create "return to list" item
SwipeMenuItem returnToListItem = new SwipeMenuItem(menu.getContext());
// set id
returnToListItem.setId(ID_RETURN_TO_LIST);
// set item background
returnToListItem.setBackground(R.color.colorReturnToListBtnBackground);
// set item width
returnToListItem.setWidth(Util.dp2px(presenter.getActivityContext(), 120));
// set item title
returnToListItem.setTitle(R.string.return_to_list_button);
// set item title font size
returnToListItem.setTitleSize(14);
// set item title font color
returnToListItem.setTitleColor(Color.WHITE);
// add to menu
menu.addMenuItem(returnToListItem);
}
// create "delete" item
SwipeMenuItem deleteItem = new SwipeMenuItem(menu.getContext());
// set id
deleteItem.setId(ID_DELETE);
// set item background
deleteItem.setBackground(R.color.colorDeleteBtnBackground);
// set item width
deleteItem.setWidth(Util.dp2px(presenter.getActivityContext(),120));
// set item title
deleteItem.setTitle(R.string.delete_button);
// set item title font size
deleteItem.setTitleSize(14);
// set item title font color
deleteItem.setTitleColor(Color.WHITE);
// add to menu
menu.addMenuItem(deleteItem);
menuLayout.addMenu(menu);
menuLayout.setMenuItemClickListener(new SwipeMenuLayout.OnMenuItemClickListener() {
@Override
public void onMenuItemClick(View v) {
switch (v.getId()) {
case ID_DELETE:
remove(item);
break;
case ID_LEAVE_AT_HOME:
leave(item);
break;
case ID_RETURN_TO_LIST:
unpack(item);
break;
case ID_ADD_TO_BAG:
pack(item);
break;
}
}
});
}
@Override
public void remove(Item item) {
if (item.isPendingRemoval()) {
presenter.getModel().unpackItem(item);
presenter.getModel().remove(item);
}
else
presenter.getModel().pendingRemove(item);
}
@Override
public void leave(Item item) {
presenter.getModel().pendingRemove(item);
}
} }

View File

@ -0,0 +1,15 @@
package com.hikapro.backpack.presenter.adapters.helper;
import android.content.Context;
import android.util.TypedValue;
/**
* Created by tariel on 10/07/16.
*/
public class Util {
public static int dp2px(Context context, int dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
context.getResources().getDisplayMetrics());
}
}

View File

@ -52,22 +52,23 @@ public class ItemSwipeCallback extends ItemTouchHelper.SimpleCallback {
@Override @Override
public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
int position = viewHolder.getAdapterPosition(); int position = viewHolder.getAdapterPosition();
/*
if (adapter.isUndoOn() && adapter.isPendingRemoval(position)) { if (adapter.isUndoOn() && adapter.isPendingRemoval(position)) {
return 0; return 0;
} }*/
return super.getSwipeDirs(recyclerView, viewHolder); return super.getSwipeDirs(recyclerView, viewHolder);
} }
@Override @Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) { public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
int swipedPosition = viewHolder.getAdapterPosition(); int swipedPosition = viewHolder.getAdapterPosition();
/*
boolean undoOn = adapter.isUndoOn(); boolean undoOn = adapter.isUndoOn();
if (undoOn) { if (undoOn) {
adapter.pendingRemoval(swipedPosition); adapter.pendingRemoval(swipedPosition);
} else { } else {
adapter.remove(swipedPosition); adapter.remove(swipedPosition);
} }*/
} }
@Override @Override

View File

@ -1,13 +0,0 @@
package com.hikapro.backpack.presenter.adapters.helper.items.swipe;
import android.widget.BaseAdapter;
/**
* Created by tariel on 18/06/16.
*/
public abstract class BaseSwipeListAdapter extends BaseAdapter {
public boolean getSwipeEnableByPosition(int position) {
return true;
}
}

View File

@ -1,144 +0,0 @@
package com.hikapro.backpack.presenter.adapters.helper.items.swipe;
import android.content.Context;
import android.database.DataSetObserver;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListAdapter;
import android.widget.WrapperListAdapter;
/**
* Created by tariel on 18/06/16.
*/
public class SwipeMenuAdapter implements WrapperListAdapter,
SwipeMenuView.OnSwipeItemClickListener {
private ListAdapter mAdapter;
private Context mContext;
private SwipeMenuListView.OnMenuItemClickListener onMenuItemClickListener;
public SwipeMenuAdapter(Context context, ListAdapter adapter) {
mAdapter = adapter;
mContext = context;
}
@Override
public int getCount() {
return mAdapter.getCount();
}
@Override
public Object getItem(int position) {
return mAdapter.getItem(position);
}
@Override
public long getItemId(int position) {
return mAdapter.getItemId(position);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
SwipeMenuLayout layout = null;
if (convertView == null) {
View contentView = mAdapter.getView(position, convertView, parent);
SwipeMenu menu = new SwipeMenu(mContext);
menu.setViewType(getItemViewType(position));
createMenu(menu);
SwipeMenuView menuView = new SwipeMenuView(menu,
(SwipeMenuListView) parent);
menuView.setOnSwipeItemClickListener(this);
SwipeMenuListView listView = (SwipeMenuListView) parent;
layout = new SwipeMenuLayout(contentView, menuView,
listView.getCloseInterpolator(),
listView.getOpenInterpolator());
layout.setPosition(position);
} else {
layout = (SwipeMenuLayout) convertView;
layout.closeMenu();
layout.setPosition(position);
View view = mAdapter.getView(position, layout.getContentView(),
parent);
}
if (mAdapter instanceof BaseSwipeListAdapter) {
boolean swipEnable = (((BaseSwipeListAdapter) mAdapter).getSwipeEnableByPosition(position));
layout.setSwipEnable(swipEnable);
}
return layout;
}
public void createMenu(SwipeMenu menu) {
// Test Code
SwipeMenuItem item = new SwipeMenuItem(mContext);
item.setTitle("Item 1");
item.setBackground(new ColorDrawable(Color.GRAY));
item.setWidth(300);
menu.addMenuItem(item);
item = new SwipeMenuItem(mContext);
item.setTitle("Item 2");
item.setBackground(new ColorDrawable(Color.RED));
item.setWidth(300);
menu.addMenuItem(item);
}
@Override
public void onItemClick(SwipeMenuView view, SwipeMenu menu, int index) {
if (onMenuItemClickListener != null) {
onMenuItemClickListener.onMenuItemClick(view.getPosition(), menu,
index);
}
}
public void setOnSwipeItemClickListener(
SwipeMenuListView.OnMenuItemClickListener onMenuItemClickListener) {
this.onMenuItemClickListener = onMenuItemClickListener;
}
@Override
public void registerDataSetObserver(DataSetObserver observer) {
mAdapter.registerDataSetObserver(observer);
}
@Override
public void unregisterDataSetObserver(DataSetObserver observer) {
mAdapter.unregisterDataSetObserver(observer);
}
@Override
public boolean areAllItemsEnabled() {
return mAdapter.areAllItemsEnabled();
}
@Override
public boolean isEnabled(int position) {
return mAdapter.isEnabled(position);
}
@Override
public boolean hasStableIds() {
return mAdapter.hasStableIds();
}
@Override
public int getItemViewType(int position) {
return mAdapter.getItemViewType(position);
}
@Override
public int getViewTypeCount() {
return mAdapter.getViewTypeCount();
}
@Override
public boolean isEmpty() {
return mAdapter.isEmpty();
}
@Override
public ListAdapter getWrappedAdapter() {
return mAdapter;
}
}

View File

@ -1,8 +0,0 @@
package com.hikapro.backpack.presenter.adapters.helper.items.swipe;
/**
* Created by tariel on 18/06/16.
*/
public interface SwipeMenuCreator {
void create(SwipeMenu menu);
}

View File

@ -1,339 +0,0 @@
package com.hikapro.backpack.presenter.adapters.helper.items.swipe;
import android.content.Context;
import android.support.v4.view.MotionEventCompat;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Interpolator;
import android.widget.ListAdapter;
import android.widget.ListView;
/**
* Created by tariel on 18/06/16.
*/
public class SwipeMenuListView extends ListView {
private static final int TOUCH_STATE_NONE = 0;
private static final int TOUCH_STATE_X = 1;
private static final int TOUCH_STATE_Y = 2;
public static final int DIRECTION_LEFT = 1;
public static final int DIRECTION_RIGHT = -1;
private int mDirection = 1;//swipe from right to left by default
private int MAX_Y = 5;
private int MAX_X = 3;
private float mDownX;
private float mDownY;
private int mTouchState;
private int mTouchPosition;
private SwipeMenuLayout mTouchView;
private OnSwipeListener mOnSwipeListener;
private SwipeMenuCreator mMenuCreator;
private OnMenuItemClickListener mOnMenuItemClickListener;
private OnMenuStateChangeListener mOnMenuStateChangeListener;
private Interpolator mCloseInterpolator;
private Interpolator mOpenInterpolator;
public SwipeMenuListView(Context context) {
super(context);
init();
}
public SwipeMenuListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public SwipeMenuListView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
MAX_X = dp2px(MAX_X);
MAX_Y = dp2px(MAX_Y);
mTouchState = TOUCH_STATE_NONE;
}
@Override
public void setAdapter(ListAdapter adapter) {
super.setAdapter(new SwipeMenuAdapter(getContext(), adapter) {
@Override
public void createMenu(SwipeMenu menu) {
if (mMenuCreator != null) {
mMenuCreator.create(menu);
}
}
@Override
public void onItemClick(SwipeMenuView view, SwipeMenu menu,
int index) {
boolean flag = false;
if (mOnMenuItemClickListener != null) {
flag = mOnMenuItemClickListener.onMenuItemClick(
view.getPosition(), menu, index);
}
if (mTouchView != null && !flag) {
mTouchView.smoothCloseMenu();
}
}
});
}
public void setCloseInterpolator(Interpolator interpolator) {
mCloseInterpolator = interpolator;
}
public void setOpenInterpolator(Interpolator interpolator) {
mOpenInterpolator = interpolator;
}
public Interpolator getOpenInterpolator() {
return mOpenInterpolator;
}
public Interpolator getCloseInterpolator() {
return mCloseInterpolator;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
//在拦截处处理在滑动设置了点击事件的地方也能swip点击时又不能影响原来的点击事件
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
mDownX = ev.getX();
mDownY = ev.getY();
boolean handled = super.onInterceptTouchEvent(ev);
mTouchState = TOUCH_STATE_NONE;
mTouchPosition = pointToPosition((int) ev.getX(), (int) ev.getY());
View view = getChildAt(mTouchPosition - getFirstVisiblePosition());
//只在空的时候赋值 以免每次触摸都赋值会有多个open状态
if (view instanceof SwipeMenuLayout) {
//如果有打开了 就拦截.
if (mTouchView != null && mTouchView.isOpen() && !inRangeOfView(mTouchView.getMenuView(), ev)) {
return true;
}
mTouchView = (SwipeMenuLayout) view;
mTouchView.setSwipeDirection(mDirection);
}
//如果摸在另外个view
if (mTouchView != null && mTouchView.isOpen() && view != mTouchView) {
handled = true;
}
if (mTouchView != null) {
mTouchView.onSwipe(ev);
}
return handled;
case MotionEvent.ACTION_MOVE:
float dy = Math.abs((ev.getY() - mDownY));
float dx = Math.abs((ev.getX() - mDownX));
if (Math.abs(dy) > MAX_Y || Math.abs(dx) > MAX_X) {
//每次拦截的down都把触摸状态设置成了TOUCH_STATE_NONE 只有返回true才会走onTouchEvent 所以写在这里就够了
if (mTouchState == TOUCH_STATE_NONE) {
if (Math.abs(dy) > MAX_Y) {
mTouchState = TOUCH_STATE_Y;
} else if (dx > MAX_X) {
mTouchState = TOUCH_STATE_X;
if (mOnSwipeListener != null) {
mOnSwipeListener.onSwipeStart(mTouchPosition);
}
}
}
return true;
}
}
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (ev.getAction() != MotionEvent.ACTION_DOWN && mTouchView == null)
return super.onTouchEvent(ev);
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
int oldPos = mTouchPosition;
mDownX = ev.getX();
mDownY = ev.getY();
mTouchState = TOUCH_STATE_NONE;
mTouchPosition = pointToPosition((int) ev.getX(), (int) ev.getY());
if (mTouchPosition == oldPos && mTouchView != null
&& mTouchView.isOpen()) {
mTouchState = TOUCH_STATE_X;
mTouchView.onSwipe(ev);
return true;
}
View view = getChildAt(mTouchPosition - getFirstVisiblePosition());
if (mTouchView != null && mTouchView.isOpen()) {
mTouchView.smoothCloseMenu();
mTouchView = null;
// return super.onTouchEvent(ev);
// try to cancel the touch event
MotionEvent cancelEvent = MotionEvent.obtain(ev);
cancelEvent.setAction(MotionEvent.ACTION_CANCEL);
onTouchEvent(cancelEvent);
if (mOnMenuStateChangeListener != null) {
mOnMenuStateChangeListener.onMenuClose(oldPos);
}
return true;
}
if (view instanceof SwipeMenuLayout) {
mTouchView = (SwipeMenuLayout) view;
mTouchView.setSwipeDirection(mDirection);
}
if (mTouchView != null) {
mTouchView.onSwipe(ev);
}
break;
case MotionEvent.ACTION_MOVE:
//有些可能有header,要减去header再判断
mTouchPosition = pointToPosition((int) ev.getX(), (int) ev.getY()) - getHeaderViewsCount();
//如果滑动了一下没完全展现就收回去这时候mTouchView已经赋值再滑动另外一个不可以swip的view
//会导致mTouchView swip 所以要用位置判断是否滑动的是一个view
if (!mTouchView.getSwipEnable() || mTouchPosition != mTouchView.getPosition()) {
break;
}
float dy = Math.abs((ev.getY() - mDownY));
float dx = Math.abs((ev.getX() - mDownX));
if (mTouchState == TOUCH_STATE_X) {
if (mTouchView != null) {
mTouchView.onSwipe(ev);
}
getSelector().setState(new int[]{0});
ev.setAction(MotionEvent.ACTION_CANCEL);
super.onTouchEvent(ev);
return true;
} else if (mTouchState == TOUCH_STATE_NONE) {
if (Math.abs(dy) > MAX_Y) {
mTouchState = TOUCH_STATE_Y;
} else if (dx > MAX_X) {
mTouchState = TOUCH_STATE_X;
if (mOnSwipeListener != null) {
mOnSwipeListener.onSwipeStart(mTouchPosition);
}
}
}
break;
case MotionEvent.ACTION_UP:
if (mTouchState == TOUCH_STATE_X) {
if (mTouchView != null) {
boolean isBeforeOpen = mTouchView.isOpen();
mTouchView.onSwipe(ev);
boolean isAfterOpen = mTouchView.isOpen();
if (isBeforeOpen != isAfterOpen && mOnMenuStateChangeListener != null) {
if (isAfterOpen) {
mOnMenuStateChangeListener.onMenuOpen(mTouchPosition);
} else {
mOnMenuStateChangeListener.onMenuClose(mTouchPosition);
}
}
if (!isAfterOpen) {
mTouchPosition = -1;
mTouchView = null;
}
}
if (mOnSwipeListener != null) {
mOnSwipeListener.onSwipeEnd(mTouchPosition);
}
ev.setAction(MotionEvent.ACTION_CANCEL);
super.onTouchEvent(ev);
return true;
}
break;
}
return super.onTouchEvent(ev);
}
public void smoothOpenMenu(int position) {
if (position >= getFirstVisiblePosition()
&& position <= getLastVisiblePosition()) {
View view = getChildAt(position - getFirstVisiblePosition());
if (view instanceof SwipeMenuLayout) {
mTouchPosition = position;
if (mTouchView != null && mTouchView.isOpen()) {
mTouchView.smoothCloseMenu();
}
mTouchView = (SwipeMenuLayout) view;
mTouchView.setSwipeDirection(mDirection);
mTouchView.smoothOpenMenu();
}
}
}
public void smoothCloseMenu(){
if (mTouchView != null && mTouchView.isOpen()) {
mTouchView.smoothCloseMenu();
}
}
private int dp2px(int dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
getContext().getResources().getDisplayMetrics());
}
public void setMenuCreator(SwipeMenuCreator menuCreator) {
this.mMenuCreator = menuCreator;
}
public void setOnMenuItemClickListener(
OnMenuItemClickListener onMenuItemClickListener) {
this.mOnMenuItemClickListener = onMenuItemClickListener;
}
public void setOnSwipeListener(OnSwipeListener onSwipeListener) {
this.mOnSwipeListener = onSwipeListener;
}
public void setOnMenuStateChangeListener(OnMenuStateChangeListener onMenuStateChangeListener) {
mOnMenuStateChangeListener = onMenuStateChangeListener;
}
public static interface OnMenuItemClickListener {
boolean onMenuItemClick(int position, SwipeMenu menu, int index);
}
public static interface OnSwipeListener {
void onSwipeStart(int position);
void onSwipeEnd(int position);
}
public static interface OnMenuStateChangeListener {
void onMenuOpen(int position);
void onMenuClose(int position);
}
public void setSwipeDirection(int direction) {
mDirection = direction;
}
/**
* 判断点击事件是否在某个view内
*
* @param view
* @param ev
* @return
*/
public static boolean inRangeOfView(View view, MotionEvent ev) {
int[] location = new int[2];
view.getLocationOnScreen(location);
int x = location[0];
int y = location[1];
if (ev.getRawX() < x || ev.getRawX() > (x + view.getWidth()) || ev.getRawY() < y || ev.getRawY() > (y + view.getHeight())) {
return false;
}
return true;
}
}

View File

@ -1,100 +0,0 @@
package com.hikapro.backpack.presenter.adapters.helper.items.swipe;
import java.util.List;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
/**
* Created by tariel on 18/06/16.
*/
public class SwipeMenuView extends LinearLayout implements OnClickListener {
private SwipeMenuListView mListView;
private SwipeMenuLayout mLayout;
private SwipeMenu mMenu;
private OnSwipeItemClickListener onItemClickListener;
private int position;
public int getPosition() {
return position;
}
public void setPosition(int position) {
this.position = position;
}
public SwipeMenuView(SwipeMenu menu, SwipeMenuListView listView) {
super(menu.getContext());
mListView = listView;
mMenu = menu;
List<SwipeMenuItem> items = menu.getMenuItems();
int id = 0;
for (SwipeMenuItem item : items) {
addItem(item, id++);
}
}
private void addItem(SwipeMenuItem item, int id) {
LayoutParams params = new LayoutParams(item.getWidth(),
LayoutParams.MATCH_PARENT);
LinearLayout parent = new LinearLayout(getContext());
parent.setId(id);
parent.setGravity(Gravity.CENTER);
parent.setOrientation(LinearLayout.VERTICAL);
parent.setLayoutParams(params);
parent.setBackgroundDrawable(item.getBackground());
parent.setOnClickListener(this);
addView(parent);
if (item.getIcon() != null) {
parent.addView(createIcon(item));
}
if (!TextUtils.isEmpty(item.getTitle())) {
parent.addView(createTitle(item));
}
}
private ImageView createIcon(SwipeMenuItem item) {
ImageView iv = new ImageView(getContext());
iv.setImageDrawable(item.getIcon());
return iv;
}
private TextView createTitle(SwipeMenuItem item) {
TextView tv = new TextView(getContext());
tv.setText(item.getTitle());
tv.setGravity(Gravity.CENTER);
tv.setTextSize(item.getTitleSize());
tv.setTextColor(item.getTitleColor());
return tv;
}
@Override
public void onClick(View v) {
if (onItemClickListener != null && mLayout.isOpen()) {
onItemClickListener.onItemClick(this, mMenu, v.getId());
}
}
public OnSwipeItemClickListener getOnSwipeItemClickListener() {
return onItemClickListener;
}
public void setOnSwipeItemClickListener(OnSwipeItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
public void setLayout(SwipeMenuLayout mLayout) {
this.mLayout = mLayout;
}
public static interface OnSwipeItemClickListener {
void onItemClick(SwipeMenuView view, SwipeMenu menu, int index);
}
}

View File

@ -1,41 +1,42 @@
package com.hikapro.backpack.presenter.adapters.helper.items.swipe; package com.hikapro.backpack.presenter.adapters.helper.items.swipe2;
import android.content.Context; import android.content.Context;
import android.graphics.Rect;
import android.support.v4.view.GestureDetectorCompat; import android.support.v4.view.GestureDetectorCompat;
import android.support.v4.widget.ScrollerCompat; import android.support.v4.widget.ScrollerCompat;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue; import android.util.TypedValue;
import android.view.GestureDetector.OnGestureListener; import android.view.GestureDetector.OnGestureListener;
import android.view.GestureDetector.SimpleOnGestureListener; import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.view.animation.Interpolator; import android.view.animation.Interpolator;
import android.widget.AbsListView; import android.widget.LinearLayout;
import android.widget.FrameLayout;
/** /**
* Created by tariel on 18/06/16. * Created by tariel on 18/06/16.
*/ */
public class SwipeMenuLayout extends FrameLayout { public class SwipableElement extends LinearLayout {
public static final int DIRECTION_LEFT = 1;
public static final int DIRECTION_RIGHT = -1;
private static final int CONTENT_VIEW_ID = 1; private static final int CONTENT_VIEW_ID = 1;
private static final int MENU_VIEW_ID = 2; private static final int MENU_VIEW_ID = 2;
private static final int STATE_CLOSE = 0; private static final int STATE_CLOSE = 0;
private static final int STATE_OPEN = 1; private static final int STATE_OPEN = 1;
private int mSwipeDirection; private int mSwipeDirection;
private View mContentView; private View mContentView;
private SwipeMenuView mMenuView; private SwipeMenuLayout mMenuView;
private int mDownX; private int mDownX;
private int state = STATE_CLOSE; private int state = STATE_CLOSE;
private GestureDetectorCompat mGestureDetector; private GestureDetectorCompat mGestureDetector;
private OnGestureListener mGestureListener; private OnGestureListener mGestureListener;
private boolean isFling; private boolean isFling;
private int MIN_FLING = dp2px(15); private int MIN_FLING = dp2px(15);
private int MAX_VELOCITYX = -dp2px(500); private int MAX_VELOCITY_X = -dp2px(500);
private ScrollerCompat mOpenScroller; private ScrollerCompat mOpenScroller;
private ScrollerCompat mCloseScroller; private ScrollerCompat mCloseScroller;
private int mBaseX; private int mBaseX;
@ -43,52 +44,39 @@ public class SwipeMenuLayout extends FrameLayout {
private Interpolator mCloseInterpolator; private Interpolator mCloseInterpolator;
private Interpolator mOpenInterpolator; private Interpolator mOpenInterpolator;
private boolean mSwipEnable = true; private boolean mSwipeEnable = true;
public SwipeMenuLayout(View contentView, SwipeMenuView menuView) { public SwipableElement(Context context, View contentView, SwipeMenuLayout menuView) {
this(contentView, menuView, null, null); this(context, contentView, menuView, null, null);
} }
public SwipeMenuLayout(View contentView, SwipeMenuView menuView, public SwipableElement(Context context, View contentView, SwipeMenuLayout menuView,
Interpolator closeInterpolator, Interpolator openInterpolator) { Interpolator closeInterpolator, Interpolator openInterpolator) {
super(contentView.getContext()); super(context);
mCloseInterpolator = closeInterpolator; mCloseInterpolator = closeInterpolator;
mOpenInterpolator = openInterpolator; mOpenInterpolator = openInterpolator;
mContentView = contentView; mContentView = contentView;
mMenuView = menuView; mMenuView = menuView;
mMenuView.setLayout(this);
init(); doSomething();
} }
// private SwipeMenuLayout(Context context, AttributeSet attrs, int private SwipableElement(Context context, AttributeSet attrs) {
// defStyle) {
// super(context, attrs, defStyle);
// }
private SwipeMenuLayout(Context context, AttributeSet attrs) {
super(context, attrs); super(context, attrs);
} }
private SwipeMenuLayout(Context context) { private SwipableElement(Context context) {
super(context); super(context);
} }
public int getPosition() {
return position;
}
public void setPosition(int position) {
this.position = position;
mMenuView.setPosition(position);
}
public void setSwipeDirection(int swipeDirection) { public void setSwipeDirection(int swipeDirection) {
mSwipeDirection = swipeDirection; mSwipeDirection = swipeDirection;
} }
private void init() { private void doSomething() {
setLayoutParams(new AbsListView.LayoutParams(LayoutParams.MATCH_PARENT, setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 56));
LayoutParams.WRAP_CONTENT));
mGestureListener = new SimpleOnGestureListener() { mGestureListener = new SimpleOnGestureListener() {
@Override @Override
public boolean onDown(MotionEvent e) { public boolean onDown(MotionEvent e) {
@ -99,20 +87,17 @@ public class SwipeMenuLayout extends FrameLayout {
@Override @Override
public boolean onFling(MotionEvent e1, MotionEvent e2, public boolean onFling(MotionEvent e1, MotionEvent e2,
float velocityX, float velocityY) { float velocityX, float velocityY) {
// TODO if (e1 != null && e2 != null) {
if (Math.abs(e1.getX() - e2.getX()) > MIN_FLING if (Math.abs(e1.getX() - e2.getX()) > MIN_FLING
&& velocityX < MAX_VELOCITYX) { && velocityX < MAX_VELOCITY_X) {
isFling = true; isFling = true;
} }
// Log.i("byz", MAX_VELOCITYX + ", velocityX = " + velocityX); }
return super.onFling(e1, e2, velocityX, velocityY); return super.onFling(e1, e2, velocityX, velocityY);
} }
}; };
mGestureDetector = new GestureDetectorCompat(getContext(), mGestureDetector = new GestureDetectorCompat(getContext(), mGestureListener);
mGestureListener);
// mScroller = ScrollerCompat.create(getContext(), new
// BounceInterpolator());
if (mCloseInterpolator != null) { if (mCloseInterpolator != null) {
mCloseScroller = ScrollerCompat.create(getContext(), mCloseScroller = ScrollerCompat.create(getContext(),
mCloseInterpolator); mCloseInterpolator);
@ -126,35 +111,17 @@ public class SwipeMenuLayout extends FrameLayout {
mOpenScroller = ScrollerCompat.create(getContext()); mOpenScroller = ScrollerCompat.create(getContext());
} }
LayoutParams contentParams = new LayoutParams( LayoutParams contentParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
mContentView.setLayoutParams(contentParams); mContentView.setLayoutParams(contentParams);
if (mContentView.getId() < 1) { if (mContentView.getId() < 1) {
mContentView.setId(CONTENT_VIEW_ID); mContentView.setId(CONTENT_VIEW_ID);
} }
if (mMenuView.getId() < 1)
mMenuView.setId(MENU_VIEW_ID); mMenuView.setId(MENU_VIEW_ID);
mMenuView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, mMenuView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
LayoutParams.WRAP_CONTENT));
addView(mContentView); addView(mContentView);
addView(mMenuView); addView(mMenuView);
// if (mContentView.getBackground() == null) {
// mContentView.setBackgroundColor(Color.WHITE);
// }
// in android 2.x, MenuView height is MATCH_PARENT is not work.
// getViewTreeObserver().addOnGlobalLayoutListener(
// new OnGlobalLayoutListener() {
// @Override
// public void onGlobalLayout() {
// setMenuHeight(mContentView.getHeight());
// // getViewTreeObserver()
// // .removeGlobalOnLayoutListener(this);
// }
// });
} }
@Override @Override
@ -170,25 +137,25 @@ public class SwipeMenuLayout extends FrameLayout {
public boolean onSwipe(MotionEvent event) { public boolean onSwipe(MotionEvent event) {
mGestureDetector.onTouchEvent(event); mGestureDetector.onTouchEvent(event);
switch (event.getAction()) { switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_DOWN:
mDownX = (int) event.getX(); mDownX = (int) event.getX();
isFling = false; isFling = false;
break; break;
case MotionEvent.ACTION_MOVE: case MotionEvent.ACTION_MOVE:
// Log.i("byz", "downX = " + mDownX + ", moveX = " + event.getX());
int dis = (int) (mDownX - event.getX()); int dis = (int) (mDownX - event.getX());
if (state == STATE_OPEN) { if (state == STATE_OPEN) {
dis += mMenuView.getWidth()*mSwipeDirection;; dis += mMenuView.getWidth() * mSwipeDirection;
} }
swipe(dis); swipe(dis);
break; break;
case MotionEvent.ACTION_UP: case MotionEvent.ACTION_UP:
if ((isFling || Math.abs(mDownX - event.getX()) > (mMenuView.getWidth() / 2)) && if ((isFling || Math.abs(mDownX - event.getX()) > (mMenuView.getWidth() / 4)) &&
Math.signum(mDownX - event.getX()) == mSwipeDirection) { Math.signum(mDownX - event.getX()) == mSwipeDirection) {
// open
smoothOpenMenu(); smoothOpenMenu();
} else { } else {
// close
smoothCloseMenu(); smoothCloseMenu();
return false; return false;
} }
@ -201,25 +168,20 @@ public class SwipeMenuLayout extends FrameLayout {
return state == STATE_OPEN; return state == STATE_OPEN;
} }
@Override
public boolean onTouchEvent(MotionEvent event) {
return super.onTouchEvent(event);
}
private void swipe(int dis) { private void swipe(int dis) {
if(!mSwipEnable){ if (!mSwipeEnable){
return ; return ;
} }
if (Math.signum(dis) != mSwipeDirection) { if (Math.signum(dis) != mSwipeDirection) {
dis = 0; dis = 0;
} else if (Math.abs(dis) > mMenuView.getWidth()) { } else if (mMenuView.getWidth() > 0 && Math.abs(dis) > mMenuView.getWidth()) {
dis = mMenuView.getWidth()*mSwipeDirection; dis = mMenuView.getWidth()*mSwipeDirection;
} }
mContentView.layout(-dis, mContentView.getTop(), mContentView.layout(-dis, mContentView.getTop(),
mContentView.getWidth() -dis, getMeasuredHeight()); mContentView.getWidth() -dis, getMeasuredHeight());
if (mSwipeDirection == SwipeMenuListView.DIRECTION_LEFT) { if (mSwipeDirection == SwipableRecycler.DIRECTION_LEFT) {
mMenuView.layout(mContentView.getWidth() - dis, mMenuView.getTop(), mMenuView.layout(mContentView.getWidth() - dis, mMenuView.getTop(),
mContentView.getWidth() + mMenuView.getWidth() - dis, mContentView.getWidth() + mMenuView.getWidth() - dis,
@ -247,7 +209,7 @@ public class SwipeMenuLayout extends FrameLayout {
public void smoothCloseMenu() { public void smoothCloseMenu() {
state = STATE_CLOSE; state = STATE_CLOSE;
if (mSwipeDirection == SwipeMenuListView.DIRECTION_LEFT) { if (mSwipeDirection == SwipableRecycler.DIRECTION_LEFT) {
mBaseX = -mContentView.getLeft(); mBaseX = -mContentView.getLeft();
mCloseScroller.startScroll(0, 0, mMenuView.getWidth(), 0, 350); mCloseScroller.startScroll(0, 0, mMenuView.getWidth(), 0, 350);
} else { } else {
@ -258,11 +220,11 @@ public class SwipeMenuLayout extends FrameLayout {
} }
public void smoothOpenMenu() { public void smoothOpenMenu() {
if(!mSwipEnable){ if(!mSwipeEnable){
return ; return ;
} }
state = STATE_OPEN; state = STATE_OPEN;
if (mSwipeDirection == SwipeMenuListView.DIRECTION_LEFT) { if (mSwipeDirection == SwipableRecycler.DIRECTION_LEFT) {
mOpenScroller.startScroll(-mContentView.getLeft(), 0, mMenuView.getWidth(), 0, 350); mOpenScroller.startScroll(-mContentView.getLeft(), 0, mMenuView.getWidth(), 0, 350);
} else { } else {
mOpenScroller.startScroll(mContentView.getLeft(), 0, mMenuView.getWidth(), 0, 350); mOpenScroller.startScroll(mContentView.getLeft(), 0, mMenuView.getWidth(), 0, 350);
@ -281,7 +243,7 @@ public class SwipeMenuLayout extends FrameLayout {
} }
public void openMenu() { public void openMenu() {
if(!mSwipEnable){ if(!mSwipeEnable){
return ; return ;
} }
if (state == STATE_CLOSE) { if (state == STATE_CLOSE) {
@ -294,7 +256,7 @@ public class SwipeMenuLayout extends FrameLayout {
return mContentView; return mContentView;
} }
public SwipeMenuView getMenuView() { public SwipeMenuLayout getMenuView() {
return mMenuView; return mMenuView;
} }
@ -306,16 +268,28 @@ public class SwipeMenuLayout extends FrameLayout {
@Override @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec); super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mMenuView.measure(MeasureSpec.makeMeasureSpec(0,
MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec( int width = getMeasuredWidth();
getMeasuredHeight(), MeasureSpec.EXACTLY)); int height = getMeasuredHeight();
int childWidthMeasureSpec;
int childHeightMeasureSpec;
childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
mContentView.measure(childWidthMeasureSpec, childHeightMeasureSpec);
childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST);
childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
mMenuView.measure(childWidthMeasureSpec, childHeightMeasureSpec);
} }
@Override @Override
protected void onLayout(boolean changed, int l, int t, int r, int b) { protected void onLayout(boolean changed, int l, int t, int r, int b) {
mContentView.layout(0, 0, getMeasuredWidth(), mContentView.layout(0, 0, getMeasuredWidth(),mContentView.getMeasuredHeight());
mContentView.getMeasuredHeight()); if (mSwipeDirection == DIRECTION_LEFT) {
if (mSwipeDirection == SwipeMenuListView.DIRECTION_LEFT) {
mMenuView.layout(getMeasuredWidth(), 0, mMenuView.layout(getMeasuredWidth(), 0,
getMeasuredWidth() + mMenuView.getMeasuredWidth(), getMeasuredWidth() + mMenuView.getMeasuredWidth(),
mContentView.getMeasuredHeight()); mContentView.getMeasuredHeight());
@ -326,7 +300,6 @@ public class SwipeMenuLayout extends FrameLayout {
} }
public void setMenuHeight(int measuredHeight) { public void setMenuHeight(int measuredHeight) {
Log.i("byz", "pos = " + position + ", height = " + measuredHeight);
LayoutParams params = (LayoutParams) mMenuView.getLayoutParams(); LayoutParams params = (LayoutParams) mMenuView.getLayoutParams();
if (params.height != measuredHeight) { if (params.height != measuredHeight) {
params.height = measuredHeight; params.height = measuredHeight;
@ -334,11 +307,21 @@ public class SwipeMenuLayout extends FrameLayout {
} }
} }
public void setSwipEnable(boolean swipEnable){ public void setSwipeEnable(boolean swipeEnable){
mSwipEnable = swipEnable; mSwipeEnable = swipeEnable;
} }
public boolean getSwipEnable(){ public boolean getSwipeEnable(){
return mSwipEnable; return mSwipeEnable;
}
public boolean isMenuVisible() {
Rect bounds = new Rect();
this.getHitRect(bounds);
if (mMenuView.getLocalVisibleRect(bounds)) {
return true;
} else {
return false;
}
} }
} }

View File

@ -0,0 +1,199 @@
package com.hikapro.backpack.presenter.adapters.helper.items.swipe2;
import android.content.Context;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
/**
* Created by tariel on 06/07/16.
*/
public class SwipableRecycler extends RecyclerView {
private static final int TOUCH_ACTION_START = 1;
private static final int TOUCH_ACTION_MOVE_X = 2;
private static final int TOUCH_ACTION_MOVE_Y = 3;
public static final int DIRECTION_LEFT = 1;
public static final int DIRECTION_RIGHT = -1;
private int mDirection = 1; // swipe from right to left by default
private int MAX_Y = 5;
private int MAX_X = 3;
private float mDownX;
private float mDownY;
private int mTouchState;
private SwipableElement lastTouchedElement;
public SwipableRecycler(Context context) {
super(context);
init();
}
public SwipableRecycler(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public SwipableRecycler(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
@Override
public boolean onInterceptTouchEvent(MotionEvent e) {
View buf;
int action = e.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
boolean handled = false;
mDownX = e.getX();
mDownY = e.getY();
handled = super.onInterceptTouchEvent(e);
mTouchState = TOUCH_ACTION_START;
buf = findChildViewUnder(mDownX, mDownY);
if (buf instanceof SwipableElement) {
if (lastTouchedElement != null && lastTouchedElement.isOpen() && !inRangeOfView(lastTouchedElement.getMenuView(), e)) {
return true;
}
lastTouchedElement = (SwipableElement) buf;
lastTouchedElement.setSwipeDirection(mDirection);
}
if (lastTouchedElement != null && lastTouchedElement.isOpen() && lastTouchedElement != buf) {
handled = true;
}
if (lastTouchedElement != null && lastTouchedElement.isOpen() && inRangeOfView(lastTouchedElement.getMenuView(), e)) {
lastTouchedElement.getMenuView().notifyOnClick(e.getRawX(), e.getRawY());
}
if (lastTouchedElement != null)
lastTouchedElement.onSwipe(e);
return handled;
case MotionEvent.ACTION_MOVE:
float dy = Math.abs((e.getY() - mDownY));
float dx = Math.abs((e.getX() - mDownX));
if (Math.abs(dy) > MAX_Y || Math.abs(dx) > MAX_X) {
if (mTouchState == TOUCH_ACTION_START) {
if (Math.abs(dy) > MAX_Y) {
mTouchState = TOUCH_ACTION_MOVE_Y;
} else if (dx > MAX_X) {
mTouchState = TOUCH_ACTION_MOVE_X;
}
}
return true;
}
}
return super.onInterceptTouchEvent(e);
}
@Override
public boolean onTouchEvent(MotionEvent e) {
View buf;
int action = e.getAction();
if (action != MotionEvent.ACTION_DOWN && lastTouchedElement == null)
return super.onTouchEvent(e);
switch (action) {
case MotionEvent.ACTION_DOWN:
SwipableElement test = null;
mDownX = e.getX();
mDownY = e.getY();
mTouchState = TOUCH_ACTION_START;
buf = findChildViewUnder(e.getX(), e.getY());
if (buf instanceof SwipableElement)
test = (SwipableElement) buf;
if (lastTouchedElement != null && lastTouchedElement == test
&& lastTouchedElement.isOpen()) {
mTouchState = TOUCH_ACTION_MOVE_X;
lastTouchedElement.onSwipe(e);
return true;
}
if (lastTouchedElement != null && lastTouchedElement.isOpen()) {
lastTouchedElement.smoothCloseMenu();
lastTouchedElement = null;
// try to cancel the touch event
MotionEvent cancelEvent = MotionEvent.obtain(e);
cancelEvent.setAction(MotionEvent.ACTION_CANCEL);
super.onTouchEvent(cancelEvent);
return true;
}
if (buf instanceof SwipableElement) {
lastTouchedElement = (SwipableElement) buf;
lastTouchedElement.setSwipeDirection(mDirection);
}
if (lastTouchedElement != null) {
lastTouchedElement.onSwipe(e);
}
break;
case MotionEvent.ACTION_MOVE:
float dy = Math.abs((e.getY() - mDownY));
float dx = Math.abs((e.getX() - mDownX));
if (mTouchState == TOUCH_ACTION_MOVE_X) {
if (lastTouchedElement != null) {
lastTouchedElement.onSwipe(e);
}
e.setAction(MotionEvent.ACTION_CANCEL);
super.onTouchEvent(e);
return true;
} else if (mTouchState == TOUCH_ACTION_START) {
if (Math.abs(dy) > MAX_Y) {
mTouchState = TOUCH_ACTION_MOVE_Y;
} else if (dx > MAX_X) {
mTouchState = TOUCH_ACTION_MOVE_X;
}
}
break;
case MotionEvent.ACTION_UP:
if (mTouchState == TOUCH_ACTION_MOVE_X) {
if (lastTouchedElement != null) {
boolean isBeforeOpen = lastTouchedElement.isOpen();
lastTouchedElement.onSwipe(e);
boolean isAfterOpen = lastTouchedElement.isOpen();
if (!isAfterOpen) {
lastTouchedElement = null;
}
}
e.setAction(MotionEvent.ACTION_CANCEL);
super.onTouchEvent(e);
return true;
}
break;
}
return super.onTouchEvent(e);
}
public static boolean inRangeOfView(View view, MotionEvent ev) {
int[] location = new int[2];
view.getLocationOnScreen(location);
int x = location[0];
int y = location[1];
if (ev.getRawX() < x || ev.getRawX() > (x + view.getWidth()) || ev.getRawY() < y || ev.getRawY() > (y + view.getHeight())) {
return false;
}
return true;
}
private void init() {
MAX_X = dp2px(MAX_X);
MAX_Y = dp2px(MAX_Y);
mTouchState = TOUCH_ACTION_START;
}
private int dp2px(int dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
getContext().getResources().getDisplayMetrics());
}
}

View File

@ -1,4 +1,4 @@
package com.hikapro.backpack.presenter.adapters.helper.items.swipe; package com.hikapro.backpack.presenter.adapters.helper.items.swipe2;
import android.content.Context; import android.content.Context;

View File

@ -1,4 +1,4 @@
package com.hikapro.backpack.presenter.adapters.helper.items.swipe; package com.hikapro.backpack.presenter.adapters.helper.items.swipe2;
import android.content.Context; import android.content.Context;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;

View File

@ -0,0 +1,123 @@
package com.hikapro.backpack.presenter.adapters.helper.items.swipe2;
import android.content.Context;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.List;
/**
* Created by tariel on 18/06/16.
*/
public class SwipeMenuLayout extends LinearLayout {
private SwipeMenu swipeMenu;
private OnMenuItemClickListener menuItemClickListener;
public OnMenuItemClickListener getMenuItemClickListener() {
return menuItemClickListener;
}
public void setMenuItemClickListener(OnMenuItemClickListener menuItemClickListener) {
this.menuItemClickListener = menuItemClickListener;
}
public SwipeMenuLayout(Context context) {
super(context);
}
public SwipeMenuLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SwipeMenuLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public void addMenu(SwipeMenu menu) {
swipeMenu = menu;
List<SwipeMenuItem> items = menu.getMenuItems();
int id = 0;
for (SwipeMenuItem item : items) {
addItem(item, item.getId() == 0 ? ++id : item.getId());
}
}
private void addItem(SwipeMenuItem item, int id) {
LayoutParams params = new LayoutParams(item.getWidth(),LayoutParams.MATCH_PARENT);
LinearLayout parent = new LinearLayout(getContext());
parent.setId(id);
parent.setGravity(Gravity.CENTER);
parent.setOrientation(LinearLayout.VERTICAL);
parent.setLayoutParams(params);
parent.setBackgroundDrawable(item.getBackground());
addView(parent);
if (item.getIcon() != null) {
parent.addView(createIcon(item));
}
if (!TextUtils.isEmpty(item.getTitle())) {
parent.addView(createTitle(item));
}
}
private ImageView createIcon(SwipeMenuItem item) {
ImageView iv = new ImageView(getContext());
iv.setImageDrawable(item.getIcon());
return iv;
}
private TextView createTitle(SwipeMenuItem item) {
TextView tv = new TextView(getContext());
tv.setText(item.getTitle());
tv.setGravity(Gravity.CENTER);
tv.setTextSize(item.getTitleSize());
tv.setTextColor(item.getTitleColor());
return tv;
}
// should be raw coordinates
public void notifyOnClick(float x, float y) {
View menuItem = findViewAtPoint(x, y);
if (menuItem != null) {
if (menuItemClickListener != null)
menuItemClickListener.onMenuItemClick(menuItem);
}
}
public interface OnMenuItemClickListener {
void onMenuItemClick(View v);
}
private View findViewAtPoint(float x, float y) {
View ret = null;
View buf;
for (int i = 0; i < this.getChildCount(); ++i) {
buf = getChildAt(i);
if (isPointInsideView(x, y, buf)) {
ret = buf;
break;
}
}
return ret;
}
private boolean isPointInsideView(float x, float y, View view) {
int location[] = new int[2];
view.getLocationOnScreen(location);
int viewX = location[0];
int viewY = location[1];
// point is inside view bounds
return ((x > viewX && x < (viewX + view.getWidth())) &&
(y > viewY && y < (viewY + view.getHeight())));
}
}

View File

@ -0,0 +1,9 @@
package com.hikapro.backpack.test;
import android.app.Fragment;
/**
* Created by tariel on 16/07/16.
*/
public class ScreenSlidePageFrag extends Fragment {
}

View File

@ -25,7 +25,7 @@ public interface View {
} }
interface ItemList extends Base { interface ItemList extends Base {
void showItemDetail(Item item); void showItemDetail(Item item, int setId);
void showPackedItems(Set set); void showPackedItems(Set set);
void setPresenter(Presenter.ItemList presenter); void setPresenter(Presenter.ItemList presenter);
Set getSet(); Set getSet();
@ -33,6 +33,7 @@ public interface View {
interface ItemDetail extends Base { interface ItemDetail extends Base {
void setPresenter(Presenter.ItemDetail presenter); void setPresenter(Presenter.ItemDetail presenter);
Item getItem(); Item getItem();
int getSetId();
} }
interface Share extends Base { interface Share extends Base {
@ -49,7 +50,7 @@ public interface View {
void startSetListFragment(); void startSetListFragment();
void startItemListFragment(Set set); void startItemListFragment(Set set);
void startPackedListFragment(Set set); void startPackedListFragment(Set set);
void startItemDetailFragment(Item item); void startItemDetailFragment(Item item, int setId);
void startShareFragment(int setId); void startShareFragment(int setId);
void startAddFragment(Set set); void startAddFragment(Set set);

View File

@ -7,9 +7,13 @@ import android.os.Bundle;
import android.app.Fragment; import android.app.Fragment;
import android.util.Log; import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import com.hikapro.backpack.R;
import com.hikapro.backpack.model.entities.Item; import com.hikapro.backpack.model.entities.Item;
import com.hikapro.backpack.presenter.Presenter; import com.hikapro.backpack.presenter.Presenter;
@ -19,6 +23,7 @@ import com.hikapro.backpack.presenter.Presenter;
public class ItemDetailFragment extends Fragment implements com.hikapro.backpack.view.View.ItemDetail { public class ItemDetailFragment extends Fragment implements com.hikapro.backpack.view.View.ItemDetail {
private static final String BUNDLE_ITEM_KEY = "BUNDLE_ITEM_KEY"; private static final String BUNDLE_ITEM_KEY = "BUNDLE_ITEM_KEY";
private static final String BUNDLE_SET_KEY = "BUNDLE_SET_KEY";
private Presenter.ItemDetail presenter; private Presenter.ItemDetail presenter;
private com.hikapro.backpack.view.View.ActivityCallback activityCallback; private com.hikapro.backpack.view.View.ActivityCallback activityCallback;
@ -32,10 +37,11 @@ public class ItemDetailFragment extends Fragment implements com.hikapro.backpack
return new ItemDetailFragment(); return new ItemDetailFragment();
} }
public static ItemDetailFragment newFromItem(Item item) { public static ItemDetailFragment newInstance(Item item, int setId) {
ItemDetailFragment ret = ItemDetailFragment.construct(); ItemDetailFragment ret = ItemDetailFragment.construct();
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putSerializable(BUNDLE_ITEM_KEY, item); args.putSerializable(BUNDLE_ITEM_KEY, item);
args.putInt(BUNDLE_SET_KEY, setId);
ret.setArguments(args); ret.setArguments(args);
return ret; return ret;
} }
@ -142,4 +148,11 @@ public class ItemDetailFragment extends Fragment implements com.hikapro.backpack
Item item = (Item) args.getSerializable(BUNDLE_ITEM_KEY); Item item = (Item) args.getSerializable(BUNDLE_ITEM_KEY);
return item; return item;
} }
@Override
public int getSetId() {
Bundle args = getArguments();
int setId = args.getInt(BUNDLE_SET_KEY);
return setId;
}
} }

View File

@ -71,11 +71,9 @@ public class ItemListFragment extends Fragment implements com.hikapro.backpack.v
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
boolean ret; boolean ret;
switch (item.getItemId()) { switch (item.getItemId()) {
case android.R.id.home:
this.getFragmentManager().popBackStack();
ret = true;
break;
case R.id.action_share : case R.id.action_share :
activityCallback.startShareFragment(getSet().getId()); activityCallback.startShareFragment(getSet().getId());
ret = true; ret = true;
@ -117,13 +115,13 @@ public class ItemListFragment extends Fragment implements com.hikapro.backpack.v
throw new ClassCastException(activity.toString() throw new ClassCastException(activity.toString()
+ " must implement activityCallback"); + " must implement activityCallback");
} }
Log.i(this.toString(), " onAttach"); Log.i(this.getClass().getName(), " onAttach");
} }
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setHasOptionsMenu(true); setHasOptionsMenu(true);
Log.i(this.toString(), " onCreate"); Log.i(this.getClass().getName(), " onCreate");
} }
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
@ -131,58 +129,58 @@ public class ItemListFragment extends Fragment implements com.hikapro.backpack.v
// Inflate the layout for this fragment // Inflate the layout for this fragment
presenter.setView(this); presenter.setView(this);
View view = presenter.onCreateView(inflater, container, savedInstanceState); View view = presenter.onCreateView(inflater, container, savedInstanceState);
Log.i(this.toString(), " onCreateView"); Log.i(this.getClass().getName(), " onCreateView");
return view; return view;
} }
@Override @Override
public void onActivityCreated(Bundle savedInstanceState) { public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState); super.onActivityCreated(savedInstanceState);
Log.i(this.toString(), " onActivityCreated"); Log.i(this.getClass().getName(), " onActivityCreated");
} }
@Override @Override
public void onStart() { public void onStart() {
super.onStart(); super.onStart();
Log.i(this.toString(), " onStart"); Log.i(this.getClass().getName(), " onStart");
} }
@Override @Override
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
Log.i(this.toString(), " onResume"); Log.i(this.getClass().getName(), " onResume");
} }
@Override @Override
public void onStop() { public void onStop() {
super.onStop(); super.onStop();
Log.i(this.toString(), " onStop"); Log.i(this.getClass().getName(), " onStop");
} }
@Override @Override
public void onDestroyView() { public void onDestroyView() {
super.onDestroyView(); super.onDestroyView();
presenter.onDestroy(true); // TODO isChangingConfigurations presenter.onDestroy(true); // TODO isChangingConfigurations
Log.i(this.toString(), " onDestroyView"); Log.i(this.getClass().getName(), " onDestroyView");
} }
@Override @Override
public void onDestroy() { public void onDestroy() {
super.onDestroy(); super.onDestroy();
presenter.onDestroy(false); // TODO isChangingConfigurations presenter.onDestroy(false); // TODO isChangingConfigurations
Log.i(this.toString(), " onDestroy"); Log.i(this.getClass().getName(), " onDestroy");
} }
@Override @Override
public void onDetach() { public void onDetach() {
super.onDetach(); super.onDetach();
Log.i(this.toString(), " onDetach"); Log.i(this.getClass().getName(), " onDetach");
} }
@Override @Override
public void onSaveInstanceState(Bundle outState) { public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState); super.onSaveInstanceState(outState);
presenter.onSaveInstanceState(outState); presenter.onSaveInstanceState(outState);
Log.i(this.toString(), " onSaveInstanceState"); Log.i(this.getClass().getName(), " onSaveInstanceState");
} }
// life cycle <-- // life cycle <--
@Override @Override
public void showItemDetail(Item item) { public void showItemDetail(Item item, int setId) {
activityCallback.startItemDetailFragment(item); activityCallback.startItemDetailFragment(item, setId);
}//TODO del? }//TODO del?
@Override @Override

View File

@ -6,8 +6,10 @@ import android.view.ViewGroup;
import android.widget.Button; import android.widget.Button;
import android.widget.CheckBox; import android.widget.CheckBox;
import android.widget.ImageButton; import android.widget.ImageButton;
import android.widget.TextView;
import com.hikapro.backpack.R; import com.hikapro.backpack.R;
import com.hikapro.backpack.presenter.adapters.helper.items.swipe2.SwipableElement;
/** /**
@ -15,12 +17,10 @@ import com.hikapro.backpack.R;
*/ */
public class ItemViewHolder extends RecyclerView.ViewHolder { public class ItemViewHolder extends RecyclerView.ViewHolder {
public int id; public CheckBox cb_item;
public CheckBox checkBox; public TextView tv_text;
public Button leaveAtHomeButton; public ImageButton im_info;
public Button deleteButton; public ViewGroup menu;
public ImageButton infoButton;
public ViewGroup swipeGroup;
public ItemViewHolder(View v) { public ItemViewHolder(View v) {
super(v); super(v);
@ -28,11 +28,10 @@ public class ItemViewHolder extends RecyclerView.ViewHolder {
} }
private void setupViews(View view) { private void setupViews(View view) {
infoButton = (ImageButton) view.findViewById(R.id.info_button); cb_item = (CheckBox) view.findViewById(R.id.item_checkbox);
checkBox = (CheckBox) view.findViewById(R.id.item_checkbox); tv_text = (TextView) view.findViewById(R.id.item_text);
leaveAtHomeButton = (Button) view.findViewById(R.id.leave_at_home_button); im_info = (ImageButton) view.findViewById(R.id.item_info_button);
deleteButton = (Button) view.findViewById(R.id.delete_button); menu = (ViewGroup) view.findViewById(R.id.menu);
swipeGroup = (ViewGroup) view.findViewById((R.id.swipe_container));
}
}
} }

View File

@ -0,0 +1,38 @@
package com.hikapro.backpack.view.recycler;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ImageButton;
import com.hikapro.backpack.R;
/**
* Created by tariel on 01/05/16.
*/
public class ItemViewHolderCopy extends RecyclerView.ViewHolder {
public int id;
public CheckBox checkBox;
public Button leaveAtHomeButton;
public Button deleteButton;
public ImageButton infoButton;
public ViewGroup swipeGroup;
public ItemViewHolderCopy(View v) {
super(v);
setupViews(v);
}
private void setupViews(View view) {
infoButton = (ImageButton) view.findViewById(R.id.info_button);
checkBox = (CheckBox) view.findViewById(R.id.item_checkbox);
leaveAtHomeButton = (Button) view.findViewById(R.id.leave_at_home_button);
deleteButton = (Button) view.findViewById(R.id.delete_button);
swipeGroup = (ViewGroup) view.findViewById((R.id.swipe_container));
}
}

View File

@ -1,15 +1,58 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
tools:context="com.hikapro.backpack.view.fragments.ItemDetailFragment"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical" android:animateLayoutChanges="true"
tools:context="com.hikapro.backpack.view.fragments.ItemDetailFragment" android:background="@color/colorUiMainbackground2">
android:background="@color/colorUiMainbackground">
<android.support.v7.widget.RecyclerView <ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.hikapro.backpack.presenter.adapters.helper.items.swipe2.SwipableRecycler
android:id="@+id/item_detail_recycler" android:id="@+id/item_detail_recycler"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:scrollbars="vertical"> android:scrollbars="vertical"
</android.support.v7.widget.RecyclerView> android:scrollIndicators="none"/>
</LinearLayout>
<ImageView
android:id="@+id/item_photo"
android:layout_width="350dp"
android:layout_height="wrap_content"
android:scaleType="fitXY"
android:adjustViewBounds="true"
android:paddingTop="20dp"
android:paddingBottom="32dp"
android:paddingStart="50dp"
android:paddingEnd="50dp"
android:layout_gravity="center_horizontal"
android:contentDescription="@string/cd_item_image"/>
<TextView
android:id="@+id/item_description"
android:paddingStart="16dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/colorUiMainFont" />
<TextView
android:id="@+id/item_link"
android:paddingStart="16dp"
android:paddingBottom="32dp"
android:paddingTop="20dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/colorUiSecondaryFont"
android:text="@string/more"/>
</LinearLayout>
</ScrollView>
</FrameLayout>

View File

@ -1,8 +1,8 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
tools:context="com.hikapro.backpack.view.fragments.ItemListFragment" tools:context="com.hikapro.backpack.view.fragments.ItemListFragment"
android:layout_width="fill_parent" android:layout_width="match_parent"
android:layout_height="fill_parent" android:layout_height="match_parent"
android:animateLayoutChanges="true"> android:animateLayoutChanges="true">
<LinearLayout <LinearLayout
@ -11,12 +11,12 @@
android:orientation="vertical" android:orientation="vertical"
android:background="@color/colorUiMainbackground2"> android:background="@color/colorUiMainbackground2">
<android.support.v7.widget.RecyclerView <com.hikapro.backpack.presenter.adapters.helper.items.swipe2.SwipableRecycler
android:id="@+id/items_recycler" android:id="@+id/items_recycler"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:scrollbars="vertical" android:scrollbars="vertical"
/> android:scrollIndicators="none"/>
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout

View File

@ -53,12 +53,11 @@
android:layout_below="@id/item_list_header" android:layout_below="@id/item_list_header"
android:background="@color/colorUiMainbackground2"> android:background="@color/colorUiMainbackground2">
<android.support.v7.widget.RecyclerView <com.hikapro.backpack.presenter.adapters.helper.items.swipe2.SwipableRecycler
android:id="@+id/items_recycler" android:id="@+id/items_recycler"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:scrollbars="vertical" android:scrollbars="vertical"/>
/>
</LinearLayout> </LinearLayout>

View File

@ -1,37 +1,29 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout <LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:paddingBottom="@dimen/margin_standard" android:orientation="vertical">
android:paddingLeft="@dimen/margin_standard"
android:paddingRight="@dimen/margin_standard"
android:paddingTop="@dimen/margin_standard">
<TextView <include layout="@layout/item_element"/>
android:id="@+id/item_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:textColor="@color/colorUiMainFont"/>
<ImageView <ImageView
android:id="@+id/item_photo" android:id="@+id/item_photo"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/item_title" android:layout_gravity="center_horizontal"
android:layout_marginTop="@dimen/margin_standard_plus_plus"
android:layout_centerInParent="true"
android:contentDescription="@string/cd_item_image"/> android:contentDescription="@string/cd_item_image"/>
<TextView <TextView
android:id="@+id/item_description" android:id="@+id/item_description"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/item_photo" android:textColor="@color/colorUiMainFont" />
android:layout_centerHorizontal="true"
android:textColor="@color/colorUiMainFont"
android:layout_marginTop="@dimen/margin_standard_plus_plus" />
</RelativeLayout> <TextView
android:id="@+id/item_link"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/colorUiMainFont"/>
</LinearLayout>

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/margin_standard"
android:paddingLeft="@dimen/margin_standard"
android:paddingRight="@dimen/margin_standard"
android:paddingTop="@dimen/margin_standard">
<TextView
android:id="@+id/item_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:textColor="@color/colorUiMainFont"/>
<ImageView
android:id="@+id/item_photo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/item_title"
android:layout_marginTop="@dimen/margin_standard_plus_plus"
android:layout_centerInParent="true"
android:contentDescription="@string/cd_item_image"/>
<TextView
android:id="@+id/item_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/item_photo"
android:layout_centerHorizontal="true"
android:textColor="@color/colorUiMainFont"
android:layout_marginTop="@dimen/margin_standard_plus_plus" />
</RelativeLayout>

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="@dimen/item_height"
android:orientation="horizontal"
tools:context=".MainActivity">
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/item_checkbox"
android:layout_gravity="start|center_vertical"
android:padding="@dimen/item_checkbox_padding"
android:layout_marginStart="@dimen/margin_standard" />
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:id="@+id/item_text"
android:gravity="center_vertical"
android:layout_gravity="center"
android:layout_marginStart="@dimen/margin_standard"
android:layout_marginEnd="@dimen/margin_standard"
android:textSize="@dimen/size_item_name"
android:textColor="@color/colorUiMainFont" />
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/item_info_button"
android:layout_gravity="end|center_vertical"
android:layout_marginEnd="@dimen/margin_standard"
android:src="@drawable/ic_info_black_24dp"
android:background="@null" />
</LinearLayout>

View File

@ -7,4 +7,8 @@
<color name="colorShareBtnBackground">#76EE00</color> <color name="colorShareBtnBackground">#76EE00</color>
<color name="colorStickyHeaderBackground">#001F3F</color> <color name="colorStickyHeaderBackground">#001F3F</color>
<color name="colorCategoryBtnBackground">#76EE00</color> <color name="colorCategoryBtnBackground">#76EE00</color>
<color name="colorDeleteBtnBackground">#F93F25</color>
<color name="colorLeaveAtHomeBtnBackground">#C9C9CE</color>
<color name="colorAddToBagBtnBackground">#76EE00</color>
<color name="colorReturnToListBtnBackground">#C9C9CE</color>
</resources> </resources>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item type="id" name="menu" />
</resources>

View File

@ -9,12 +9,16 @@
<string name="choose_category">Choose item category:</string> <string name="choose_category">Choose item category:</string>
<string name="continue_packing">Continue with my packing &#x2191;</string> <string name="continue_packing">Continue with my packing &#x2191;</string>
<string name="already_in_list">Already in List</string> <string name="already_in_list">Already in List</string>
<string name="what_is_it">WHAT IS IT?</string>
<string name="more">More about this item &#x276D;</string>
<string name="unpack_button">UNPACK MY BAG</string> <string name="unpack_button">UNPACK MY BAG</string>
<string name="share_button">Share</string> <string name="share_button">Share</string>
<string name="undo_button">undo</string> <string name="undo_button">undo</string>
<string name="delete_button">delete</string> <string name="delete_button">DELETE</string>
<string name="leave_at_home_button">leave at home</string> <string name="leave_at_home_button">LEAVE AT HOME</string>
<string name="add_to_bag_button">ADD TO BAG</string>
<string name="return_to_list_button">RETURN TO LIST</string>
<string name="save_button">SAVE</string> <string name="save_button">SAVE</string>
<string name="cancel_button">CANCEL</string> <string name="cancel_button">CANCEL</string>
<string name="ok_button">OKAY</string> <string name="ok_button">OKAY</string>