Twitter like conversation view using RecyclerView and RelativeLayout - android

I am trying to implement an Activity similar to Twitter's tweet page. When a tweet is a reply to another tweet, if you scroll up, you can see the original tweet being replied to, which is initially hidden above the screen. Here is the code I have:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<include layout="#layout/toolbar"/>
<android.support.v7.widget.RecyclerView
android:id="#+id/in_reply_to"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginLeft="5dp"
android:layout_marginStart="5dp"
android:layout_marginRight="5dp"
android:layout_marginEnd="5dp"
>
<ImageView
android:id="#+id/user_image"
android:layout_width="65dp"
android:layout_height="65dp"
android:layout_marginLeft="10dp"
android:layout_marginStart="10dp"
android:layout_marginTop="5dp"
android:scaleType="fitXY"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
/>
<TextView
android:id="#+id/real_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginStart="10dp"
android:layout_marginTop="5dp"
android:textSize="18sp"
android:layout_toRightOf="#id/user_image"
android:layout_toEndOf="#id/user_image"
/>
<TextView
android:id="#+id/username"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginStart="10dp"
android:layout_marginTop="0dp"
android:layout_below="#id/real_name"
android:layout_toRightOf="#id/user_image"
android:layout_toEndOf="#id/user_image"
android:textSize="15sp"
/>
<TextView
android:id="#+id/tweet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_below="#id/user_image"
android:textSize="18sp"
/>
</RelativeLayout>
</LinearLayout>
Unfortunately, in this code only the original tweet shows up and the RecyclerView remains hidden for some reason. Could someone help me out how to position them in such a way that the RecyclerView is hidden above the screen and is visible only if you scroll up?

Decided to expand on my comment above with code. You can have multiple ViewHolders in one RecyclerView.Adapter, each can have different layouts (R.layout.original_tweet and R.layout.other_tweets here). getItemViewType() sets which viewholder to show. I didn't test or run the code so there might be a few bugs, but it should give you an idea at least.
public class MyAdapter
extends RecyclerView.Adapter {
private static final int ORIGINAL_TWEET = 0;
private static final int OTHER_TWEETS = 1;
private List<String> mTweets;
public MyAdapter(List<String> tweets) {
mTweets = tweets;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view;
if (ORIGINAL_TWEET == viewType) {
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.original_tweet, parent, false);
return new OriginalTweetViewHolder(view);
} else {
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.other_tweets, parent, false);
return new OtherTweetsViewHolder(view);
}
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof OriginalTweetViewHolder) {
// populate with tweet data
} else if (holder instanceof OtherTweetsViewHolder) {
// populate with tweet data
}
}
#Override
public int getItemCount() {
return mTweets.size();
}
#Override
public int getItemViewType(int position) {
if (position == mTweets.size() - 1) {
// At bottom position
return ORIGINAL_TWEET;
} else {
return OTHER_TWEETS;
}
}
}
public static class OriginalTweetViewHolder extends RecyclerView.ViewHolder {
// ViewHolder fields
public OriginalTweetViewHolder(View view) {
super(view);
}
}
public static class OtherTweetsViewHolder extends RecyclerView.ViewHolder {
// ViewHolder fields
public OtherTweetsViewHolder(View view) {
super(view);
}
}

Related

Bug in recycle grid. Changing UI without click randomly

