I know that this question has been asked many times, but the answers doesn't work for me. I am trying to use Horizontal placement. Here is my code:
public class CalendarDaysAdapter extends RecyclerView.Adapter<CalendarDaysAdapter.MyViewHolder> {
private ArrayList<String> list;
public CalendarDaysAdapter(ArrayList<String> list)
{
this.list = list;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.fragment_calendar_days_item, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
String day = list.get(position);
holder.daystxt.setText(day);
}
#Override
public int getItemCount() {
return list.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView daystxt;
public MyViewHolder(View view) {
super(view);
daystxt = (TextView) view.findViewById(R.id.daystxt);
}
}
}
fragment_calendar_days_item xml:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="50dp"
android:gravity="center">
<TextView
android:id="#+id/daystxt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="MON"
android:textSize="20sp"/>
</RelativeLayout>
</LinearLayout>
I tried every combination of wrap_content - match_parent, also on the RecyclerView xml in parent Activity, but only the first item is showing. I have used breakpoints to see if the data of the list are there, and they are.
So what I am missing ?
Change your fragment_calendar_days_item height and width to android:layout_height="wrap_content" and android:layout_width="wrap_content"
it will solve your issue
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="50dp"
android:gravity="center">
<TextView
android:id="#+id/daystxt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="MON"
android:textSize="20sp"/>
</RelativeLayout>
</LinearLayout>
Try this for your
fragment_calendar_days_item xml:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="50dp"
android:gravity="center">
<TextView
android:id="#+id/daystxt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="MON"
android:textSize="20sp"/>
</RelativeLayout>
</LinearLayout>
I think what you want to do is show that "n" elements and the rest must be scrollable.
The solution of setting the hard value is not the best. it's not generic. I think that my solution will fit very well in any case. ;-)
For that I propose you a solution
First determine and create a MAX_ITEMS variable
Kotlin
recycler.addOnLayoutChangeListener { v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom ->
if (recycler.layoutManager.itemCount > maxItemVisible) {
val height = (0 until maxItemVisible).sumBy { recycler.layoutManager.findViewByPosition(it).height }
recycler.layoutParams = LayoutParams(recycler.width, height)
}
}
Java
mRecycler.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
#Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
if (mRecycler.getLayoutManager().getItemCount() > maxItemVisible) {
int height = 0;
for (int i = 0; i < maxItemVisible; i++){
height += mRecycler.getLayoutManager().findViewByPosition(i).getHeight()
}
mRecycler.setLayoutParams(new LinearLayout.LayoutParams(mRecycler.getWidth(), height));
}
}
});
Hoping to have answered your need
Related
I have to do something like Instagram does. I have a horizontal RecyclerView for stories, and, below, a vertical RecyclerView for feed. I want to accomplish the same scroll behavior(the stories should go with feed at scroll, not stay on top as fixed). The only solution I found is NestedScrollView but it makes extremely bad performance for RecyclerViews, my screen freezes almost forever. I tried a lot of tricks found here like nestedScrollEnabled, autoLayoutMeasure etc. but nothing worked. Thanks.
Sorry if this explanation is too abstract. Let me know if you need me to be more explicit.
public class VerticalAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
private static final int TYPE_HEADER = 0;
private static final int TYPE_POST = 1;
List<Post> posts;
List<FeedItems> feedItems; //this array is going to populate the horizontal recycler view. Notice that is passed it on the adapter constructor
public VerticalAdapter(List<Post> posts,List<FeedItems> feedItems) {
this.posts = posts;
this.feedItems = feedItems;
}
public void notifyFeedChanged(List<FeedItems> newFeedItems){
this.feedItems.clear();
this.feedItems = newFeedItems; //set the new feed items in the array
notifyItemChanged(0); //tell the main recycler view "Hey, update your first position". This will cause the onBindViewHolder to be called again an thus, the new items will be set into the horizontal recycler view
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == TYPE_HEADER)
return new HeaderViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.your_header_layout, false));
else if (viewType == TYPE_POST)
return new PostViewHolder (LayoutInflater.from(parent.getContext()).inflate(R.layout.your_post_layout, false));
throw new RuntimeException("Don't know this type");
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof HeaderViewHolder){
//set adapter for the horizontal recycler view
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(((HeaderViewHolder) holder).recyclerView.getContext(),LinearLayoutManager.HORIZONTAL, false)
((HeaderViewHolder) holder).recyclerView.setLayoutManager(linearLayoutManager);
if (((HeaderViewHolder) holder).recyclerView.getAdapter() == null){ //only create the adapter the first time. the following times update the values
AnotherAdaterYouNeedToCreateForTheHorizontalRecyclerView adapter = new AnotherAdaterYouNeedToCreateForTheHorizontalRecyclerView(feedItems);
((HeaderViewHolder) holder).recyclerView.setAdapter(adapter);
}else {
((HeaderViewHolder) holder).recyclerView.getAdapter().notifyDataSetChanged();
}
}else if (holder instanceof PostViewHolder){
//just do the normal post binding
}
}
#Override
public int getItemCount() {
return posts.size() + 1; // +1 because of the header
}
#Override
public int getItemViewType(int position) {
return position == 0 ? TYPE_HEADER : TYPE_POST;
}
private class HeaderViewHolder extends RecyclerView.ViewHolder{
RecyclerView recyclerView;
public HeaderViewHolder(View itemView) {
super(itemView);
recyclerView = itemView.findViewById(R.id.the_recycler_view_id_on_the_heaedr_layout_file);
}
}
private class PostViewHolder extends RecyclerView.ViewHolder{
ImageView imageView;
public PostViewHolder(View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.post_image_view_or_whatever);
}
}}
So, your vertical recyclerview has the Post items (or whatever your post class is) drawn vertically, that's the easy thing to achieve. Now, for the horizontal view, you should implement a recyclerview header (check my Adapter example). The header layout will have another horizontal recyclerview.
In your XML Layout try keeping both the "header" recycler view and "Post" recycler view in a nested scroll view. It works for me.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFFFFF">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="16dp"
android:paddingTop="8dp"
android:text="Welcome"
android:textAppearance="#style/TextAppearance.AppCompat.Large"
android:textColor="#000000"
android:textSize="24sp"
android:textStyle="bold" />
<TextView
android:id="#+id/date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="16dp"
android:paddingTop="8dp"
android:textAppearance="#style/TextAppearance.AppCompat.Body1"
android:textColor="#color/black_80" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:orientation="horizontal" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rvv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
I'm working on a chatting application. All I did is i can get api response successfully and can show them serially like this
This is id of sender and reciver
This is the messages
For doing this I created an adapter which code is something like this.
public class Single_chat_adapter extends RecyclerView.Adapter<Single_chat_adapter.Single_chat_adapterViewHolder>{
private List<Datum2> data;
private int rowLayout;
private Context context;
public Single_chat_adapter(List<Datum2> data, int rowLayout, Context context) {
this.data = data;
this.rowLayout = rowLayout;
this.context = context;
}
#Override
public Single_chat_adapterViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.card2, parent, false);
return new Single_chat_adapterViewHolder(view); }
#Override
public void onBindViewHolder(Single_chat_adapterViewHolder holder, int position) {
holder.single_msg.setText(data.get(position).getMsg());
}
#Override
public int getItemCount() {
return data.size();
}
public class Single_chat_adapterViewHolder extends RecyclerView.ViewHolder {
TextView single_msg;
public Single_chat_adapterViewHolder(View itemView) {
super(itemView);
single_msg =itemView.findViewById(R.id.userNameTV);
}
}
}
Here I use a single view which is card2.xml. But all I need to do is set senders message in the left side and receiver message in other side.
What To do?
To achieve what you have explained, Create two views in card2.xml(one at the left and the other in the right). I have created one for you.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:layout_marginBottom="6dp"
android:layout_marginTop="4dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:layout_width="40dp"
android:id="#+id/avatar"
android:background="#drawable/circle_stroke"
android:layout_marginStart="5dp"
android:layout_marginEnd="5dp"
android:src="#drawable/useric"
android:layout_height="40dp" />
<RelativeLayout
android:layout_toEndOf="#+id/avatar"
android:id="#+id/msg_back"
android:layout_marginBottom="5dp"
android:layout_gravity="center_vertical"
android:background="#drawable/message_bubble_accent"
android:layout_width="match_parent"
android:padding="10dp"
android:orientation="vertical"
android:layout_height="wrap_content">
<TextView
android:textSize="17sp"
android:id="#+id/user_text"
android:layout_width="wrap_content"
android:textColor="#color/white"
android:text="Hello world how are you?"
android:layout_height="wrap_content" />
<TextView
android:textSize="12sp"
android:layout_below="#+id/user_text"
android:id="#+id/chat_time"
android:textColor="#color/dark"
android:text="3:33pm"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
<ImageView
android:layout_width="40dp"
android:id="#+id/avatar2"
android:layout_alignParentEnd="true"
android:layout_below="#+id/msg_back"
android:background="#drawable/circle_stroke"
android:layout_marginStart="5dp"
android:layout_marginEnd="5dp"
android:src="#drawable/useric"
android:layout_height="40dp" />
<RelativeLayout
android:layout_toStartOf="#+id/avatar2"
android:layout_below="#+id/msg_back"
android:id="#+id/msg_back2"
android:layout_gravity="center_vertical"
android:background="#drawable/message_bubble_white"
android:layout_width="match_parent"
android:padding="10dp"
android:orientation="vertical"
android:layout_height="wrap_content">
<TextView
android:textSize="17sp"
android:id="#+id/user_text2"
android:layout_width="wrap_content"
android:textColor="#color/white"
android:text="Hello world how are you?"
android:layout_height="wrap_content" />
<TextView
android:layout_below="#+id/user_text2"
android:id="#+id/chat_time2"
android:textColor="#color/dark"
android:text="3:33pm"
android:textSize="12sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:layout_alignParentEnd="true"
android:layout_below="#+id/user_text2"
android:text="#string/sent"
android:width="20dp"
android:textAppearance="?android:textAppearanceSmall"
android:layout_width="20dp"
android:layout_height="20dp"
android:textColor="#android:color/holo_green_light"/>
</RelativeLayout>
</RelativeLayout>
</LinearLayout>
Modify your onBindViewHolder and add the condition that will check if the message is coming from another user or not. Like this...
#Override
public void onBindViewHolder(Single_chat_adapterViewHolder holder, int position) {
Datum2 datum = data.get(position);
holder.single_msg.setText(datum.getMsg());
int msgId = datum.getMsgId();
if (msgId == datum.getUserMsgId) {
//Do everything pertaining to this user here
holder.rightBubble.setText(single_msg);
//holder.rightAvatar.setText(single_msg) //For setting image
} else {
holder.leftBubble.setText(single_msg);
}
}
Make sure you reference leftBubble and rightBubble from you ViewHolder, and set the current userMsgid from the activity that is using this adapter.
You have to create 2 viewtype and two xml for them additionally and load them in a single adapter. Follow the link may help you.
Android Chat Tutorial: Building a Messaging UI
1) Create 2 views in card2.xml
2) One for left and another for right
3) Put condition in your onBindViewHolder, if message is from senders make left view visible and hide right view and same thing for right view also.
You can put condition inside onCreateViewHolder, this will let you to swap the layout (xml file)
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
int layout = -1;
switch (viewType) {
case Message.TYPE_MESSAGE:
layout = R.layout.item_message;
break;
case Message.TYPE_LOG:
layout = R.layout.item_log;
break;
case Message.TYPE_ACTION:
layout = R.layout.item_action;
break;
}
View v = LayoutInflater
.from(parent.getContext())
.inflate(layout, parent, false);
return new ViewHolder(v);
}
You can change viewtype from this method
#Override
public int getItemViewType(int position) {
// Just as an example, return 0 or 2 depending on position
// Note that unlike in ListView adapters, types don't have to be contiguous
return position % 2 * 2;
}
I have a list of 100 items. I'm using a recyclerview with custom adapter.
It seems that all the items are load in the same times which cause OOM because I'am loading big images.
I have no problem with listview because listview does not load everything at once.
I heard that recyclerview load everything at once on lollipop, but how can I fix that?
public class ProductAdapter extends RecyclerView.Adapter<ProductViewHolder> {
List<Produit> list;
private Context ac;
private int nbColumn;
public ProductAdapter(List<Produit> list, Context ac)
{
this.list = list;
this.ac = ac;
this.nbColumn = 2;
}
public ProductAdapter(List<Produit> list, Context ac, int nbColumn)
{
this.list = list;
this.ac = ac;
this.nbColumn = nbColumn;
}
#Override
public ProductViewHolder onCreateViewHolder(ViewGroup viewGroup, int itemType) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_product,viewGroup,false);
return new ProductViewHolder(view);
}
public void setNbColumn(int nb)
{
this.nbColumn = nb;
}
#Override
public void onBindViewHolder(final ProductViewHolder myViewHolder, int position) {
if (list != null) {
System.out.println("LOAD ITEM!!!!!!!!!!!!");
final Produit myObject = list.get(position);
myViewHolder.bind(myObject);
}
}
#Override
public int getItemCount() {
return list.size();
}
}
without start scrolling the output is
I/System.out: LOAD ITEM!!!!!!!!!!!!!!!!!
X100 times
UPDATE :
this is the code of my layout
<?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.support.v4.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="wrap_content"
>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:layout_width="match_parent"
>
<TextView
android:id="#+id/cat"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="This is a title"
android:padding="10dp"
android:gravity="center"
android:textColor="#color/black"
android:textStyle="bold"
android:textSize="17dp"
/>
<ImageView
android:layout_width="25dp"
android:layout_height="25dp"
android:src="#drawable/list1_unselected"
android:id="#+id/list1"
android:layout_below="#+id/cat"
android:paddingLeft="10dp"
android:clickable="true"
/>
<ImageView
android:layout_width="25dp"
android:layout_height="25dp"
android:src="#drawable/list2"
android:paddingLeft="10dp"
android:id="#+id/list2"
android:layout_below="#+id/cat"
android:layout_toRightOf="#+id/list1"
android:clickable="true"
/>
<android.support.v7.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/listingGrid"
android:layout_width="match_parent"
android:nestedScrollingEnabled="false"
android:layout_below="#+id/list2"
android:layout_height="match_parent"/>
</RelativeLayout>
</android.support.v4.widget.NestedScrollView>
</RelativeLayout>
I partially figured out my problem. After removing the NestedScrollView, the behavior of my Recyclerview works as expected. The thing is how can I combine both NestedScrollView and RecyclerView?
Thank you
Set android:layout_height of your RecyclerView to match_parent or some constant value.
EDIT:
Obviously it didn't help, since you have it all wrapped in NestedScrollView.
I would suggest removing NestedScrollView and combining all views from your RelativeLayout into another layout that you would use as header in your RecyclerView
Replace if (list != null) with if (myViewHolder != null) and it will work as intended
I'm using android:windowSoftInputMode="stateHidden|adjustResize" to push the EditText and RecyclerView up when keyboard appears, but it only works on the EditText. RecyclerView stays in the same position (thus some elements are not visible). What am I doing wrong?
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="co.bla.bla.ChatActivity"
android:id="#+id/chat_root">
<include android:id="#+id/toolbar" layout="#layout/toolbar"/>
<android.support.v7.widget.RecyclerView
android:id="#+id/chat_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/message_input_wrapper"
android:scrollbars="vertical"
android:paddingBottom="20dp"
android:layout_below="#id/toolbar"
/>
<LinearLayout
android:id="#+id/message_input_wrapper"
android:layout_width="match_parent"
android:layout_height="60dp"
android:padding="6dp"
android:orientation="horizontal"
android:weightSum="4"
android:background="#android:color/white"
android:layout_alignParentBottom="true">
<EditText
android:id="#+id/message_input"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="#string/chat_input_hint"
android:layout_gravity="center_vertical"
android:layout_weight="3"
android:background="#android:color/transparent"/>
<Button
android:id="#+id/message_send_button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="#string/chat_button_text"
android:layout_weight="1"
android:onClick="onButtonClicked"/>
</LinearLayout>
</RelativeLayout>
I don't know how adjustResize exactly works, but I assume when using android:layout_above in this case, the RecyclerView and LinearLayout "stick" together and should be pushed up together?
In your activity manifest:
android:windowSoftInputMode="adjustResize"
Then add an OnLayoutChangeListener to yout recyclerView:
recyclerView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
#Override
public void onLayoutChange(View v, int left, int top, int right,int bottom, int oldLeft, int oldTop,int oldRight, int oldBottom)
{
recyclerView.scrollToPosition(recyclerView.getAdapter().getItemCount()-1);
}
});
This works for me :)
set a soft keyboard listener:
private boolean mLastKeyBoardVisible = false;
private void addOnSoftKeyBoardVisibleListener(final OnSoftKeyBoardVisibleListener listener) {
final View decorView = getWindow().getDecorView();
decorView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
Rect rect = new Rect();
decorView.getWindowVisibleDisplayFrame(rect);
int displayHight = rect.bottom - rect.top;
int hight = decorView.getHeight();
boolean visible = (double) displayHight / hight < 0.8;
if(visible != mLastKeyBoardVisible){
listener.onSoftKeyBoardVisible(visible);
}
mLastKeyBoardVisible = visible;
}
});
}
private OnSoftKeyBoardVisibleListener onSoftKeyBoardVisibleListener = new OnSoftKeyBoardVisibleListener() {
#Override
public void onSoftKeyBoardVisible(boolean visible) {
scrollToBottom(visible);
}
};
synchronized private void scrollToBottom(boolean visible) {
if (visible) {
if (mMessageList.size() != messageAdapter.getItemCount() && mMessageList.size() > 0) {
messageAdapter.notifyDataSetChanged();
messageListView.scrollToPosition(mMessageList.size() - 1);
} else if (mMessageList.size() > 0) {
messageListView.scrollToPosition(mMessageList.size() - 1);
}
}
}
I have a recycler view in which i want to show another layout on swiping item view which is hidden behind the current layout. In short i want to achieve something like below image.
The problem with my code is that the the whole view is swiped, but i want to swipe only to the width of the hidden layout.
Code in Activity
final ItemTouchHelper.Callback simpleItemTouchCallback = new ItemTouchHelper.Callback() {
#Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
if (viewHolder.getAdapterPosition() < target.getAdapterPosition()) {
for (int i = viewHolder.getAdapterPosition(); i < target.getAdapterPosition(); i++) {
Collections.swap(myDataset, i, i + 1);
}
} else {
for (int i = viewHolder.getAdapterPosition(); i > target.getAdapterPosition(); i--) {
Collections.swap(myDataset, i, i - 1);
}
}
mAdapter.notifyItemMoved(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
#Override
public boolean isLongPressDragEnabled() {
return true;
}
#Override
public boolean isItemViewSwipeEnabled() {
return true;
}
#Override
public void onSwiped(final RecyclerView.ViewHolder viewHolder, final int swipeDir) {
}
#Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
View itemView = viewHolder.itemView;
ImageView delete_image=(ImageView) itemView.findViewById(R.id.delete_image);
delete_image.setY(itemView.getTop());
if(isCurrentlyActive) {
delete_image.setVisibility(View.VISIBLE);
}else{
delete_image.setVisibility(View.GONE);
}
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
#Override
public int getMovementFlags(RecyclerView recyclerView,
RecyclerView.ViewHolder viewHolder) {
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
return makeMovementFlags(dragFlags, swipeFlags);
}
};
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback);
itemTouchHelper.attachToRecyclerView(mRecyclerView);
Custom Layout for recylerview item
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:fresco="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingBottom="#dimen/padding_xsmall">
<LinearLayout
android:id="#+id/top_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:background="#color/very_light_grey"
android:orientation="horizontal"
android:paddingBottom="#dimen/padding_xlarge"
android:paddingEnd="#dimen/padding_small"
android:paddingLeft="#dimen/padding_xlarge"
android:paddingRight="#dimen/padding_small"
android:paddingStart="#dimen/padding_xlarge"
android:paddingTop="#dimen/padding_xlarge">
<com.facebook.drawee.view.SimpleDraweeView
android:id="#+id/friend_image"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="center_vertical"
fresco:placeholderImage="#drawable/user_placeholder"
fresco:roundAsCircle="true"
fresco:roundedCornerRadius="50dp"
fresco:roundingBorderColor="#android:color/white"
fresco:roundingBorderWidth="2dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="#dimen/margin_small"
android:layout_marginLeft="#dimen/margin_small"
android:layout_marginRight="#dimen/margin_small"
android:layout_marginStart="#dimen/margin_small"
android:orientation="vertical">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<bi.it.com.bio.textview.CustomTextView
android:id="#+id/friend_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_toLeftOf="#+id/badge_text"
android:text="John"
android:textSize="#dimen/text_size_medium" />
<bi.it.com.bio.textview.CustomTextView
android:id="#+id/badge_text"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_alignParentRight="true"
android:background="#drawable/badgeicon"
android:gravity="center"
android:text="24"
android:textColor="#android:color/white"
android:textSize="#dimen/text_size_xxsmall" />
</RelativeLayout>
<bi.it.com.bio.textview.CustomTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="this is message from john"
android:textSize="#dimen/text_size_xsmall" />
</LinearLayout>
</LinearLayout>
<ImageView
android:id="#+id/delete_image"
android:paddingLeft="#dimen/padding_large"
android:paddingStart="#dimen/padding_large"
android:paddingEnd="#dimen/padding_large"
android:paddingRight="#dimen/padding_large"
android:paddingTop="#dimen/padding_small"
android:paddingBottom="#dimen/padding_small"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="#color/red_color_list"
android:src="#drawable/ic_delete_frd"
android:layout_gravity="end|right"
android:visibility="gone"/>
</FrameLayout>
I do not want to use any library. Any help is really appreciated.
Thanks in advance.
You can do this with a ViewPager and a PagerAdapter. Your PagerAdapter will have two pages: your "main" full-width view and a second view that has your operation buttons.
The key is to override getPageWidth() in your adapter and return 1.0 for your main view and some fraction for your second view. The fraction is calculated by dividing the desired width of the view by the width of the ViewPager.
When the user swipes, the second view can't take up the entire screen, so the first view is still partially shown, as in your animated image.
With the ViewHolder referencing the ViewPager and the ViewPager referencing the PagerAdapter, you can even recycle the adapters right along with the ViewPagers.
Actually there is a hidden useful class in the Android sdk called ViewDragHelper
You can implement the swipe to show button easily with little code. However, ViewDragHelper is not well documented, but I found this link contains a very useful tutorial for implementing it: http://fedepaol.github.io/blog/2014/09/01/dragging-with-viewdraghelper/