i already success to make one Recyclerview and i want to add new Recyclerview Horizontal on top. i will explain in my code :
<android.support.v7.widget.RecyclerView
android:id="#+id/arrayListUser"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:divider="#color/white">
</android.support.v7.widget.RecyclerView>
<android.support.v7.widget.RecyclerView
android:id="#+id/arrayList"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
android:divider="#color/white">
</android.support.v7.widget.RecyclerView>
id:arrayList is my first Recyclerview have name xml feeds_listview
id:arrayListUser is my new Recyclerview, i want make this Recyclerview Horizontal
xml for new Recylerview is feeds_listviewUser
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<de.hdodenhof.circleimageview.CircleImageView
android:id="#+id/profil"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginBottom="5dp"
android:layout_marginTop="30dp"
android:layout_gravity="center"
android:src="#drawable/cthprofil" />
<TextView
android:id="#+id/fullName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginTop="5dp"
android:layout_marginBottom="20"
android:text="Megi Fernanda"
android:textSize="17sp"
android:textColor="#color/colordefault"
android:textStyle="bold" />
</LinearLayout>
and this is my class adapter
public class FeedsCustomAdapter extends RecyclerView.Adapter<FeedsCustomAdapter.ViewHolder> {
private Context context;
private List<FeedsAdapter> feeds_list;
private ArrayList<Feeds> mFeedsList = new ArrayList<Feeds>();
private OnItemClickListener mListener;
private OnItemClickListener mListener2;
public FeedsCustomAdapter(Context context, ArrayList<Feeds> mFeedsList) {
this.context = context;
this.mFeedsList = mFeedsList;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.feeds_listview, parent, false);
return new ViewHolder(itemView);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Feeds feed = getFeeds().get(position);
int textColor = context.getResources().getColor(R.color.btn_next);
int textColor2 = context.getResources().getColor(R.color.text_color_black);
holder.fullName.setText(feed.user.fullName);
holder.location.setText(feed.user.location);
holder.topic.setText(Html.fromHtml( "Menyelesaikan Tantangan " + " <font color = '" + String.valueOf(textColor2) + "'>" + feed.topic + "</font>" ) );
Picasso.with(context)
.load(feed.user.avatar)
.into(holder.profile);
PrettyTime prettyTime = new PrettyTime();
String times = prettyTime.format(DateUtil.timeMilisTodate(feed.timestamp * 1000));
holder.times.setText(times);
}
#Override
public int getItemCount() {
return mFeedsList.size();
}
public ArrayList<Feeds> getFeeds() {
return mFeedsList;
}
public void setComplete(int position) {
mFeedsList.get(position).isComplete = 1;
}
public boolean last() {
boolean result = false;
int total = mFeedsList.size();
for (int i = 0; i < mFeedsList.size(); i++) {
if (mFeedsList.get(i).isComplete == 1) {
total--;
}
}
if (total == 1) {
result = true;
}
return result;
}
class ViewHolder extends RecyclerView.ViewHolder {
public TextView fullName;
public TextView location;
public TextView topic;
public ImageView profile;
public TextView times;
public ViewHolder(View itemView) {
super(itemView);
fullName = (TextView) itemView.findViewById(R.id.fullName);
location = (TextView) itemView.findViewById(R.id.location);
topic = (TextView) itemView.findViewById(R.id.topic);
profile = (ImageView) itemView.findViewById(R.id.profil);
times = (TextView) itemView.findViewById(R.id.times);
profile.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(mListener2 != null){
mListener2.onItemClick2(v ,getPosition());
}
}
});
topic.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(mListener != null){
mListener.onItemClick(v ,getPosition());
}
}
});
}
}
public void setClickListener(OnItemClickListener clickListener) {
this.mListener = clickListener;
}
public void setClickListenerProfile(OnItemClickListener clickListener2){
this.mListener2 = clickListener2;
}
public interface OnItemClickListener {
public abstract void onItemClick(View view, int position);
public abstract void onItemClick2(View view, int position);
}
so, in my code i success to display first recylerview with my first xml and i want add new recylerview horizontal with new xml feeds_listviewUser
You can use LinearLayout to wrap both recyclerView.
<android.support.v7.widget.RecyclerView
android:id="#+id/arrayListUser"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="#color/white">
</android.support.v7.widget.RecyclerView>
<android.support.v7.widget.RecyclerView
android:id="#+id/arrayList"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:divider="#color/white">
</android.support.v7.widget.RecyclerView>
And assign horizontal layout manager to one recyclerview and vertical layout manager to other
LinearLayoutManager userManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
arrayListUser.setLayoutManager(userManager);
LinearLayoutManager listManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
arrayList.setLayoutManager(listManager);
Put your recyclerviews in Relative layout.
First add horizontal recyclerView to alignParentTop true and fix height according to visibility of feeds_listviewUser next add vertical recyclerView with layout_below horizontal recyclerview id.
Related
I have implemented a RecyclerView inside a ConstraintLayout. I am having one child image element inside the layout. But when I click the child image, it always returns the ConstraintLayout, not the clicked image.
Could you please tell me why this is happening, what is the solution for this ?
I separately did bind listener to image, it is working but not able to get the RecyclerItem object. I need RecyclerItem object for the position to proceed.
I implemented it by binding elements via onBindViewholder method in Adapter. Below are the codes
customAdapter = new GridViewAdapter(recyclerItems, 1, this.getContext().getPackageName(),
new GridViewAdapter.OnItemClickListener(){
#Override
public void onItemClick(RecyclerItem item) {
CommonUtil.addFragment("REP", Constants.CONTAINER_HOME,
new ModifyFragment(), getActivity(), null);
}
}, R.layout.rec_view_item_stock, Constants.V_SPAN_LIST_8);
RecyclerView recyclerView = view.findViewById(R.id.stockListRecView);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setLayoutManager(new GridLayoutManager(this.getContext(), 1));
recyclerView.setAdapter(customAdapter);
//Adapter
public class GridViewAdapter extends RecyclerView.Adapter<GridViewAdapter.ViewHolder>{
private List<RecyclerItem> dataItems;
private int hSpan = 1;
private String packageName;
private final OnItemClickListener listener;
private int inflator;
private int vSpan;
public interface OnItemClickListener {
void onItemClick(RecyclerItem item);
}
public static class ViewHolder extends RecyclerView.ViewHolder {
private final ConstraintLayout constraintLayout;
private final TextView textView;
private final ImageView imageView;
private Object obj;
public ViewHolder(View view) {
super(view);
constraintLayout = (ConstraintLayout) view.findViewById(R.id.rec_content_layout);
textView = constraintLayout.findViewById(R.id.recTextView);
imageView = constraintLayout.findViewById(R.id.recImage);
}
public void bind(final RecyclerItem item, final OnItemClickListener listener) {
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
listener.onItemClick(item);
}
});
}
public TextView getTextView() {
return textView;
}
public ImageView getImageView() {
return imageView;
}
public Object getObj() {
return obj;
}
public void setObj(Object obj) {
this.obj = obj;
}
}
public GridViewAdapter(List<RecyclerItem> items, int spanCount, String packageName, OnItemClickListener listener,
int inflator, int vSpan) {
dataItems = items;
this.hSpan = spanCount;
this.packageName = packageName;
this.listener = listener;
this.inflator = inflator;
this.vSpan = vSpan;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int gridType) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(inflator, viewGroup, false);
ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
layoutParams.width = (viewGroup.getResources().getDisplayMetrics().widthPixels / hSpan) - 24;
if(Constants.V_SPAN_GRID == vSpan) {
layoutParams.height = layoutParams.width;
} else {
layoutParams.height = (viewGroup.getResources().getDisplayMetrics().widthPixels / vSpan);
}
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(ViewHolder viewHolder, final int position) {
viewHolder.getTextView().setText(dataItems.get(position).getText());
int imgId = viewHolder.getImageView().getResources().getIdentifier(
dataItems.get(position).getImageName(), "drawable", packageName);
viewHolder.getImageView().setImageResource(imgId);
viewHolder.setObj(dataItems.get(position));
viewHolder.bind(dataItems.get(position), listener);
}
#Override
public int getItemCount() {
return dataItems.size();
}
//item layout
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/rec_content_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:layout_marginTop="8dp"
android:layout_marginLeft="4dp"
android:padding="8dp"
android:background="#drawable/border_top_bottom" >
<androidx.constraintlayout.widget.Guideline
android:id="#+id/viewstock_gline_1_v"
android:layout_width="1dp"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.6"/>
<ImageView
android:id="#+id/recImage"
android:background="#color/colorPrimaryDark"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp" />
<TextView
android:id="#+id/recTextView"
app:layout_constraintLeft_toRightOf="#+id/recImage"
app:layout_constraintTop_toTopOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp" />
<ImageView
android:id="#+id/editstock_image"
android:src="#drawable/ic_edit_stock"
android:background="#color/colorPrimaryDark"
app:layout_constraintRight_toLeftOf="#+id/deletestock_image"
app:layout_constraintTop_toTopOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp" />
<ImageView
android:id="#+id/deletestock_image"
android:src="#drawable/ic_delete_stock"
android:background="#color/colorPrimaryDark"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp" />
</androidx.constraintlayout.widget.ConstraintLayout>```
Try this!
public void bind(final RecyclerItem item, final OnItemClickListener listener, TextView itemTextView) {
itemTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
listener.onItemClick(item);
}
});
}
Pass every item text view instance from the view holder or fro onBindViewHolder itself implement onclick listener
I have two RecyclerViews on my screen. And I need to scroll both at the same time on the same distance programmatically. But if I do it fast - the RecyclerViews desynchronizes.
In this source code you should fast click on button in the right top and will see the result.
This is Activity, where button listener for scrolling lists created:
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView1;
private RecyclerView recyclerView2;
private Adapter adapter1;
private Adapter adapter2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView1 = findViewById(R.id.recycler_view1);
recyclerView2 = findViewById(R.id.recycler_view2);
adapter1 = new Adapter();
recyclerView1.setLayoutManager(new LinearLayoutManager(this));
recyclerView1.setAdapter(adapter1);
adapter2 = new Adapter();
recyclerView2.setLayoutManager(new LinearLayoutManager(this));
recyclerView2.setAdapter(adapter2);
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
recyclerView1.smoothScrollBy(0, 400);
recyclerView2.smoothScrollBy(0, 400);
}
});
}
}
Adapter for lists:
public class Adapter extends RecyclerView.Adapter<Adapter.Holder>{
private boolean changeHeight = false;
#Override
public Holder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
return new Holder(view);
}
#Override
public void onBindViewHolder(Holder holder, int position) {
holder.setContent(String.valueOf(position), position % 2 == 0 ? R.color.colorPrimary : R.color.colorAccent);
if (changeHeight && position == 3) holder.changeHeight();
}
#Override
public int getItemCount() {
return 100;
}
class Holder extends RecyclerView.ViewHolder {
private View view;
private TextView textView;
public Holder(View itemView) {
super(itemView);
view = itemView;
textView = itemView.findViewById(R.id.text_view);
}
public void setContent(String text, int colorRes) {
textView.setText(text);
textView.setBackgroundResource(colorRes);
}
public void changeHeight() {
ViewGroup.LayoutParams params = view.getLayoutParams();
params.height = view.getHeight() * 2;
view.setLayoutParams(params);
}
}
}
This is activity_main.xml layout for Activity
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view1"
android:layout_width="0dp"
android:layout_weight="0.5"
android:layout_height="match_parent"/>
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view2"
android:layout_width="0dp"
android:layout_weight="0.5"
android:layout_height="match_parent"/>
<Button
android:id="#+id/button"
android:layout_width="100dp"
android:layout_height="100dp"/>
</LinearLayout>
Item for RecyclerView item.xml
<?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="100dp">
<TextView
android:id="#+id/text_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"/>
</RelativeLayout>
Crude solution is copying scroll of first recycler into the second one:
recyclerView1.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
recyclerView2.scrollBy(dx, dy);
}
});
Then proceed to smoothScroll only recyclerView1.
I've got a RecyclerView which populates from an ArrayList. The output is a CardView layout.
In the Cardview, there are 2 buttons amongst other Views.
They only have to read the current value of a TextView, which by default is 1, and increase or decrease it.
The Arraylist contains 8 items.
When I run the app the UI works fine. Trouble is when I try to modify the value of the TextView.
The value is correctly increased and decreased on the CardView I'm working on, but ALSO the value is modified on another CardView. And in that second CardView, modifying its TextView value, also modifies the first one.
So, what am I doing wrong?
This is my Fragment:
public class Fragment_rosas extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.layout_rosas,container,false);
RecyclerView recyclerview_rosas;
RecyclerView.Adapter adaptador_rv_rosas;
RecyclerView.LayoutManager lm_rosas;
List rosas = new ArrayList();
rosas.add(new Tropa(1,R.drawable.minibarbaro, getResources().getString(R.string.barbaro),7,1));
recyclerview_rosas = (RecyclerView) view.findViewById(R.id.recyclerView_tropasRosas);
recyclerview_rosas.setHasFixedSize(true);
lm_rosas = new LinearLayoutManager(getContext());
recyclerview_rosas.setLayoutManager(lm_rosas);
adaptador_rv_rosas = new AdaptadorTropa(rosas);
recyclerview_rosas.setAdapter(adaptador_rv_rosas);
return view;
}
}
And here the part of code on my Adapter:
#Override
public void onBindViewHolder(final TropaViewHolder viewHolder, int i) {
viewHolder.imagen.setImageResource(items.get(i).getImagen());
viewHolder.nombre.setText(items.get(i).getNombre());
viewHolder.maxnivel.setText(String.valueOf(items.get(i).getNivelMax()));
viewHolder.espacioencamp.setText((String.valueOf(items.get(i).getEspacioEnCamp())));
final String nombre = items.get(i).getNombre();
final int maxnivel = items.get(i).getNivelMax();
viewHolder.nivelmas.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String niveltemp = viewHolder.nivel.getText().toString();
String nivelmaxtemp = viewHolder.maxnivel.getText().toString();
int nivel = Integer.parseInt(niveltemp);
int maxxnivel = Integer.parseInt(nivelmaxtemp);
int nuevonivel = nivel+1 ;
if (nuevonivel<=maxxnivel) {
viewHolder.txtv_nivel.setText(String.valueOf(nuevonivel));
}
}
});
My OnCreateViewHolder (nothing really happens here):
#Override
public TropaViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.cardview, viewGroup, false);
return new TropaViewHolder(v);
}
Here is the solution, as mentioned in the comment above, it addresses two problems:
1. positiontoValueMap - saves current value for each position
2. onclicklistener is passed to the ViewHolder in onCreateViewHolder
Adapter Class
public class MyAdapter extends RecyclerView.Adapter {
private Context context;
private List<String> dataList;
private Map<Integer, Integer> positionToValueMap = new HashMap<>();
public MyAdapter(Context context, List<String> dataList) {
this.context = context;
this.dataList = dataList;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.recycler_view_item, null, false);
return new MyViewHolder(view, new OnRecyclerItemClickListener());
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
((MyViewHolder) holder).onRecyclerItemClickListener.updatePosition(position);
((MyViewHolder) holder).position.setText("" + position);
((MyViewHolder) holder).title.setText(dataList.get(position));
int valueToDisplay = 1;
if(positionToValueMap.containsKey(position)) {
valueToDisplay = positionToValueMap.get(position);
} else {
positionToValueMap.put(position, valueToDisplay);
}
((MyViewHolder) holder).valueView.setText("value: " + valueToDisplay);
}
#Override
public int getItemCount() {
return dataList.size();
}
private class MyViewHolder extends RecyclerView.ViewHolder {
private OnRecyclerItemClickListener onRecyclerItemClickListener;
private TextView position;
private TextView title;
private TextView valueView;
public MyViewHolder(View itemView, OnRecyclerItemClickListener onRecyclerItemClickListener) {
super(itemView);
itemView.setOnClickListener(onRecyclerItemClickListener);
this.onRecyclerItemClickListener = onRecyclerItemClickListener;
this.position = (TextView) itemView.findViewById(R.id.position);
this.title = (TextView) itemView.findViewById(R.id.title);
this.valueView = (TextView) itemView.findViewById(R.id.value_view);
}
}
private class OnRecyclerItemClickListener implements View.OnClickListener {
private int position = -1;
public void updatePosition(int position) {
this.position = position;
}
#Override
public void onClick(View v) {
int oldValue = positionToValueMap.get(position); // get current value
oldValue++; // increment
positionToValueMap.put(position, oldValue); // save current value
notifyItemChanged(position); // update clicked view so that it picks up the new saved value from the positionToValueMap in onBindViewHolder
}
}
}
RecyclerView item layout
<TextView
android:id="#+id/position"
android:layout_width="30dp"
android:layout_height="50dp"
android:textColor="#android:color/white"
android:gravity="center"
android:background="#android:color/holo_green_light"
android:layout_alignParentLeft="true"/>
<TextView
android:id="#+id/title"
android:layout_width="50dp"
android:layout_height="50dp"
android:textColor="#android:color/white"
android:gravity="center"
android:background="#android:color/holo_green_dark"
android:layout_toRightOf="#id/position" />
<TextView
android:id="#+id/value_view"
android:layout_width="match_parent"
android:layout_height="50dp"
android:textColor="#android:color/white"
android:gravity="center"
android:background="#android:color/holo_green_light"
android:layout_toRightOf="#id/title"
android:layout_alignParentRight="true"/>
</RelativeLayout>
And Activity to test it out
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
recyclerView.setAdapter(new MyAdapter(getApplicationContext(), getSampleData()));
}
private static List<String> getSampleData() {
List<String> dataList = new ArrayList<>();
dataList.add("zero");
dataList.add("one");
dataList.add("two");
dataList.add("three");
dataList.add("four");
dataList.add("five");
dataList.add("six");
dataList.add("seven");
dataList.add("eight");
dataList.add("nine");
dataList.add("ten");
dataList.add("eleven");
dataList.add("twelve");
dataList.add("thirteen");
dataList.add("fourteen");
dataList.add("fifteen");
dataList.add("sixteen");
dataList.add("seventeen");
dataList.add("eighteen");
dataList.add("nineteen");
dataList.add("twenty");
return dataList;
}
}
activity layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/root_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/white"/>
</RelativeLayout>
I am using linkify to make links clickable in the textview. But whenever text length is big, the text flickers on scrolling or sometimes just disappears. The text view is part of header of recyclerview. Posting relevant code from activity class, its xml and adapter.
The Activity:
public class NewDiscussionDetailActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_discussion_detail);
Toolbar toolbar = (Toolbar) findViewById(R.id.detail_toolbar);
aQuery = new AQuery(this);
setSupportActionBar(toolbar);
final ActionBar ab = getSupportActionBar();
if (ab != null) {
ab.setDisplayHomeAsUpEnabled(true);
ab.setTitle("Discussion");
}
Intent activityIntent = getIntent();
discussion_id = Integer.parseInt(activityIntent.getStringExtra("discussion_id"));
discussion_title = activityIntent.getStringExtra("discussion_title");
discussion_text = activityIntent.getStringExtra("discussion_text");
discussion_image_url = activityIntent.getStringExtra("discussion_image_url");
comment_count = Integer.parseInt(activityIntent.getStringExtra("discussion_comment_no"));
community_id = activityIntent.getStringExtra("community_id");
community_name = activityIntent.getStringExtra("community_name");
is_from_notification = activityIntent.getBooleanExtra("is_notification", false);
// initializing header and footer for List view
footer = getLayoutInflater().inflate(R.layout.main_list_footer, null);
header = getLayoutInflater().inflate(R.layout.discussion_detail_header, null);
prepareHeader(header);
recyclerView = (RecyclerView) findViewById(R.id.comment_list);
// use a linear layout manager
mLayoutManager = new LinearLayoutManager(recyclerView.getContext());
mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
mLayoutManager.canScrollVertically();
recyclerView.setLayoutManager(mLayoutManager);
adapter = new CommentAdapter(commentList, this);
/* download page 1*/
adapter.addHeader(header);
recyclerView.setAdapter(adapter);
getCommentList();
/* Scroll Listener which takes care of all triggers to download to load data to adapter based position of the view*/
// code for downloading more pages of comments
}
private void prepareHeader(View header) {
/* preparing the header*/
discussion_image = (ImageView) header.findViewById(R.id.discussion_image_1);
title = (TextView) header.findViewById(R.id.discussion_title);
commentno = (TextView) header.findViewById(R.id.comment_count);
description = (TextView) header.findViewById(R.id.discussion_text_content);
title.setText(discussion_title);
title.setTypeface(AppConstants.getTypeFaceBold(this));
description.setText(discussion_text);
discriptionText = discussion_text + "";
Linkify.addLinks(description, Linkify.WEB_URLS);
description.setTypeface(AppConstants.getTypeFaceNormal(this));
if (comment_count > 2) {
commentno.setText(String.valueOf(comment_count - 1) + " comments");
} else if (comment_count == 2){
commentno.setText(String.valueOf(comment_count - 1) + " comment");
}else {
commentno.setText("Be the first to comment");
}
if (discussion_image_url == null || discussion_image_url.equals("")) {
discussion_image.setVisibility(View.GONE);
//progressbar.setVisibility(View.GONE);
} else {
discussion_image.setVisibility(View.VISIBLE);
final String image_url = discussion_image_url;
if(UtilMethod.isStringNullOrBlank(image_url))
{
//progressbar.setVisibility(View.GONE);
}
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int width=dm.widthPixels;
int height=dm.heightPixels;
Picasso.with(this)
.load(image_url)
.placeholder(R.drawable.default_img_big).error(R.drawable.default_img_big)
.transform(new ImageTransformation(width))
.into(discussion_image, new Callback() {
#Override
public void onSuccess() {
// TODO Auto-generated method stub
//progressbar.setVisibility(View.GONE);
}
#Override
public void onError() {
// TODO Auto-generated method stub
//progressbar.setVisibility(View.GONE);
}
});
discussion_image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// code
}
});
}
}
The Adapter:
public class CommentAdapter extends RecyclerView.Adapter<CommentAdapter.CustomViewHolder> {
ArrayList<CommentListBean> mArrayList;
Context mContext;
String event = "";
public static final int TYPE_HEADER = 111;
public static final int TYPE_FOOTER = 222;
public static final int TYPE_ITEM = 333;
//headers
List<View> headers = new ArrayList<>();
//footers
List<View> footers = new ArrayList<>();
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public static class CustomViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
private View view;
final TextView timestamp_tv;
final TextView chat_username;
final TextView description_tv;
final ImageView author_image_view;
final ImageView comment_image;
public CustomViewHolder(View v) {
super(v);
view = v;
chat_username = (TextView) v.findViewById(R.id.comment_author_chatname);
timestamp_tv = (TextView) v.findViewById(R.id.comment_timestamp);
description_tv = (TextView) v.findViewById(R.id.comment_text);
comment_image = (ImageView) v.findViewById(R.id.comment_image);
author_image_view = (ImageView) v.findViewById(R.id.comment_author_image);
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public CommentAdapter(ArrayList<CommentListBean> arrayList, Context context) {
this.mContext = context;
this.mArrayList = arrayList;
}
// Create new views (invoked by the layout manager)
#Override
public CustomViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
if (viewType == TYPE_ITEM) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.comment_list_item, null);
CustomViewHolder viewHolder = new CustomViewHolder(view);
return viewHolder;
} else {
//create a new framelayout, or inflate from a resource
FrameLayout frameLayout = new FrameLayout(parent.getContext());
//make sure it fills the space
frameLayout.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
return new HeaderFooterViewHolder(frameLayout);
}
}
// Replace the contents of a view (invoked by the layout manager)
public void onBindViewHolder(final CustomViewHolder holder, final int position) {
//check what type of view our position is
if(position < headers.size()){
View v = headers.get(position);
//add our view to a header view and display it
prepareHeaderFooter((HeaderFooterViewHolder) holder, v);
}else if(position >= headers.size() + mArrayList.size()){
View v = footers.get(position-mArrayList.size()-headers.size());
//add oru view to a footer view and display it
prepareHeaderFooter((HeaderFooterViewHolder) holder, v);
}else {
// - code for normal comment view
}
}
#Override
public int getItemViewType(int position) {
//check what type our position is, based on the assumption that the order is headers > items > footers
if(position < headers.size()){
return TYPE_HEADER;
}else if(position >= headers.size() + mArrayList.size()){
return TYPE_FOOTER;
}
return TYPE_ITEM;
}
private void prepareHeaderFooter(HeaderFooterViewHolder vh, View view){
//empty out our FrameLayout and replace with our header/footer
vh.base.removeAllViews();
vh.base.addView(view);
}
//add a header to the adapter
public void addHeader(View header){
if(!headers.contains(header)){
headers.add(header);
//animate
notifyItemInserted(headers.size()-1);
}
}
//remove a header from the adapter
public void removeHeader(View header){
if(headers.contains(header)){
//animate
notifyItemRemoved(headers.indexOf(header));
headers.remove(header);
}
}
//add a footer to the adapter
public void addFooter(View footer){
if (!footers.contains(footer)){
footers.add(footer);
//animate
notifyItemInserted(headers.size()+mArrayList.size()+footers.size()-1);
}
}
//remove a footer from the adapter
public void removeFooter(View footer){
if(footers.contains(footer)) {
//animate
notifyItemRemoved(headers.size()+mArrayList.size()+footers.indexOf(footer));
footers.remove(footer);
}
}
//our header/footer RecyclerView.ViewHolder is just a FrameLayout
public static class HeaderFooterViewHolder extends CustomViewHolder{
FrameLayout base;
public HeaderFooterViewHolder(View itemView) {
super(itemView);
this.base = (FrameLayout) itemView;
}
}
}
XML for the header view
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="#dimen/margin_10">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/message_list_image_layout"
android:orientation="horizontal"
android:paddingTop="20dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:contentDescription="Representative image for the discussion"
android:background="#color/background_color"
android:id="#+id/discussion_image_1"
android:layout_marginBottom="#dimen/margin_5"
android:layout_marginTop="#dimen/margin_5"
android:src="#drawable/bg"
android:adjustViewBounds="true"
android:scaleType="centerCrop"
android:maxHeight="280dp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/discussion_title"
android:text="This is heading of the content"
android:layout_marginLeft="#dimen/margin_20"
android:layout_marginRight="#dimen/margin_20"
style="#style/Base.TextAppearance.AppCompat.Display1"
android:alpha="075" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/discussion_text_content"
android:layout_marginTop="#dimen/margin_10"
android:layout_marginLeft="#dimen/margin_20"
android:layout_marginRight="#dimen/margin_20"
android:text="this is the text of content. this is the text of content. this is the text of content. this is the text of content. this is the text of content.this is the text of content. this is the text of content. this is the text of content. this is the text of content. this is the text of content."
style="#style/Base.TextAppearance.AppCompat.Body1"
android:alpha="0.75" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="#dimen/margin_10"
android:layout_marginLeft="#dimen/margin_20"
android:layout_marginRight="#dimen/margin_20"
android:background="#color/dark_background_color"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginTop="#dimen/margin_10"
android:layout_marginBottom="#dimen/margin_10"
android:layout_marginRight="#dimen/margin_20"
android:layout_marginLeft="#dimen/margin_20"
android:gravity="center_vertical|right|end"
android:orientation="horizontal">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/comment_count"
android:text="4 comments" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
Screenshots
Normal view
when I scroll a bit
I have a feeling that it has something to do with LinkMovementMethod. Please help.
I am trying to create a ListView, each row of which is a horizontal scrolling list. Earlier, I was using HorizontalScrollView but I needed a layout which could recycle views. So I used RecyclerView, but now the contents of RecyclerView are not visible.
Here is my adapter for vertical listview:
public class FeedAdapter extends BaseAdapter {
private Context context;
private FeedItem feedItem;
private static LayoutInflater inflater = null;
private Picasso picasso;
Typeface opensans;
public FeedAdapter(Context context, FeedItem feedItem) {
this.context = context;
this.feedItem = feedItem;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
opensans = Typeface.createFromAsset(context.getAssets(), "fonts/OpenSans-Regular.ttf");
OkHttpClient okHttpClient = new OkHttpClient();
picasso = new Picasso.Builder(context)
.downloader(new OkHttpDownloader(okHttpClient))
.build();
}
#Override
public int getCount() {
return feedItem.getFeedList().size();
}
#Override
public FeedList getItem(int position) {
return feedItem.getFeedList().get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
final FeedRowViewHolder rowViewHolder;
if (view == null) {
view = inflater.inflate(R.layout.feed_row, parent, false);
rowViewHolder = new FeedRowViewHolder(view);
view.setTag(rowViewHolder);
} else {
rowViewHolder = (FeedRowViewHolder) view.getTag();
}
final FeedList feedList = feedItem.getFeedList().get(position);
picasso.with(context)
.load(feedList.getThumbnailUrl())
.resize(120, 120)
.centerCrop()
.into(rowViewHolder.galleryThumb);
rowViewHolder.galleryThumb.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String api_url = feedList.getUrl();
String delims = "/";
String[] tokens = api_url.split(delims);
String thumbId = tokens[5];
((HomeActivity) context).changeIntent(thumbId);
}
});
rowViewHolder.galleryName.setText(feedList.getGalleryName());
rowViewHolder.galleryName.setTypeface(opensans);
rowViewHolder.galleryName.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String api_url = feedList.getUrl();
String delims = "/";
String[] tokens = api_url.split(delims);
String thumbId = tokens[5];
((HomeActivity) context).changeIntent(thumbId);
}
});
rowViewHolder.timestamp.setText(feedList.getCreatedDate());
rowViewHolder.timestamp.setTypeface(opensans);
rowViewHolder.followButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
picasso.with(context)
.load(R.drawable.cta_button_follow_secondary_state)
.into(rowViewHolder.followButton);
}
});
LinearLayoutManager layoutManager = new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false);
rowViewHolder.recyclerView.setLayoutManager(layoutManager);
FeedItemAdapter adapter = new FeedItemAdapter(context, feedList.getPhotos());
rowViewHolder.recyclerView.setAdapter(adapter);
return view;
}
static class FeedRowViewHolder {
#Bind(R.id.imageView75)
ImageView galleryThumb;
#Bind(R.id.textView65)
TextView galleryName;
#Bind(R.id.textView66)
TextView timestamp;
#Bind(R.id.imageView162)
ImageView followButton;
#Bind(R.id.recyclerView)
RecyclerView recyclerView;
public FeedRowViewHolder(View view) {
ButterKnife.bind(this, view);
}
}
}
Here is my adapter for Horizontal RecyclerView:
public class FeedItemAdapter extends RecyclerView.Adapter<FeedItemAdapter.ViewHolder> {
private List<Photo> list;
private Context context;
private Picasso picasso;
Typeface opensans;
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.feed_item, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
final Photo photo = getValueAt(position);
picasso.with(context)
.load(photo.getPhotoUrl())
.resize(1020, 768)
.centerCrop()
.into(holder.image);
holder.image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String photo_url = photo.getPhoto();
String delims = "/";
String[] tokens = photo_url.split(delims);
String photoId = tokens[5];
((HomeActivity) context).setBackImage(photoId);
}
});
picasso.with(context)
.load(photo.getProfilePic())
.resize(120, 120)
.centerCrop()
.transform(new CircleTransform())
.into(holder.profilePic);
holder.profilePic.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String user_url = photo.getOwner();
String delims = "/";
String[] tokens = user_url.split(delims);
String photoId = tokens[5];
((HomeActivity) context).showUserProfile(photoId);
}
});
holder.commentButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
((HomeActivity) context).showComments();
}
});
holder.fiveImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
((HomeActivity) context).showLikes();
}
});
holder.commentImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
((HomeActivity) context).showComments();
}
});
holder.username.setText(photo.getUserName());
holder.username.setTypeface(opensans);
holder.userFives.setText(Integer.toString(photo.getUserFives()) + " Fives");
holder.userFives.setTypeface(opensans);
holder.caption.setText(photo.getCaption());
holder.caption.setTypeface(opensans);
final int[] fives = {photo.getPhotoFives()};
holder.numFives.setText(Integer.toString(photo.getPhotoFives()));
holder.numFives.setTypeface(opensans);
holder.numComments.setText(Integer.toString(photo.getNumComments()));
holder.numComments.setTypeface(opensans);
final boolean[] liked = {false};
holder.fiveButton.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
holder.fiveButton.setText("Hi Fiveeed!");
holder.fiveButton.setTypeface(opensans);
holder.fiveButton.setTextColor(Color.parseColor("#FAC80A"));
picasso.with(context)
.load(R.drawable.cta_ic_five_pressed_state)
.into(holder.fiveImage);
}
if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
holder.fiveButton.setText("Five This!");
holder.fiveButton.setTypeface(opensans);
holder.fiveButton.setTextColor(Color.parseColor("#707070"));
picasso.with(context)
.load(R.drawable.user_profile_activity_1_ic_five_count)
.into(holder.fiveImage);
}
if (motionEvent.getAction() == MotionEvent.ACTION_MOVE) {
holder.fiveButton.setText("Five This!");
holder.fiveButton.setTypeface(opensans);
holder.fiveButton.setTextColor(Color.parseColor("#707070"));
picasso.with(context)
.load(R.drawable.user_profile_activity_1_ic_five_count)
.into(holder.fiveImage);
}
return false;
}
});
holder.fiveButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (liked[0] == false) {
holder.fiveButton.setText("Hi Fived!");
holder.fiveButton.setTypeface(opensans);
holder.fiveButton.setTextColor(Color.parseColor("#FAC80A"));
holder.numFives.setText(Integer.toString(fives[0] + 1));
fives[0] = fives[0] + 1;
picasso.with(context)
.load(R.drawable.cta_ic_five_pressed_state)
.into(holder.fiveImage);
liked[0] = true;
} else {
holder.fiveButton.setText("Five This!");
holder.fiveButton.setTypeface(opensans);
holder.fiveButton.setTextColor(Color.parseColor("#707070"));
holder.numFives.setText(Integer.toString(fives[0] - 1));
fives[0] = fives[0] - 1;
picasso.with(context)
.load(R.drawable.user_profile_activity_1_ic_five_count)
.into(holder.fiveImage);
liked[0] = false;
}
}
});
}
#Override
public int getItemCount() {
return list.size();
}
public Photo getValueAt(int position) {
return list.get(position);
}
public static class ViewHolder extends RecyclerView.ViewHolder {
#Bind(R.id.imageView86)
ImageView image;
#Bind(R.id.imageView76)
ImageView profilePic;
#Bind(R.id.textView67)
TextView username;
#Bind(R.id.textView68)
TextView userFives;
#Bind(R.id.textView1)
TextView caption;
#Bind(R.id.textView69)
TextView fiveButton;
#Bind(R.id.textView71)
TextView commentButton;
#Bind(R.id.imageView77)
ImageView fiveImage;
#Bind(R.id.textView72)
TextView numFives;
#Bind(R.id.imageView120)
ImageView commentImage;
#Bind(R.id.textView73)
TextView numComments;
public ViewHolder(View view) {
super(view);
ButterKnife.bind(this, view);
}
}
public FeedItemAdapter(Context context, List<Photo> list) {
this.context = context;
this.list = list;
opensans = Typeface.createFromAsset(context.getAssets(), "fonts/OpenSans-Regular.ttf");
OkHttpClient okHttpClient = new OkHttpClient();
picasso = new Picasso.Builder(context)
.downloader(new OkHttpDownloader(okHttpClient))
.build();
}
}
Here is my layout for row of listview:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/scroller_placeholder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#231f20"
android:orientation="vertical">
<LinearLayout
android:id="#+id/linearLayout7"
android:background="#343031"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/imageView75"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:paddingRight="5dp"
android:src="#drawable/user_profile_activity_1_img_gallery_1_icon"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_marginLeft="10dp" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="#+id/imageView75"
android:orientation="vertical"
android:paddingLeft="5dp">
<TextView
android:id="#+id/textView65"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:alpha="0.8"
android:paddingBottom="2dp"
android:text="Wilderness"
android:textColor="#FFFFFF" />
<TextView
android:id="#+id/textView66"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="2dp"
android:text="2 hrs."
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="#707070"
android:textSize="12sp" />
</LinearLayout>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/imageView162"
android:src="#drawable/cta_button_follow_default_state"
android:layout_alignParentEnd="true"
android:layout_marginRight="20dp"
android:layout_centerVertical="true" />
</RelativeLayout>
</LinearLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
The items for each row were getting displayed perfectly fine when I was using HorizontalScrollView but the contents of recyclerView are not getting displayed. I can't figure out what is the problem. Any help would be highly appreciated.
I think your problem is here RecyclerView's android:layout_height="wrap_content". Try to set this attribute to specific value.
Update
New release of Android Support Library 23.2:
The RecyclerView widget provides an advanced and flexible base for
creating lists and grids as well as supporting animations. This
release brings an exciting new feature to the LayoutManager API:
auto-measurement! This allows a RecyclerView to size itself based on
the size of its contents. This means that previously unavailable
scenarios, such as using WRAP_CONTENT for a dimension of the
RecyclerView, are now possible. You’ll find all built in
LayoutManagers now support auto-measurement.
As mr.icetea said you need to set the layout-height to a specific amount. You could get the shown items height and pass that on to the layout-height param.
https://developer.android.com/reference/android/widget/LinearLayout.LayoutParams.html documentation for adding layoutparams on the fly.
check out this method to calculate recyclerview height dynamically
// calculating height of Recycler view
private int calculateHeight(int size,int viewHeight) {
final float scale = mContext.getResources().getDisplayMetrics().density;
int singleViewHeight = (int) (viewHeight * scale + 0.5f);
int totalHeight = singleViewHeight * size;
return totalHeight;
}
and set height to recyclerview as-
//get recyclerview height
int height = calculateHeight(firstParam, secondparam);
ViewGroup.LayoutParams params = recyclerView.getLayoutParams();
params.height = height;
firstparam is sizofYourDataList_or_Array and secondparam is height of your row for recyclerview(so you have to give height for your row layout and that wiil be your second parameter's value)