I have a custom ListView showing the list of words selecting from database. When I swipe this listview item i want to show Delete button like image below. And when I press t
I have gone through tons of third party libraries to try to achieve this. But none of them exhibits smoothness and usability experience which i wanted. Then i decided to write it myself. And the result was , well, i loved it. I will share the code here. Maybe i will write it as a library which can be embedded in any recycler view in future. But for now here is the code.
Note: i have uses recycler view and ViewHolder. Some values are hardcoded so change them according to your requirement.
row_layout.xml
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:orientation="horizontal">
<Button
android:id="@+id/slide_button_2"
android:text="Button2"
android:layout_width="80dp"
android:layout_height="80dp" />
<Button
android:id="@+id/slide_button_1"
android:text="Button1"
android:layout_width="80dp"
android:layout_height="80dp" />
</LinearLayout>
<LinearLayout
android:id="@+id/chat_row_cell"
android:layout_width="match_parent"
android:layout_height="80dp"
android:orientation="horizontal"
android:background="@color/white">
<ImageView
android:id="@+id/chat_image"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_marginRight="10dp"
android:layout_gravity="center"/>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/chat_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/md_grey_800"
android:textSize="18sp"/>
<TextView
android:id="@+id/chat_subtitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/md_grey_600"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
ChatAdaptor.java
public class ChatAdaptor extends RecyclerView.Adapter {
List<MXGroupChatSession> sessions;
Context context;
ChatAdaptorInterface listener;
public interface ChatAdaptorInterface{
void cellClicked(MXGroupChatSession session);
void utilityButton1Clicked(MXGroupChatSession session);
void utilityButton2Clicked(MXGroupChatSession session);
}
public ChatAdaptor(List<MXGroupChatSession> sessions, ChatAdaptorInterface listener, Context context){
this.sessions=sessions;
this.context=context;
this.listener=listener;
}
@Override
public ChatViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view=(View)LayoutInflater.from(parent.getContext()).inflate(R.layout.chat_row,null);
ChatViewHolder chatViewHolder=new ChatViewHolder(view);
return chatViewHolder;
}
@Override
public void onBindViewHolder(ChatViewHolder holder, final int position) {
MXGroupChatSession session=this.sessions.get(position);
holder.selectedSession=session;
holder.titleView.setText(session.getTopic());
holder.subtitleView.setText(session.getLastFeedContent());
Picasso.with(context).load(new File(session.getCoverImagePath())).transform(new CircleTransformPicasso()).into(holder.imageView);
}
@Override
public int getItemCount() {
return sessions.size();
}
public class ChatViewHolder extends RecyclerView.ViewHolder{
ImageView imageView;
TextView titleView;
TextView subtitleView;
ViewGroup cell;
ViewGroup cellContainer;
Button button1;
Button button2;
MXGroupChatSession selectedSession;
private GestureDetectorCompat gestureDetector;
float totalx;
float buttonTotalWidth;
Boolean open=false;
Boolean isScrolling=false;
public ChatViewHolder(View itemView) {
super(itemView);
cell=(ViewGroup) itemView.findViewById(R.id.chat_row_cell);
cellContainer=(ViewGroup) itemView.findViewById(R.id.chat_row_container);
button1=(Button) itemView.findViewById(R.id.slide_button_1);
button2=(Button) itemView.findViewById(R.id.slide_button_2);
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
listener.utilityButton1Clicked(selectedSession);
}
});
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
listener.utilityButton2Clicked(selectedSession);
}
});
ViewTreeObserver vto = cellContainer.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
buttonTotalWidth = button1.getWidth()+button2.getWidth();
}
});
this.titleView=(TextView)itemView.findViewById(R.id.chat_title);
subtitleView=(TextView)itemView.findViewById(R.id.chat_subtitle);
imageView=(ImageView)itemView.findViewById(R.id.chat_image);
gestureDetector=new GestureDetectorCompat(context,new ChatRowGesture());
cell.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if(gestureDetector.onTouchEvent(event)){
return true;
}
if(event.getAction() == MotionEvent.ACTION_UP) {
if(isScrolling ) {
isScrolling = false;
handleScrollFinished();
};
}
else if(event.getAction() == MotionEvent.ACTION_CANCEL){
if(isScrolling ) {
isScrolling = false;
handleScrollFinished();
};
}
return false;
}
});
}
public class ChatRowGesture extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onSingleTapUp(MotionEvent e) {
if (!open){
listener.cellClicked(selectedSession);
}
return true;
}
@Override
public boolean onDown(MotionEvent e) {
return true;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
isScrolling=true;
totalx=totalx+distanceX;
freescroll(totalx);
return true;
}
}
void handleScrollFinished(){
if (open){
if (totalx>2*buttonTotalWidth/3){
slideLeft();
totalx=buttonTotalWidth;
}else{
slideRight();
totalx=0;
}
}else{
if (totalx>buttonTotalWidth/3){
slideLeft();
totalx=buttonTotalWidth;
}else{
slideRight();
totalx=0;
}
}
}
void slideRight(){
TransitionManager.beginDelayedTransition(cellContainer);
ViewGroup.MarginLayoutParams params;
params=(ViewGroup.MarginLayoutParams) cell.getLayoutParams();
params.setMargins(0,0,0,0);
cell.setLayoutParams(params);
open=false;
}
void slideLeft(){
TransitionManager.beginDelayedTransition(cellContainer);
ViewGroup.MarginLayoutParams params;
params=(ViewGroup.MarginLayoutParams) cell.getLayoutParams();
params.setMargins(((int)buttonTotalWidth*-1),0,(int)buttonTotalWidth,0);
cell.setLayoutParams(params);
open=true;
}
void freescroll(float x){
if (x<buttonTotalWidth && x>0){
int xint=(int)x;
ViewGroup.MarginLayoutParams params;
params=(ViewGroup.MarginLayoutParams) cell.getLayoutParams();
params.setMargins(params.leftMargin,0,xint,0);
cell.setLayoutParams(params);
}
}
}
Hope this helps someone!!
It's a lose of time to implement from scratch this functionality. I implemented the library recommended by SalutonMondo and I am very satisfied. It is very simple to use and very quick. I improved the original library and I added a new click listener for item click. Also I added font awesome library (http://fortawesome.github.io/Font-Awesome/) and now you can simply add a new item title and specify the icon name from font awesome.
Here is the github link
EDIT: between other options there's a nice library that could solve your issue: https://github.com/daimajia/AndroidSwipeLayout
An app is available that demonstrates a listview that combines both swiping-to-delete and dragging to reorder items. The code is based on Chet Haase's code for swiping-to-delete and Daniel Olshansky's code for dragging-to-reorder.
Chet's code deletes an item immediately. I improved on this by making it function more like Gmail where swiping reveals a bottom view that indicates that the item is deleted but provides an Undo button where the user has the possibility to undo the deletion. Chet's code also has a bug in it. If you have less items in the listview than the height of the listview is and you delete the last item, the last item appears to not be deleted. This was fixed in my code.
Daniel's code requires pressing long on an item. Many users find this unintuitive as it tends to be a hidden function. Instead, I modified the code to allow for a "Move" button. You simply press on the button and drag the item. This is more in line with the way the Google News app works when you reorder news topics.
The source code along with a demo app is available at: https://github.com/JohannBlake/ListViewOrderAndSwipe
Chet and Daniel are both from Google.
Chet's video on deleting items can be viewed at: https://www.youtube.com/watch?v=YCHNAi9kJI4
Daniel's video on reordering items can be viewed at: https://www.youtube.com/watch?v=_BZIvjMgH-Q
A considerable amount of work went into gluing all this together to provide a seemless UI experience, so I'd appreciate a Like or Up Vote. Please also star the project in Github.
see there link was very nice and simple. its working fine... u don't want any library its working fine. click here
OnTouchListener gestureListener = new View.OnTouchListener() {
private int padding = 0;
private int initialx = 0;
private int currentx = 0;
private ViewHolder viewHolder;
public boolean onTouch(View v, MotionEvent event) {
if ( event.getAction() == MotionEvent.ACTION_DOWN) {
padding = 0;
initialx = (int) event.getX();
currentx = (int) event.getX();
viewHolder = ((ViewHolder) v.getTag());
}
if ( event.getAction() == MotionEvent.ACTION_MOVE) {
currentx = (int) event.getX();
padding = currentx - initialx;
}
if ( event.getAction() == MotionEvent.ACTION_UP ||
event.getAction() == MotionEvent.ACTION_CANCEL) {
padding = 0;
initialx = 0;
currentx = 0;
}
if(viewHolder != null) {
if(padding == 0) {
v.setBackgroundColor(0xFF000000 );
if(viewHolder.running)
v.setBackgroundColor(0xFF058805);
}
if(padding > 75) {
viewHolder.running = true;
v.setBackgroundColor(0xFF00FF00 );
viewHolder.icon.setImageResource(R.drawable.clock_running);
}
if(padding < -75) {
viewHolder.running = false;
v.setBackgroundColor(0xFFFF0000 );
}
v.setPadding(padding, 0,0, 0);
}
return true;
}
};
I had created a demo on my github which includes on swiping from right to left a delete button will appear and you can then delete your item from the ListView and update your ListView.