I have a recycler inside fragment in view pager.
The problem that it put likes on user accounts in UI randomly but in DB everything is fine.
In logs, I see that random is not influence on BD. So the bug is only in UI part. After the refresh of the list, it can appear again and after that disappear.
I would like to share code but I already don't have an I idea where the problem could be. It might be in adapter/refresh list listener / XML or any other places. Please let me know what part of the code you need and I will provide it. Maybe it is a bug of recycler as itself and I can't fix it.
Adapter class code:
public class SearchAdapter extends RecyclerView.Adapter<SearchAdapter.UserViewHolder>{
private List<FsUser> fsUserList = new ArrayList<>();
private OnItemClickListener.OnItemClickCallback onItemClickCallback;
private OnItemClickListener.OnItemClickCallback onChatClickCallback;
private OnItemClickListener.OnItemClickCallback onLikeClickCallback;
private Context context;
public SearchAdapter(OnItemClickListener.OnItemClickCallback onItemClickCallback,
OnItemClickListener.OnItemClickCallback onChatClickCallback,
OnItemClickListener.OnItemClickCallback onLikeClickCallback) {
this.onItemClickCallback = onItemClickCallback;
this.onChatClickCallback = onChatClickCallback;
this.onLikeClickCallback = onLikeClickCallback;
}
public void addUsers(List<FsUser> userList) {
fsUserList.addAll(userList);
notifyItemRangeInserted(fsUserList.size() - userList.size(), fsUserList.size());
}
public void clearData(){
fsUserList.clear();
notifyDataSetChanged();
}
#NonNull
#Override
public UserViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
context = parent.getContext();
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_user, parent, false);
return new UserViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull UserViewHolder holder, int position) {
FsUser fsUser = fsUserList.get(position);
holder.bind(fsUser, position);
}
#Override
public int getItemCount() {
return fsUserList.size();
}
public String getLastItemId(){
return fsUserList.get(fsUserList.size() - 1).getUid();
}
class UserViewHolder extends RecyclerView.ViewHolder {
RelativeLayout container;
ImageView imageView, like, chat;
TextView name, country;
private LottieAnimationView animationView;
UserViewHolder(View itemView) {
super(itemView);
context = itemView.getContext();
container = itemView.findViewById(R.id.item_user_container);
imageView = itemView.findViewById(R.id.user_img);
like = itemView.findViewById(R.id.search_btn_like);
chat = itemView.findViewById(R.id.search_btn_chat);
name = itemView.findViewById(R.id.user_name);
country = itemView.findViewById(R.id.user_country);
animationView = itemView.findViewById(R.id.lottieAnimationView);
}
void bind(FsUser fsUser, int position){
ViewCompat.setTransitionName(imageView, fsUser.getName());
if (FirebaseUtils.isUserExist() && fsUser.getUid() != null) {
new FriendRepository().isLiked(fsUser.getUid(), flag -> {
if (flag) {
like.setBackground(ContextCompat.getDrawable(context, R.drawable.ic_favorite));
animationView.setVisibility(View.VISIBLE);
}
});
}
if(fsUser.getUid() != null) {
chat.setOnClickListener(new OnItemClickListener(position, onChatClickCallback));
like.setOnClickListener(new OnItemClickListener(position, onLikeClickCallback));
}
imageView.setOnClickListener(new OnItemClickListener(position, onItemClickCallback));
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
if(fsUser.getImage().equals("default")){
Glide.with(context).load(context.getResources().getDrawable(R.drawable.default_avatar)).into(imageView);
} else {
Glide.with(context).load(fsUser.getImage()).thumbnail(0.5f).into(imageView);
}
name.setText(fsUser.getName());
country.setText(fsUser.getCountry());
ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f).setDuration(500);
animator.addUpdateListener(valueAnimator ->
animationView.setProgress((Float) valueAnimator.getAnimatedValue()));
if (animationView.getProgress() == 0f) {
animator.start();
} else {
animationView.setProgress(0f);
}
}
}
}
And xml file of RecyclerView item:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/item_user_container"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.CardView
android:layout_width="#dimen/user_cv_width"
android:layout_height="#dimen/user_cv_height"
android:layout_margin="#dimen/dp4"
android:elevation="#dimen/dp4">
<RelativeLayout
android:id="#+id/item_user_main_relative_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<RelativeLayout
android:id="#+id/item_user_top_relative_container"
android:layout_width="#dimen/user_rl_width"
android:layout_height="#dimen/user_rl_height">
<ImageView
android:id="#+id/user_img"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="centerCrop"
android:src="#drawable/default_avatar" />
<RelativeLayout
android:id="#+id/item_user_top_relative"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/user_item_bg"
android:orientation="vertical">
<TextView
android:id="#+id/user_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/dp4"
android:textColor="#android:color/white"
android:textSize="#dimen/medium_text_size" />
<TextView
android:id="#+id/user_country"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#android:color/white"
android:layout_marginStart="#dimen/dp4"
android:textSize="#dimen/medium_text_size" />
</LinearLayout>
</RelativeLayout>
</RelativeLayout>
<RelativeLayout
android:id="#+id/item_user_bottom_relative_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:orientation="horizontal">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="#dimen/dp12">
<ImageView
android:id="#+id/search_btn_like"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/heart_outline"
android:contentDescription="#string/search_btn_like_desc"/>
<com.airbnb.lottie.LottieAnimationView
android:id="#+id/lottieAnimationView"
android:visibility="gone"
android:layout_width="#dimen/lottie_animation_view_size"
android:layout_height="#dimen/lottie_animation_view_size"
app:lottie_loop="true"
app:lottie_autoPlay="true"
app:lottie_fileName="like.json"/>
</RelativeLayout>
<ImageView
android:id="#+id/search_btn_chat"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="#dimen/dp12"
android:layout_weight="1"
android:src="#drawable/message_outline" />
</LinearLayout>
</RelativeLayout>
</RelativeLayout>
</android.support.v7.widget.CardView>
</RelativeLayout>
Override this two methods inside your adapter
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemViewType(int position) {
return position;
}

