From 6faa06a6b01a7f881f99812671b6330ff7c4430d Mon Sep 17 00:00:00 2001 From: LuLe73 Date: Wed, 30 May 2018 13:14:13 +0200 Subject: [PATCH] Swipe des chatrooms + suppression implantes. A faire: nettoyage et commentaires --- res/layout/chatlist_cell.xml | 9 +- res/layout/chatlist_cell_active.xml | 125 ----------- .../org/linphone/chat/ChatListFragment.java | 111 +++++---- .../org/linphone/chat/ChatRoomsAdapter.java | 15 +- .../org/linphone/ui/SelectableAdapter.java | 69 +++++- .../org/linphone/ui/SwipeController.java | 211 ++++++++++++++++++ .../linphone/ui/SwipeControllerActions.java | 7 + 7 files changed, 375 insertions(+), 172 deletions(-) delete mode 100644 res/layout/chatlist_cell_active.xml create mode 100644 src/android/org/linphone/ui/SwipeController.java create mode 100644 src/android/org/linphone/ui/SwipeControllerActions.java diff --git a/res/layout/chatlist_cell.xml b/res/layout/chatlist_cell.xml index 99aefd1ff..0e27ce336 100644 --- a/res/layout/chatlist_cell.xml +++ b/res/layout/chatlist_cell.xml @@ -6,7 +6,8 @@ android:paddingLeft="10dp" android:paddingRight="10dp" android:paddingTop="5dp" - android:background="@drawable/list_selector"> + android:foreground="?android:attr/selectableItemBackground" + android:background="@drawable/list_selector"> + \ No newline at end of file diff --git a/res/layout/chatlist_cell_active.xml b/res/layout/chatlist_cell_active.xml deleted file mode 100644 index 6989dc64e..000000000 --- a/res/layout/chatlist_cell_active.xml +++ /dev/null @@ -1,125 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/android/org/linphone/chat/ChatListFragment.java b/src/android/org/linphone/chat/ChatListFragment.java index 0c7f9463c..8aa501101 100644 --- a/src/android/org/linphone/chat/ChatListFragment.java +++ b/src/android/org/linphone/chat/ChatListFragment.java @@ -23,13 +23,16 @@ package org.linphone.chat; import android.app.Fragment; import android.content.Context; +import android.graphics.Canvas; import android.os.Bundle; import android.support.v4.widget.DrawerLayout; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; -import android.support.v7.widget.Toolbar; +import android.support.v7.widget.helper.ItemTouchHelper; import android.view.ActionMode; import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; @@ -48,6 +51,8 @@ import org.linphone.core.ChatRoomListenerStub; import org.linphone.core.Core; import org.linphone.core.CoreListenerStub; import org.linphone.fragments.FragmentsAvailable; +import org.linphone.ui.SwipeController; +import org.linphone.ui.SwipeControllerActions; import java.util.ArrayList; import java.util.Arrays; @@ -58,7 +63,7 @@ import static org.linphone.fragments.FragmentsAvailable.CHAT_LIST; //import android.widget.Toolbar; //public class ChatListFragment extends Fragment implements ContactsUpdatedListener, ListSelectionHelper.DeleteListener { -public class ChatListFragment extends Fragment implements ContactsUpdatedListener, /**ListSelectionHelper.DeleteListener,*/ ChatRoomsAdapter.ChatRoomViewHolder.ClickListener { +public class ChatListFragment extends Fragment implements ContactsUpdatedListener, ChatRoomsAdapter.ChatRoomViewHolder.ClickListener { //public class ChatListFragment extends Fragment { private ActionModeCallback actionModeCallback = new ActionModeCallback(); @@ -77,7 +82,7 @@ public class ChatListFragment extends Fragment implements ContactsUpdatedListene private int mChatRoomDeletionPendingCount; private ChatRoomListenerStub mChatRoomListener; private Context mContext; - private List mRooms; + public List mRooms; @Override public View onCreateView(final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -91,7 +96,7 @@ public class ChatListFragment extends Fragment implements ContactsUpdatedListene View view = inflater.inflate(R.layout.chatlist, container, false); RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(mContext); - Toolbar toolbar = this.getActivity().findViewById(R.id.context_bar); +// Toolbar toolbar = this.getActivity().findViewById(R.id.context_bar); // mChatRoomsAdapter = new ChatRoomsAdapter(mContext, R.layout.chatlist_cell, mRooms); mChatRoomsAdapter = new ChatRoomsAdapter(mContext, R.layout.chatlist_cell, mRooms,this); @@ -101,6 +106,7 @@ public class ChatListFragment extends Fragment implements ContactsUpdatedListene + // mSelectionHelper = new ListSelectionHelper(view, this); // mChatRoomsAdapter = new ChatRoomsAdapter(this, mSelectionHelper, mRooms); // mSelectionHelper.setAdapter(mChatRoomsAdapter); @@ -118,6 +124,33 @@ public class ChatListFragment extends Fragment implements ContactsUpdatedListene mChatRoomsList.setLayoutManager(layoutManager); // mNoChatHistory = view.findViewById(R.id.noChatHistory); + final SwipeController swipeController = new SwipeController(new SwipeControllerActions() { + @Override + public void onLeftClicked(int position) { + super.onLeftClicked(position); + } + + @Override + public void onRightClicked(int position) { + mChatRoomsAdapter.removeItem(position); +// mChatRoomsAdapter.mRooms.remove(position); +// mChatRoomsAdapter.notifyItemRemoved(position); +// mChatRoomsAdapter.notifyItemRangeChanged(position, mChatRoomsAdapter.getItemCount()); + } + }); + + ItemTouchHelper itemTouchhelper = new ItemTouchHelper(swipeController); + itemTouchhelper.attachToRecyclerView(mChatRoomsList); + mChatRoomsList.addItemDecoration(new RecyclerView.ItemDecoration() { + @Override + public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { + swipeController.onDraw(c); + } + }); + + + + // mNoChatHistory.setVisibility(View.GONE); mEditTopBar = view.findViewById(R.id.edit_list); mTopBar = view.findViewById(R.id.top_bar); @@ -128,12 +161,8 @@ public class ChatListFragment extends Fragment implements ContactsUpdatedListene mEditButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - actionMode = getActivity().startActionMode(actionModeCallback); - - -// getActivity().setActionBar(); - - } + actionMode = getActivity().startActionMode(actionModeCallback); + } }); mCancelButton = view.findViewById(R.id.cancel); @@ -177,6 +206,7 @@ public class ChatListFragment extends Fragment implements ContactsUpdatedListene } }; + mChatRoomListener = new ChatRoomListenerStub() { @Override public void onStateChanged(ChatRoom room, ChatRoom.State state) { @@ -199,6 +229,8 @@ public class ChatListFragment extends Fragment implements ContactsUpdatedListene return view; } + + @Override public void onItemClicked(int position) { if (actionMode != null) { @@ -266,11 +298,11 @@ public class ChatListFragment extends Fragment implements ContactsUpdatedListene actionMode.finish(); } }); - mTabBar = (LinearLayout) getActivity().findViewById(R.id.footer); +// mTabBar = (LinearLayout) getActivity().findViewById(R.id.footer); // mTabBar.setVisibility(View.GONE); - mSideMenu=(DrawerLayout) getActivity().findViewById(R.id.side_menu); - - mSideMenu.setDrawerLockMode(1); +// mSideMenu=(DrawerLayout) getActivity().findViewById(R.id.side_menu); +// +// mSideMenu.setDrawerLockMode(1); //Add all non-selected items to the selection mSelectAllButton.setOnClickListener(new View.OnClickListener() { @@ -437,32 +469,35 @@ public class ChatListFragment extends Fragment implements ContactsUpdatedListene super.onPause(); } - @Override - public void onDeleteSelection(Object[] objectsToDelete) { - Core lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull(); - mChatRoomDeletionPendingCount = objectsToDelete.length; - for (Object obj : objectsToDelete) { - ChatRoom room = (ChatRoom)obj; - for (EventLog eventLog : room.getHistoryEvents(0)) { - if (eventLog.getType() == EventLog.Type.ConferenceChatMessage) { - ChatMessage message = eventLog.getChatMessage(); - if (message.getAppdata() != null && !message.isOutgoing()) { - File file = new File(message.getAppdata()); - if (file.exists()) { - file.delete(); // Delete downloaded file from incoming message that will be deleted - } - } - } - } - room.addListener(mChatRoomListener); - lc.deleteChatRoom(room); - } - if (mChatRoomDeletionPendingCount > 0) { - mWaitLayout.setVisibility(View.VISIBLE); - } - } + +// @Override +// public void onDeleteSelection(Object[] objectsToDelete) { +// Core lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull(); +// mChatRoomDeletionPendingCount = objectsToDelete.length; +// for (Object obj : objectsToDelete) { +// ChatRoom room = (ChatRoom)obj; +// +// for (EventLog eventLog : room.getHistoryEvents(0)) { +// if (eventLog.getType() == EventLog.Type.ConferenceChatMessage) { +// ChatMessage message = eventLog.getChatMessage(); +// if (message.getAppdata() != null && !message.isOutgoing()) { +// File file = new File(message.getAppdata()); +// if (file.exists()) { +// file.delete(); // Delete downloaded file from incoming message that will be deleted +// } +// } +// } +// } +// +// room.addListener(mChatRoomListener); +// lc.deleteChatRoom(room); +// } +// if (mChatRoomDeletionPendingCount > 0) { +// mWaitLayout.setVisibility(View.VISIBLE); +// } +// } @Override public void onContactsUpdated() { diff --git a/src/android/org/linphone/chat/ChatRoomsAdapter.java b/src/android/org/linphone/chat/ChatRoomsAdapter.java index de5b7462e..1d7585e1e 100644 --- a/src/android/org/linphone/chat/ChatRoomsAdapter.java +++ b/src/android/org/linphone/chat/ChatRoomsAdapter.java @@ -22,8 +22,6 @@ package org.linphone.chat; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; -import android.net.Uri; -import android.provider.MediaStore; import android.support.v7.widget.RecyclerView; import android.view.ActionMode; import android.view.LayoutInflater; @@ -31,10 +29,9 @@ import android.view.View; import android.view.ViewGroup; import android.widget.CheckBox; import android.widget.ImageView; +import android.widget.RelativeLayout; import android.widget.TextView; -import android.widget.Toast; -//import org.linphone.Chat; import org.linphone.LinphoneManager; import org.linphone.LinphoneUtils; import org.linphone.R; @@ -56,9 +53,11 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; +//import org.linphone.Chat; + public class ChatRoomsAdapter extends RecyclerView.Adapter { - public class ChatRoomViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + public static class ChatRoomViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener{ public TextView lastMessageSenderView; public TextView lastMessageView; public TextView date; @@ -68,6 +67,8 @@ public class ChatRoomsAdapter extends RecyclerView.Adapter mRooms; + public List mRooms; private LayoutInflater mLayoutInflater; private Bitmap mDefaultBitmap, mDefaultGroupBitmap; private ChatRoomListenerStub mListener; @@ -202,7 +204,6 @@ public class ChatRoomsAdapter extends RecyclerView.Adapter mRooms) { public ChatRoomsAdapter(Context context, int itemResource, List mRooms, ChatRoomViewHolder.ClickListener clickListener) { - public ChatRoomsAdapter(Context context, int itemResource, List mRooms) { super(); this.editionMode = false; this.clickListener = clickListener; diff --git a/src/android/org/linphone/ui/SelectableAdapter.java b/src/android/org/linphone/ui/SelectableAdapter.java index 00d12b9fd..d07c548b7 100644 --- a/src/android/org/linphone/ui/SelectableAdapter.java +++ b/src/android/org/linphone/ui/SelectableAdapter.java @@ -1,4 +1,71 @@ package org.linphone.ui; -public abstract class SelectableAdapter { +import android.support.v7.widget.RecyclerView; +import android.util.SparseBooleanArray; + +import java.util.ArrayList; +import java.util.List; + +public abstract class SelectableAdapter extends RecyclerView.Adapter { + @SuppressWarnings("unused") + private static final String TAG = SelectableAdapter.class.getSimpleName(); + + private SparseBooleanArray selectedItems; + + public SelectableAdapter() { + selectedItems = new SparseBooleanArray(); + } + + /** + * Indicates if the item at position position is selected + * @param position Position of the item to check + * @return true if the item is selected, false otherwise + */ + public boolean isSelected(int position) { + return getSelectedItems().contains(position); + } + + /** + * Toggle the selection status of the item at a given position + * @param position Position of the item to toggle the selection status for + */ + public void toggleSelection(int position) { + if (selectedItems.get(position, false)) { + selectedItems.delete(position); + } else { + selectedItems.put(position, true); + } + notifyItemChanged(position); + } + + /** + * Clear the selection status for all items + */ + public void clearSelection() { + List selection = getSelectedItems(); + selectedItems.clear(); + for (Integer i : selection) { + notifyItemChanged(i); + } + } + + /** + * Count the selected items + * @return Selected items count + */ + public int getSelectedItemCount() { + return selectedItems.size(); + } + + /** + * Indicates the list of selected items + * @return List of selected items ids + */ + public List getSelectedItems() { + List items = new ArrayList<>(selectedItems.size()); + for (int i = 0; i < selectedItems.size(); ++i) { + items.add(selectedItems.keyAt(i)); + } + return items; + } } diff --git a/src/android/org/linphone/ui/SwipeController.java b/src/android/org/linphone/ui/SwipeController.java new file mode 100644 index 000000000..2564cdfde --- /dev/null +++ b/src/android/org/linphone/ui/SwipeController.java @@ -0,0 +1,211 @@ +package org.linphone.ui; + +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.RectF; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.helper.ItemTouchHelper.Callback; +import android.view.MotionEvent; +import android.view.View; + +import static android.support.v7.widget.helper.ItemTouchHelper.ACTION_STATE_SWIPE; +import static android.support.v7.widget.helper.ItemTouchHelper.LEFT; + +enum ButtonsState { + GONE, + LEFT_VISIBLE, + RIGHT_VISIBLE +} + +public class SwipeController extends Callback { + + private boolean swipeBack = false; + private ButtonsState buttonShowedState = ButtonsState.GONE; + private RectF buttonInstance = null; + private RecyclerView.ViewHolder currentItemViewHolder = null; + private SwipeControllerActions buttonsActions = null; + private static final float buttonWidth = 300; + + + public SwipeController(SwipeControllerActions buttonsActions) { + this.buttonsActions = buttonsActions; + } + + @Override + public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { + return makeMovementFlags(0, LEFT); +// return makeMovementFlags(0, LEFT | RIGHT); + } + + @Override + public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { + return false; + } + + @Override + public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { + + } + + @Override + public int convertToAbsoluteDirection(int flags, int layoutDirection) { + if (swipeBack) { + swipeBack = false; + return 0; + } + return super.convertToAbsoluteDirection(flags, layoutDirection); + } + + @Override + public void onChildDraw(Canvas c, + RecyclerView recyclerView, + RecyclerView.ViewHolder viewHolder, + float dX, float dY, + int actionState, boolean isCurrentlyActive) { + + if (actionState == ACTION_STATE_SWIPE) { + if (buttonShowedState != ButtonsState.GONE) { + if (buttonShowedState == ButtonsState.LEFT_VISIBLE) dX = Math.max(dX, buttonWidth); + if (buttonShowedState == ButtonsState.RIGHT_VISIBLE) dX = Math.min(dX, -buttonWidth); + super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); + }else { + setTouchListener(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); + } + } + if (buttonShowedState == ButtonsState.GONE) { + super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); + } + currentItemViewHolder = viewHolder; +// drawButtons(c, viewHolder); + } + + private void drawButtons(Canvas c, RecyclerView.ViewHolder viewHolder) { + float buttonWidthWithoutPadding = buttonWidth - 20; + float corners = 16; + + View itemView = viewHolder.itemView; + Paint p = new Paint(); + + RectF leftButton = new RectF(itemView.getLeft(), itemView.getTop(), itemView.getLeft() + buttonWidthWithoutPadding, itemView.getBottom()); + p.setColor(Color.BLUE); + c.drawRoundRect(leftButton, corners, corners, p); + drawText("EDIT", c, leftButton, p); + + RectF rightButton = new RectF(itemView.getRight() - buttonWidthWithoutPadding, itemView.getTop(), itemView.getRight(), itemView.getBottom()); + p.setColor(Color.RED); + c.drawRoundRect(rightButton, corners, corners, p); + drawText("DELETE", c, rightButton, p); + + buttonInstance = null; + if (buttonShowedState == ButtonsState.LEFT_VISIBLE) { + buttonInstance = leftButton; + } + else if (buttonShowedState == ButtonsState.RIGHT_VISIBLE) { + buttonInstance = rightButton; + } + + + } + + private void drawText(String text, Canvas c, RectF button, Paint p) { + float textSize = 60; + p.setColor(Color.WHITE); + p.setAntiAlias(true); + p.setTextSize(textSize); + + float textWidth = p.measureText(text); + c.drawText(text, button.centerX()-(textWidth/2), button.centerY()+(textSize/2), p); + } + + + + + private void setTouchListener(final Canvas c, + final RecyclerView recyclerView, + final RecyclerView.ViewHolder viewHolder, + final float dX, final float dY, + final int actionState, final boolean isCurrentlyActive) { + + recyclerView.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + swipeBack = event.getAction() == MotionEvent.ACTION_CANCEL || event.getAction() == MotionEvent.ACTION_UP; + if (swipeBack) { + if (dX < -buttonWidth) buttonShowedState = ButtonsState.RIGHT_VISIBLE; + else if (dX > buttonWidth) buttonShowedState = ButtonsState.LEFT_VISIBLE; + + if (buttonShowedState != ButtonsState.GONE) { + setTouchDownListener(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); + setItemsClickable(recyclerView, false); + } + } + return false; + } + }); + } + + private void setTouchDownListener(final Canvas c, + final RecyclerView recyclerView, + final RecyclerView.ViewHolder viewHolder, + final float dX, final float dY, + final int actionState, final boolean isCurrentlyActive) { + recyclerView.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + setTouchUpListener(c, recyclerView, viewHolder, dX, dY, + actionState, isCurrentlyActive); + } + return false; + } + }); + } + + private void setTouchUpListener(final Canvas c, final RecyclerView recyclerView, + final RecyclerView.ViewHolder viewHolder, + final float dX, final float dY, + final int actionState, final boolean isCurrentlyActive) { + recyclerView.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_UP) { + SwipeController.super.onChildDraw(c, recyclerView, viewHolder, 0F, dY, actionState, isCurrentlyActive); + recyclerView.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + return false; + } + }); + setItemsClickable(recyclerView, true); + swipeBack = false; + if (buttonsActions != null && buttonInstance != null && buttonInstance.contains(event.getX(), event.getY())) { + if (buttonShowedState == ButtonsState.LEFT_VISIBLE) { + buttonsActions.onLeftClicked(viewHolder.getAdapterPosition()); + } + else if (buttonShowedState == ButtonsState.RIGHT_VISIBLE) { + buttonsActions.onRightClicked(viewHolder.getAdapterPosition()); + } + } + + buttonShowedState = ButtonsState.GONE; + currentItemViewHolder = null; + } + return false; + } + }); + } + + private void setItemsClickable(RecyclerView recyclerView, boolean isClickable) { + for (int i = 0; i < recyclerView.getChildCount(); ++i) { + recyclerView.getChildAt(i).setClickable(isClickable); + } + } + + public void onDraw(Canvas c) { + if (currentItemViewHolder != null) { + drawButtons(c, currentItemViewHolder); + } + } + +} diff --git a/src/android/org/linphone/ui/SwipeControllerActions.java b/src/android/org/linphone/ui/SwipeControllerActions.java new file mode 100644 index 000000000..09cbe58b2 --- /dev/null +++ b/src/android/org/linphone/ui/SwipeControllerActions.java @@ -0,0 +1,7 @@ +package org.linphone.ui; + +public abstract class SwipeControllerActions { + public void onLeftClicked(int position) {} + + public void onRightClicked(int position) {} +}