firebase recycler adapter with multiple views

I am trying to create my own custom firebase recycler adapter for a chat app. I want to inflate two views in the adapter, one for the sender and one for the receiver, but don't know how.
How shall I proceed with this?
To inflate different views in a RecyclerView, you need to implement this function in your adapter:
public int getItemViewType(int position);
This function is called before onCreateViewHolder and allows you to return an int depending on the type of the view you want to inflate. You can imagine using an enum to achieve this:
public enum TYPE {
SENDER,
RECEIVER
}
This way you will return an int depending on the type (with type.ordinal()).
Then you will get your type on the function onCreateViewHolder(ViewGroup parent, int viewType), you will be able to match you type again TYPE.values()[viewType]. This way you will return the inflated layout depending on the type.
Finally on onBindViewHolder(TimelineItemViewHolder holder, int position), you will be able either to:
Call getItemViewType(int position) to know how to cast and display your contents
Using instanceof be able to detect what is the type of the ViewHolder you are looking at
Use an abstract class, extending RecyclerView.ViewHolder shared by your two ViewHolder, allowing you to call a common function, like display(MyObject object)
private static final int RIGHT_MSG = 0;
private static final int LEFT_MSG = 1;
/*Viewholder for messages*/
public static class MessageViewHolder extends RecyclerView.ViewHolder {
public EmojiconTextView messageTextView;
public TextView messengerTextView;
public CircleImageView messengerImageView;
public ImageView sendimage;
public ImageView videoview;
public TextView messageTime;
public MessageViewHolder(View v) {
super(v);
messageTextView = (EmojiconTextView) itemView.findViewById(R.id.messageTextView);
messengerTextView = (TextView) itemView.findViewById(R.id.messengerTextView);
messengerImageView = (CircleImageView) itemView.findViewById(R.id.messengerImageView);
sendimage = (ImageView) itemView.findViewById(R.id.image);
videoview = (ImageView) itemView.findViewById(R.id.videoview);
messageTime = (TextView)itemView.findViewById(R.id.message_time);
}
/*Firebase recycler Adapter*/
mFirebaseAdapter = new FirebaseRecyclerAdapter < FriendlyMessage, MessageViewHolder > (
FriendlyMessage.class, R.layout.item_message, MessageViewHolder.class,
mFirebaseDatabaseReference.child(MESSAGES_CHILD)) {
#Override
protected void populateViewHolder(final MessageViewHolder viewHolder, final FriendlyMessage friendlyMessage, int position) {
mProgressBar.setVisibility(ProgressBar.INVISIBLE);
viewHolder.messageTextView.setText(friendlyMessage.getText());
viewHolder.messengerTextView.setText(friendlyMessage.getName());
viewHolder.messageTime.setText(DateFormat.format("MMM d, yyyy hh:mm a", friendlyMessage.getMessageTime()));
if (friendlyMessage.getPhotoUrl() == null) {
viewHolder.messengerImageView.setImageDrawable(ContextCompat.getDrawable(Chat.this,
R.drawable.ic_account_circle_black_36dp));
} else {
Glide.with(Chat.this).load(friendlyMessage.getPhotoUrl()).into(viewHolder.messengerImageView);
}
//for show send image
if (friendlyMessage.getImageUrl() == null) {
viewHolder.sendimage.setVisibility(View.GONE);
} else {
viewHolder.sendimage.setVisibility(View.VISIBLE);
Glide.with(Chat.this).load(friendlyMessage.getImageUrl()).into(viewHolder.sendimage);
}
//to show the videoattach in videoview
if (friendlyMessage.getVideoUrl() == null) {
Glide.with(Chat.this).load("").placeholder(R.drawable.videoiconcrop).into(viewHolder.videoview);
//viewHolder.videoview.setVisibility(View.GONE);
} else {
viewHolder.videoview.setVisibility(View.VISIBLE);
}
}
#Override
public MessageViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view;
if (viewType == RIGHT_MSG) {
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.activity_viewholder2, parent, false);
return new MessageViewHolder(view);
} else {
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.activity_viewholder1, parent, false);
return new MessageViewHolder(view);
}
}
#Override
public int getItemViewType(int position) {
FriendlyMessage model = getItem(position);
if (model.getContactNumber().equals(UserDetails.contact)) {
return RIGHT_MSG;
} else {
return LEFT_MSG;
}
}
};
/*Xml for messages i try to provide you one side try to make another side by using id same as this layout*/
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
xmlns:emojicon="http://schemas.android.com/apk/res-auto">
<de.hdodenhof.circleimageview.CircleImageView
android:layout_width="32dp"
android:layout_height="32dp"
android:id="#+id/messengerImageView"
android:src="#drawable/ic_account_circle_black_36dp"/>
<FrameLayout
android:id="#+id/incoming_layout_bubble"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="2dp"
android:layout_marginRight="60dp"
android:layout_alignParentLeft="true"
android:background="#drawable/balloon_incoming_normal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textStyle="bold|italic"
android:text="Receiver"
android:textSize="16dp"
android:layout_marginRight="50dp"
android:layout_marginBottom="10dp"
android:paddingBottom="12dp"
android:layout_marginLeft="6dp"
android:layout_above="#+id/messageTextView"
android:id="#+id/messengerTextView"
android:layout_weight="0"/>
<hani.momanii.supernova_emoji_library.Helper.EmojiconTextView
android:id="#+id/messageTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="6dp"
android:layout_marginTop="18dp"
android:layout_marginBottom="10dp"
android:autoLink="web"
android:text="Rahul Agrawal is a good boy but he does not know what he wants."
style="#style/chat_text_message_style"
emojicon:emojiconSize="30sp"/>
<TextView
android:id="#+id/message_time"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:paddingRight="5dp"
android:text="11:15 PM"
android:layout_marginLeft="6dp"
style="#style/chat_timings"
android:layout_gravity="bottom|right"/>
<ImageView
android:id="#+id/image"
android:layout_width="150dp"
android:layout_height="160dp"
android:src="#drawable/ic_account_circle_black_36dp"
android:contentDescription="send_photo"
android:visibility="gone"
android:layout_marginTop="23dp"
android:layout_marginBottom="18dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_gravity="center"
android:scaleType="fitXY"/>
<ImageView
android:layout_width="150dp"
android:layout_height="120dp"
android:id="#+id/videoview"
android:contentDescription="send_video"
android:src="#drawable/videoiconcrop"
android:layout_marginTop="20dp"
android:layout_marginBottom="18dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_gravity="center"
android:visibility="gone"
/>
</FrameLayout>
</LinearLayout>
may be this code help you out Happy Coding

How to remove redundancy item in CardView layout

I'm using a CardView Layout in a RecyclerView, JSON will load data and fill the adapter. My layout includes a ImageView, a TextView and everything is fine.
This is the Adapter class (UPDATED):
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {
private static final int TYPE_HEADER = 4;
private static final int TYPE_ITEM = 1;
Context context;
List<CarData> getCarData; // getDataAdapter
ImageLoader imageThumbLoader;
public RecyclerViewAdapter(List<CarData> getCarData, Context context){
super();
this.getCarData = getCarData;
this.context = context;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_items, parent, false);
ViewHolder viewHolder = new ViewHolder(v);
return viewHolder;
}
#Override
public void onBindViewHolder(ViewHolder Viewholder, int position) {
// if (!isPositionHeader(position)) {
CarData getCarData1 = getCarData.get(position - 1);
imageThumbLoader = ServerImageParseAdapter.getInstance(context).getImageLoader();
imageThumbLoader.get(getCarData1.getImageThumb(),
ImageLoader.getImageListener(
Viewholder.imageThumb,//Server Image
R.mipmap.ic_launcher,//Before loading server image the default showing image.
android.R.drawable.ic_dialog_alert //Error image if requested image dose not found on server.
)
);
Viewholder.imageThumb.setImageUrl(getCarData1.getImageThumb(), imageThumbLoader);
Viewholder.titleName.setText(getCarData1.getTitleName());
Viewholder.doorName.setText(Html.fromHtml("<b>Số cửa:</b> " + getCarData1.getDoorName()));
Viewholder.seatName.setText(Html.fromHtml("<b>Số ghế:</b> " + getCarData1.getSeatName()));
Viewholder.cityName.setText(Html.fromHtml(getCarData1.getCityName()));
Viewholder.districtName.setText(Html.fromHtml(getCarData1.getDistrictName()));
// }
}
public int getDataAdapter() {
return getCarData == null ? 0 : getCarData.size();
}
#Override
public int getItemViewType(int position) {
if (isPositionHeader(position)) {
return TYPE_HEADER;
}
return TYPE_ITEM;
}
#Override
public int getItemCount() {
return getDataAdapter(); // + 1
}
private boolean isPositionHeader(int position) {
return position == 0;
}
class ViewHolder extends RecyclerView.ViewHolder{
public TextView titleName;
public NetworkImageView imageThumb;
public TextView doorName;
public TextView seatName;
public TextView cityName;
public TextView districtName;
public ViewHolder(View itemView) {
super(itemView);
titleName = (TextView) itemView.findViewById(R.id.titleName);
imageThumb = (NetworkImageView) itemView.findViewById(R.id.imageThumb);
doorName = (TextView) itemView.findViewById(R.id.doorName);
seatName = (TextView) itemView.findViewById(R.id.seatName);
cityName = (TextView) itemView.findViewById(R.id.cityName);
districtName = (TextView) itemView.findViewById(R.id.districtName);
}
}
}
My layout:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/cardview1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardElevation="3dp"
card_view:contentPadding="3dp"
card_view:cardCornerRadius="3dp"
card_view:cardMaxElevation="3dp"
card_view:cardUseCompatPadding="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.android.volley.toolbox.NetworkImageView
android:id="#+id/imageThumb"
android:layout_width="400dp"
android:layout_height="230dp"
android:src="#mipmap/ic_launcher"
android:gravity="top"
android:scaleType="centerCrop"/>
<TextView
android:id="#+id/titleName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Image View"
android:layout_centerVertical="true"
android:layout_toRightOf="#+id/imageThumb"
android:layout_toEndOf="#+id/imageThumb"
android:layout_marginLeft="20dp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="2">
<TextView
android:id="#+id/doorName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"/>
<TextView
android:id="#+id/seatName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="2">
<TextView
android:id="#+id/cityName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"/>
<TextView
android:id="#+id/districtName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"/>
</LinearLayout>
<TextView
android:id="#+id/checkStatus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="KIỂM TRA TÌNH TRẠNG XE"
android:textColor="#color/color_primary_green_dark"
android:textStyle="bold"
android:textSize="12dp"
android:layout_centerVertical="true"
android:layout_toRightOf="#+id/textView_item32"
android:layout_toEndOf="#+id/textView_item32"
android:layout_marginLeft="20dp"/>
</LinearLayout>
But when I load data for the first time, there is a redundant item. Look at the following attachment:
The exception has happened when updated code:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: pl.michalz.hideonscrollexample, PID: 9794
java.lang.ArrayIndexOutOfBoundsException: length=18; index=-1
at java.util.ArrayList.get(ArrayList.java:310)
at pl.michalz.hideonscrollexample.RecyclerViewAdapter$override.onBindViewHolder(RecyclerViewAdapter.java:54)
at pl.michalz.hideonscrollexample.RecyclerViewAdapter$override.access$dispatch(RecyclerViewAdapter.java)
at pl.michalz.hideonscrollexample.RecyclerViewAdapter.onBindViewHolder(RecyclerViewAdapter.java:0)
at pl.michalz.hideonscrollexample.RecyclerViewAdapter.onBindViewHolder(RecyclerViewAdapter.java:20)
at android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:5768)
at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:5801)
How do I remove this redundant item in the CardView?
You have + 1 in your overridden getItemCount() method. It causes that you have one extra item in your list.
Then you have the method isPositionHeader, which you call in the onBindViewHolder method to find out, if the position is a header position. You are filling your cardview with data, if it is not the header position. But if it is the header position, you just skip it. So the first item, which is blank, is the header using the same cardview, as the other items, in fact.
Try to remove the + 1 and this condition if (!isPositionHeader(position)).

Group Recyclerview Items that getting from a Json

I am getting a Json output from the server.
This is my Json look like
{
"feed": [
{
"order_no": "70000004",
"quotation_no": "abc004a"
},
{
"order_no": "70000003",
"quotation_no": "abc003a"
},
{
"order_no": "70000001",
"quotation_no": "abc001a"
},
{
"order_no": "70000001",
"quotation_no": "abc001b"
}
]
}
I know how to populate this in a recyclerview. But what I want is grouping this json using order_no and populate. For example there are two 70000001. So i only need to show one 70000001 order no.
This is my custom row .xml file.
<?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="56dp"
android:background="#color/white">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="2dp"
android:layout_marginLeft="3dp"
android:layout_marginRight="3dp"
android:layout_marginTop="2dp"
android:background="#color/white">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#dbdbda"
android:orientation="vertical">
<TextView
android:id="#+id/parent_list_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="10dp"
android:text="Parent Title"
android:textColor="#color/primaryColorText"
android:textStyle="bold" />
<TextView
android:id="#+id/parent_q_item_one"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="2dp"
android:text="Q Title"
android:textColor="#color/secondaryColorText"
android:textSize="12sp" />
<TextView
android:id="#+id/parent_q_item_two"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="2dp"
android:text="Q Title"
android:textColor="#color/secondaryColorText"
android:textSize="12sp" />
</LinearLayout>
</android.support.v7.widget.CardView>
</RelativeLayout>
After grouping, I need to show only one order_no in parent_list_item (70000001) and under that I need to show one quotation_no in the first text view and second quotation_no in the second text view under same order_no
My adapter class
public class OrderQuatationHistory extends RecyclerView.Adapter<OrderQuatationHistory.ItemViewHolder> {
private LayoutInflater layoutInflater;
private ArrayList<OrderHistoryData> orderHistoryDataArrayList;
public OrderQuatationHistory() {
}
public OrderQuatationHistory(Context context) {
orderHistoryDataArrayList = new ArrayList<>();
layoutInflater = LayoutInflater.from(context);
}
public void setOrderHistoryList(ArrayList<OrderHistoryData> orderHistoryDataArrayList) {
this.orderHistoryDataArrayList = orderHistoryDataArrayList;
notifyItemRangeChanged(0, orderHistoryDataArrayList.size());
}
#Override
public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = layoutInflater.inflate(R.layout.custom_order_history_p_row, parent, false);
ItemViewHolder itemViewHolder = new ItemViewHolder(view);
return itemViewHolder;
}
#Override
public void onBindViewHolder(ItemViewHolder holder, int position) {
OrderHistoryData orderHistoryData = orderHistoryDataArrayList.get(position);
holder.orderNo.setText(orderHistoryData.getOrderNo());
holder.quotationNo.setText(orderHistoryData.getQuotationNo());
}
#Override
public int getItemCount() {
return orderHistoryDataArrayList.size();
}
public static class ItemViewHolder extends RecyclerView.ViewHolder {
private TextView orderNo,quotationNo;
public ItemViewHolder(View itemView) {
super(itemView);
orderNo = (TextView) itemView.findViewById(R.id.parent_list_item);
quotationNo = (TextView) itemView.findViewById(R.id.parent_q_list);
}
}
}
Try this... For avoiding of duplicate value,you can use this Method.
ArrayList<Integer> jSonOrder=new ArrayList();
int order_no= assigned values that you have retrieved from JSon.
if (!jSonOrder.contains(order_no)) {
jSonOrder.add(order_no);
}

StickyGridHeader custom header display wrong size

I use StickyGridHeader library with a custom header view like image below. The problem is this header only work when it's sticky on the top. On normal state, it show width size incorrectly, I think it caused by measuring header size from StickyGridHeadersGridView
Here is my header 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="wrap_content"
android:paddingBottom="10dp"
android:paddingTop="10dp" >
<TextView
android:id="#+id/tvHeaderName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_toLeftOf="#+id/tvHeaderDate"
android:minWidth="250dp"
android:paddingLeft="10dp"
android:text="aaa"
android:textColor="#color/white"/>
<TextView
android:id="#+id/tvHeaderDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:paddingRight="10dp"
android:text="aaa"
android:textColor="#color/white" />
<!--gray line-->
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_below="#+id/tvHeaderDate"
android:layout_marginTop="10dp"
android:background="#color/gray_line" />
</RelativeLayout>
And my adapter:
public class GalleryAdapter extends BaseAdapter implements StickyGridHeadersBaseAdapter {
// initialize image item ...
#Override
public int getCountForHeader(int position) {
return getHeaderItem(position).getImages().size();
}
public GalleryItem getHeaderItem(int position) {
return parents.get(position);
}
#Override
public View getHeaderView(int position, View view, ViewGroup parent) {
HeaderViewHolder viewHolder;
if (view == null) {
view = mInflater.inflate(R.layout.item_header_gallery, parent, false);
viewHolder = new HeaderViewHolder();
viewHolder.tvHeaderName = (TextView) view.findViewById(R.id.tvHeaderName);
viewHolder.tvHeaderDate = (TextView) view.findViewById(R.id.tvHeaderDate);
view.setTag(viewHolder);
} else {
viewHolder = (HeaderViewHolder) view.getTag();
}
viewHolder.tvHeaderName.setText(getHeaderItem(position).getGroupName());
viewHolder.tvHeaderDate.setText(getHeaderItem(position).getTime());
return view;
}
#Override
public int getNumHeaders() {
return parents.size();
}
private static class HeaderViewHolder {
public TextView tvHeaderName;
public TextView tvHeaderDate;
}
Does anyone know how to solve this?
I think you should try what I say in this other question.
Basically, you have to replace your stickygridheaders.jar or your dependency in gradle with this other jar stickygridheaders.jar

Categories

Resources