RecyclerView inside fragment not Clickable - android

Silly question probably but i cant find why my RecyclerView not responding to clicks. The RV is in a fragment, i added an interface to the adapter and im implementing it to the fragment. But while trying the click the emulator does not even does the "click" sound
This is my adapter
public class ArtistsRvAdapter extends RecyclerView.Adapter<ArtistsRvAdapter.ArtistViewHolder> {
private List<Artist> mArtists;
private Context mContext;
final private ItemClickListener mItemClickListener;
public ArtistsRvAdapter(Context c, ItemClickListener listener){
mContext=c;
mItemClickListener =listener;
}
#NonNull
#Override
public ArtistsRvAdapter.ArtistViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
int layoutIdForListItem = R.layout.artist_list_item;
LayoutInflater inflater = LayoutInflater.from(mContext);
boolean shouldAttachToParentImmediately = false;
View view = inflater.inflate(layoutIdForListItem, viewGroup, shouldAttachToParentImmediately);
ArtistViewHolder viewHolder = new ArtistViewHolder(view);
return viewHolder;
}
#Override
public void onBindViewHolder(#NonNull ArtistViewHolder artistViewHolder, int position) {
Artist artist = this.mArtists.get(position);
Log.d("rv adapter ", "artist img " + artist.getArtistImageUrl());
String image = artist.getArtistImageUrl();
Picasso.get()
.load(image)
.placeholder(R.drawable.ic_launcher_background)
.error(R.drawable.ic_launcher_foreground)
.into(artistViewHolder.artistImage);
artistViewHolder.artistName.setText(artist.getArtistName());
Log.d("rv adapter ", "artist name " + artist.getArtistName());
artistViewHolder.artistGenre.setText(artist.getArtistGenre());
artistViewHolder.concertDate.setText(artist.getConcertDate());
artistViewHolder.concertLocation.setText(artist.getConcertLocation());
}
#Override
public int getItemCount() {
return (null != mArtists ? mArtists.size() : 0);
}
public class ArtistViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
ImageView artistImage;
TextView artistName;
TextView artistGenre;
TextView concertLocation;
TextView concertDate;
public ArtistViewHolder(View itemView){
super(itemView);
artistImage = itemView.findViewById(R.id.artist_image);
artistName = itemView.findViewById(R.id.artist_name);
artistGenre = itemView.findViewById(R.id.artist_genre);
concertLocation = itemView.findViewById(R.id.concert_location);
concertDate = itemView.findViewById(R.id.concert_date);
}
#Override
public void onClick(View v) {
String elementID = mArtists.get(getAdapterPosition()).getKey();
Log.d(" adapter " , "position clicked " + getAdapterPosition());
mItemClickListener.onItemClickListener(elementID);
}
}
public interface ItemClickListener {
void onItemClickListener(String itemId);
}
public void setArtists(List<Artist> artists){
mArtists = artists;
Log.d("rv " , "list artists " + mArtists);
notifyDataSetChanged();
}
}
And this is the fragment
public class BaseFragment extends Fragment implements ArtistsRvAdapter.ItemClickListener {
private ArtistsRvAdapter mAdapter;
private String LOG_TAG = BaseFragment.class.getSimpleName();
private View mRootView;
#BindView(R.id.rv)
RecyclerView recyclerView;
private Context mContext;
private AppDatabase mDb;
public BaseFragment(){}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
mRootView= inflater.inflate(R.layout.base_fragment, container, false);
ButterKnife.bind(this, mRootView);
mContext = getActivity().getApplicationContext();
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(mContext);
mDb = AppDatabase.getInstance(getActivity());
mAdapter = new ArtistsRvAdapter(mContext, this);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(mAdapter);
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(),
((LinearLayoutManager) layoutManager).getOrientation());
recyclerView.addItemDecoration(dividerItemDecoration);
setupViewModel();
return mRootView;
}
private void setupViewModel(){
Log.d(LOG_TAG, "getting artists from DB");
DetailsViewModel viewModel = ViewModelProviders.of(getActivity()).get(DetailsViewModel.class);
viewModel.getArtists().observe(this, new Observer<List<Artist>>() {
#Override
public void onChanged(List<Artist> artists) {
mAdapter.setArtists(artists);
}
});
}
#Override
public void onItemClickListener(String itemId) {
Intent i = new Intent(getActivity(), DetailsActivity.class);
i.putExtra("artistId", itemId);
startActivity(i);
}
}
This is the xml
<androidx.constraintlayout.widget.ConstraintLayout 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"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="6dp"
android:theme="#style/Theme.Bacon.AppBarOverlay"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:layout_gravity="bottom">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="#string/app_name"
android:src="#mipmap/logo"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/app_name"/>
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.AppBarLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/min_margin_dp"
android:layout_marginLeft="#dimen/min_margin_dp"
android:layout_marginTop="#dimen/rv_margin"
android:layout_marginEnd="#dimen/min_margin_dp"
android:layout_marginRight="#dimen/min_margin_dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/appBarLayout">
</androidx.recyclerview.widget.RecyclerView>

please add this line "itemView.setOnClickListener(this);" in "ArtistViewHolder"s constructor
public ArtistViewHolder(View itemView){
super(itemView);
artistImage = itemView.findViewById(R.id.artist_image);
artistName = itemView.findViewById(R.id.artist_name);
artistGenre = itemView.findViewById(R.id.artist_genre);
concertLocation = itemView.findViewById(R.id.concert_location);
concertDate = itemView.findViewById(R.id.concert_date);
itemView.setOnClickListener(this);
};

In your ArtistViewHolder after super(itemView); add
itemView.setOnClickListener(this);

Related

RecyclerView is duplicating Alert Dialog results

I have a fragment that is suppose to display the results of my alert dialog in my RecyclerView. Every time I click the "ADD" in my dialog, it adds duplicated results to my RecyclerView. I've searched and searched but cannot seem to find what I am doing wrong. I've tried adding .clear(); but if I add that, nothing shows up in my RecyclerView at all. I've added in my adapter getItemId and getItemViewType to return position; but the items still get duplicated. I've added adapter.setData(model) followed by adapter.notifyDataSetChange(); and my RecyclerView still shows duplicated items. The app runs so I have no logcat to post. Thank you.
Model
public class SubjectsModel
{
//private long id;
private String mTitle;
private String mTeacher;
public String getmTitle()
{
return mTitle;
}
public void setmTitle(String title)
{
this.mTitle = title;
}
public String getmTeacher()
{
return mTeacher;
}
public void setmTeacher(String teacher)
{
this.mTeacher = teacher;
}
}
Fragment
public class SubjectsFrag extends DialogFragment implements
SubjectsEditor.OnAddSubjectListener
{
private static final String TAG = SubjectsFrag.class.getSimpleName();
#NonNull
Context context;
private EditText titleView, teacherView;
private String sTitle, sTeacher;
public EmptyRecyclerView recyclerView;
public RecyclerView.LayoutManager layoutManager;
public RecyclerSubAdapter recyclerSubAdapter;
public ArrayList<SubjectsModel> subMod = new ArrayList<>();
DbHelper helper;
#BindView(R.id.main_root)
ViewGroup root;
public SubjectsFrag() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_subjects, container, false);
FloatingActionButton fab = view.findViewById(R.id.fab_sub);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
showDialog();
}
});
helper = new DbHelper(getActivity());
helper.getSubject();
titleView = view.findViewById(R.id.edit_subject);
teacherView = view.findViewById(R.id.edit_subject_teacher);
View emptyView = view.findViewById(R.id.empty_subject_view);
recyclerView = view.findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
recyclerSubAdapter = new RecyclerSubAdapter(getContext(), subMod);
layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(recyclerSubAdapter);
return view;
}
#Override
public void OnAddSubjectSubmit(String title, String teacher)
{
SubjectsModel model = new SubjectsModel();
model.setmTitle(title);
model.setmTeacher(teacher);
//subMod.clear();
subMod.add(model);
recyclerSubAdapter.setData(subMod);
recyclerSubAdapter.notifyDataSetChanged();
}
private void showDialog()
{
SubjectsEditor addSubjectDialog = new SubjectsEditor();
addSubjectDialog.setTargetFragment(this, 0);
addSubjectDialog.show(getFragmentManager(), null);
}
}
Adapter
public class RecyclerSubAdapter extends RecyclerView.Adapter<RecyclerSubAdapter.ViewHolder>
{
private static final String TAG = RecyclerSubAdapter.class.getSimpleName();
public List<SubjectsModel> subMod = new ArrayList<>();
private OnItemClicked onClick;
static ClickListener clickListener;
Context context;
DbHelper helper;
public RecyclerSubAdapter(Context context, ArrayList<SubjectsModel> subMod)
{
this.context = context;
this.subMod = subMod;
this.helper = new DbHelper(context);
}
#NonNull
#Override
public RecyclerSubAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType)
{
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.subjects_item_list, parent, false);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}
#Override
public void onBindViewHolder(final RecyclerSubAdapter.ViewHolder holder, final int position)
{
SubjectsModel currentSubject = subMod.get(position);
holder.titleView.setText(currentSubject.getmTitle());
holder.teacher.setText(currentSubject.getmTeacher());
//helper.addClass(subMod.get(position));
}
public class ViewHolder extends RecyclerView.ViewHolder implements
View.OnClickListener
{
TextView titleView;
TextView teacher;
CardView cardView;
public ViewHolder(View itemView)
{
super(itemView);
titleView = itemView.findViewById(R.id.subject_subject);
teacher = itemView.findViewById(R.id.subject_teacher_text);
cardView = itemView.findViewById(R.id.card_view);
}
#Override
public void onClick(View view)
{
if (clickListener != null)
{
}
}
}
#Override
public int getItemCount()
{
if (subMod == null)
{
Log.d(TAG, "sub is null");
}
return subMod.size();
}
#Override
public long getItemId(int position)
{
return position;
}
#Override
public int getItemViewType(int position)
{
return position;
}
public interface OnItemClicked
{
void onItemClick(int position);
}
public void setOnClick(OnItemClicked onClick)
{
this.onClick = onClick;
}
public void setClickListener(ClickListener clicked)
{
RecyclerSubAdapter.clickListener = clicked;
}
public interface ClickListener
{
void itemClicked(SubjectsModel model, int position);
}
public void setData(ArrayList<SubjectsModel> data)
{
this.subMod = data;
//this.subMod.clear();
this.subMod.addAll(data);
notifyDataSetChanged();
}
}
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="match_parent"
android:id="#+id/main_root">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.example.ashleighwilson.schoolscheduler.adapter.EmptyRecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="60dp"/>
</LinearLayout>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true">
<TextView
android:id="#+id/empty_subject_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:visibility="gone"
android:text="#string/no_subjects"/>
</RelativeLayout>
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab_sub"
style="#style/FAB" />
</RelativeLayout>
In OnAddSubjectSubmit() you call subMod.add(model);
and then you call recyclerSubAdapter.setData(subMod); which in turn calls this.subMod.addAll(data);.
Check it yourself. I believe it's there where you add the new item twice.
Suggestion: comment out recyclerSubAdapter.setData(subMod); from OnAddSubjectSubmit().
this.subMod = data;
this.subMod.addAll(data);
You initilize subMod by assigning data to it, and later you add data again:
this.subMod.addAll(data);

Android setonclicklistener is not working recycler header

I am developing an app using recycler header. And my recycler having header. The source code recycler header is shown in https://github.com/blipinsk/RecyclerViewHeader.
I want to active the set on click listener in recycler header. when i click the recycler header it shows a toasted message. My code is given below.
I am using in fragment.
HomeFragment.java
public class HomeFragment extends android.support.v4.app.Fragment {
List<GetDataAdapter> GetDataAdapter1;
RecyclerView recyclerView;
RecyclerView.LayoutManager recyclerViewlayoutManager;
RecyclerView.Adapter recyclerViewadapter;
RecyclerViewHeader recyclerHeader;
String GET_JSON_DATA_HTTP_URL;
String JSON_IMAGE_TITLE_NAME = "image_title";
String JSON_IMAGE_URL = "image_url";
String JSON_IMAGE_ID = "id";
String JSON_MRP = "mrp";
String JSON_RATE = "rate";
String JSON_DISCOUNT = "discount";
JsonArrayRequest jsonArrayRequest ;
RequestQueue requestQueue ;
public HomeFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_home, container, false);
((AppCompatActivity)getActivity()).getSupportActionBar().setTitle("Home");
GET_JSON_DATA_HTTP_URL = Util.URL_SERVER + "categories.php";
GetDataAdapter1 = new ArrayList<>();
recyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerview3);
recyclerView.setHasFixedSize(true);
recyclerViewlayoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(recyclerViewlayoutManager);
recyclerHeader = (RecyclerViewHeader) rootView.findViewById(R.id.header);
recyclerHeader.attachTo(recyclerView);
recyclerHeader.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("LOG", "clicked");
}
});
JSON_DATA_WEB_CALL();
// Inflate the layout for this fragment
return rootView;
}
public void JSON_DATA_WEB_CALL(){
final ProgressDialog progressDialog = new ProgressDialog(getContext(), R.style.AppTheme_Dark_Dialog);
progressDialog.setIndeterminate(true);
progressDialog.setMessage("Loading");
progressDialog.show();
jsonArrayRequest = new JsonArrayRequest(GET_JSON_DATA_HTTP_URL,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
progressDialog.dismiss();
Log.d("LOGTAG", "Response :"+response);
JSON_PARSE_DATA_AFTER_WEBCALL(response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
requestQueue = Volley.newRequestQueue(getContext());
requestQueue.add(jsonArrayRequest);
}
public void JSON_PARSE_DATA_AFTER_WEBCALL(JSONArray array){
for(int i = 0; i<array.length(); i++) {
GetDataAdapter GetDataAdapter2 = new GetDataAdapter();
JSONObject json = null;
try {
json = array.getJSONObject(i);
GetDataAdapter2.setImageTitleName(json.getString(JSON_IMAGE_TITLE_NAME));
GetDataAdapter2.setImageServerUrl(json.getString(JSON_IMAGE_URL));
GetDataAdapter2.setImageId(json.getString(JSON_IMAGE_ID));
GetDataAdapter2.setMrp(json.getString(JSON_MRP));
GetDataAdapter2.setDiscount(json.getString(JSON_DISCOUNT));
//Log.d("LOGTAG", "JSON_MRP : "+json.getString(JSON_MRP)+"JSON_RATE : "+json.getString(JSON_RATE)+"JSON_DISCOUNT :"+json.getString(JSON_DISCOUNT));
} catch (JSONException e) {
e.printStackTrace();
}
GetDataAdapter1.add(GetDataAdapter2);
}
recyclerViewadapter = new RecyclerViewAdapter(GetDataAdapter1, getContext());
recyclerView.setAdapter(recyclerViewadapter);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
}
#Override
public void onDetach() {
super.onDetach();
}
}
RecyclerViewAdapter
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {
static String categoryId;
Context context;
List<GetDataAdapter> getDataAdapter;
ImageLoader imageLoader1;
private final View.OnClickListener mOnClickListener = new MyOnClickListener();
public RecyclerViewAdapter(List<GetDataAdapter> getDataAdapter, Context context){
super();
this.getDataAdapter = getDataAdapter;
this.context = context;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.subcategory_items, parent, false);
v.setOnClickListener(mOnClickListener);
ViewHolder viewHolder = new ViewHolder(v);
return viewHolder;
}
#Override
public void onBindViewHolder(ViewHolder Viewholder, int position) {
GetDataAdapter getDataAdapter1 = getDataAdapter.get(position);
Viewholder.ImageTitleNameView.setText(getDataAdapter1.getImageTitleName());
Viewholder.Mrp.setText(getDataAdapter1.getMrp());
Viewholder.Discount.setText(getDataAdapter1.getDiscount());
categoryId = getDataAdapter1.getImageTitleName();
imageLoader1 = ServerImageParseAdapter.getInstance(context).getImageLoader();
imageLoader1.get(getDataAdapter1.getImageServerUrl(),
ImageLoader.getImageListener(
Viewholder.networkImageView,//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.networkImageView.setImageUrl(getDataAdapter1.getImageServerUrl(), imageLoader1);
}
#Override
public int getItemCount() {
return getDataAdapter.size();
}
class ViewHolder extends RecyclerView.ViewHolder{
public TextView ImageTitleNameView;
public TextView imageid;
public NetworkImageView networkImageView ;
public CardView cardView ;
public TextView Mrp;
public TextView Rate;
public TextView Discount;
public ViewHolder(final View itemView) {
super(itemView);
ImageTitleNameView = (TextView) itemView.findViewById(R.id.textView_item) ;
networkImageView = (NetworkImageView) itemView.findViewById(R.id.VollyNetworkImageView1);
cardView = (CardView) itemView.findViewById(R.id.cardview1);
Mrp = (TextView) itemView.findViewById(R.id.textViewMrp) ;
Rate = (TextView) itemView.findViewById(R.id.textViewRate) ;
Discount = (TextView) itemView.findViewById(R.id.textViewDiscount) ;
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int pos = getAdapterPosition();
Log.d("LOGTAG", "position : "+pos);
Log.d("LOGTAG", "position : "+getDataAdapter.get(pos).getImageId());
ProductFragment fragobj=new ProductFragment();
Bundle bundle=new Bundle();
bundle.putString("subcategory_Product_ID", getDataAdapter.get(pos).getImageId());
fragobj.setArguments(bundle);
switchFragment(R.id.container_body, fragobj); //replace container ID
}
});
}
}
public void switchFragment(int id, Fragment fragment) {
if (context == null)
return;
//MainActivity is your activity where FriendsFragment is called
if (context instanceof HomeActivity) {
HomeActivity homeActivity = (HomeActivity) context;
homeActivity.loadFragment(id, fragment);
}
}
private class MyOnClickListener implements View.OnClickListener {
#Override
public void onClick(View v) {
GetDataAdapter getDataAdapter = new GetDataAdapter();
}
}
}
fragment_sample.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="#dimen/title_padding"
android:paddingRight="#dimen/title_padding">
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|top"/>
<com.bartoszlipinski.recyclerviewheader2.RecyclerViewHeader
android:id="#+id/header"
android:layout_width="match_parent"
android:layout_height="#dimen/header_height"
android:layout_gravity="center_horizontal|top"
android:layout_margin="#dimen/recycler_divider_width"
android:background="#drawable/rounded_background_header">
<Button
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:background="?selectableItemBackgroundBorderless"
android:fontFamily="sans-serif-light"
android:textAllCaps="false"
android:text="#string/header"
android:textColor="#color/clouds"
android:textSize="20sp"/>
</com.bartoszlipinski.recyclerviewheader2.RecyclerViewHeader>
</FrameLayout>
layout_item
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/layout"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="#dimen/recycler_divider_width"
android:background="#drawable/round_background_green">
<TextView
android:layout_width="wrap_content"
android:layout_height="80dp"
android:layout_gravity="center"
android:gravity="center"
android:fontFamily="sans-serif-light"
android:text="#string/item"
android:textSize="16sp"
android:textColor="#color/clouds" />
</FrameLayout>
You're setting your OnClickListener on the RecyclerViewHeader, when I believe you want to set it on the button you have inside your RecyclerViewHeader.
Add an android:id to the Button in your RecyclerViewHeader
<Button
android:id="#+id/button_header"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:background="?selectableItemBackgroundBorderless"
android:fontFamily="sans-serif-light"
android:textAllCaps="false"
android:text="#string/header"
android:textColor="#color/clouds"
android:textSize="20sp"/>
Find this Button in your HomeFragment
recyclerHeader = (RecyclerViewHeader) rootView.findViewById(R.id.header);
recyclerHeader.attachTo(recyclerView);
Button headerButton = (Button) recyclerHeader.findViewById(R.id.button_header);
Set OnClickListener on the headerButton instead of the RecyclerViewHeader
headerButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("LOG", "clicked");
}
});
I think the reason why onClickListener don't work for RecyclerViewHeader because inside RecyclerViewHeader you have a Button.
This button will display above RecyclerViewHeader have width/height match RecyclerViewHeader.
So you will never be able to click on RecyclerViewHeader, just able to click on Button
If you still want to handle onClickListener on RecyclerViewHeader, you need set the size of Button smaller then you can click RecyclerViewHeader

How save the state of RecyclerView row item?

I have a recyclerview which populates data from SQL database. Now each row in the recyclerview has a seekbar which when moved displays it's progress in a textview inside the same row. The problem is when I scroll the recyclerview up or down then return back to the first changed row, the seekbar is returned to its default position. How can I make it save the new position ? In normal activities/fragments I use lifecycle methods as "onPause" to save/restore the state. Here we have onAttachedToRecyclerView, I think it should solve my problem but I don't know exactly how.
EDIT : here is a full simple app files which I'm working on to test this problem.
MainActivity.class
public class MainActivity extends AppCompatActivity {
private List<Score> scoreList = new ArrayList<>();
private RecyclerView recyclerView;
private MyAdapter mAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
mAdapter = new MyAdapter(scoreList);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(mAdapter);
prepareScoreData();
}
private void prepareScoreData() {
Score score = new Score("title", 5);
scoreList.add(score);
for(int i= 0; i<1000; i++){
score = new Score("title", 5);
scoreList.add(score);
}
mAdapter.notifyDataSetChanged();
}
}
MyAdapter
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private List<Score> scoresList;
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView title, scoreView;
SeekBar seekbar;
public MyViewHolder(View view) {
super(view);
title = (TextView) view.findViewById(R.id.title);
scoreView = (TextView) view.findViewById(R.id.score);
seekbar = (SeekBar) view.findViewById(R.id.seekbar);
}
}
public MyAdapter(List<Score> scoresList) {
this.scoresList = scoresList;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
final Score score = scoresList.get(position);
holder.title.setText(score.getTitle());
if (!score.getProgressed()) {
holder.seekbar.setProgress(0) ;
} else {
holder.seekbar.setProgress(score.getSeekbarProgress());
}
holder.seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
holder.scoreView.setText(String.valueOf(i));
score.setSeekbarProgress(i);
score.setProgressed(true);
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
#Override
public int getItemCount() {
return scoresList.size();
}
}
Score class
public class Score {
private String title;
int seekbarProgress;
boolean progressed;
public Score() {
}
public Score(String title,int seekbarProgress) {
this.title = title;
this.seekbarProgress = seekbarProgress;
}
public void setProgressed(boolean progressed) {
this.progressed = progressed;
}
public void setTitle(String title) {
this.title = title;
}
public void setSeekbarProgress(int seekbarProgress) {
this.seekbarProgress = seekbarProgress;
}
public String getTitle() {
return title;
}
public int getSeekbarProgress() {
return seekbarProgress;
}
public boolean getProgressed() {
return progressed;
}
}
MainActivity_Layout
<?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"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.moaness.tut_recyclerview.MainActivity">
<!-- A RecyclerView with some commonly used attributes -->
<android.support.v7.widget.RecyclerView
android:id="#+id/my_recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
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="wrap_content"
android:focusable="true"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="60dp"
android:paddingBottom="60dp"
android:layout_marginBottom="10dp"
android:clickable="true"
android:background="#f2f2f2"
android:orientation="vertical">
<TextView
android:id="#+id/title"
android:text="title"
android:textColor="#color/title"
android:textSize="16dp"
android:paddingTop="16dp"
android:textStyle="bold"
android:layout_alignParentTop="true"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/score"
android:text="score"
android:layout_below="#+id/title"
android:textSize="16dp"
android:paddingBottom="16dp"
android:textStyle="bold"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<SeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/score"
android:id="#+id/seekbar"
/>
</RelativeLayout>
If you are using recyclerview you need to maintain states of each row, means if you are checking using a condition(i.e. if) at any stage of recyclerview item(in recyclerview adapter class) then you need to handle else as well. I can send you a code snippet so you can have a good idea for recyclerview adapter.
public class ContactsAdapter extends RecyclerView.Adapter<ContactsAdapter.ViewHolder> {
List<ViewHolder> holders = new ArrayList<ViewHolder>();
private ArrayList<ContactModel> arrayList = new ArrayList<>();
private Context context;
private LayoutInflater inflater;
public void clearAdapter() {
arrayList.clear();
notifyDataSetChanged();
}
public ContactsAdapter(Context context, ArrayList<ContactModel> arrayList) {
this.context = context;
this.arrayList = arrayList;
}
public void setList(ArrayList<ContactModel> listSearch) {
this.arrayList = listSearch;
notifyItemRangeChanged(0, listSearch.size());
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
inflater = LayoutInflater.from(parent.getContext());
View view = inflater.inflate(R.layout.custom_row_for_contacts, parent, false);
ViewHolder viewHolder = new ViewHolder(view);
holders.add(viewHolder);
return viewHolder;
}
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
final ContactModel current = this.arrayList.get(position);
holder.txtDriverName.setText(current.getName());
holder.txtDriverPhone.setText(current.getPhone());
if (current.getImgUrl().length() > 0) {
String urlLicenceThumb = UrlEndPoints.parentUrl + current.getImgUrl();
Glide.with(context).load(urlLicenceThumb).error(R.mipmap.ic_launcher).into(holder.imgDriver);
} else {
Glide.with(context).load(R.mipmap.ic_launcher).into(holder.imgDriver);
}
}
public void delete(int position) {
arrayList.remove(position);
notifyItemRemoved(position);
}
#Override
public int getItemCount() {
return (null != arrayList ? arrayList.size() : 0);
}
class ViewHolder extends RecyclerView.ViewHolder {
private TextView txtDriverName, txtDriverPhone;
private CircleImageView imgDriver;
private Button btnInvite;
private CheckBox chkAdd;
public ViewHolder(View itemView) {
super(itemView);
chkAdd = (CheckBox) itemView.findViewById(R.id.chkAdd);
imgDriver = (CircleImageView) itemView.findViewById(R.id.imgDriver);
txtDriverName = (TextView)itemView.findViewById(R.id.txtDriverName);
txtDriverPhone = (TextView) itemView.findViewById(R.id.txtDriverPhone);
btnInvite = (Button) itemView.findViewById(R.id.btnInvite);
}
}
}

child recyclerview methods is not calling (onCreateViewHolder, onBindViewHolder). But getItemCount() method is calling

I have one recyclerview and this will display data in vertically. One row will display data in horizontally so i used another recyclerview. which is calling from first recyclerview's onBindViewHolder.
parent recylerview is working but when i am adding child recycler view. these methods are not calling (onCreateViewHolder, onBindViewHolder). Probably something issue in xml files.
parent xml:-
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
tools:context="com.catrackapp.catrack.MainActivity" >
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/textView"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="VIDEO LATEST"
android:id="#+id/textView"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:gravity="center" />
</RelativeLayout>
child xml which i am using in onCreateViewHolder as displaying row
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</android.support.design.widget.CoordinatorLayout>
and this xml is using by child recyclerview.
<?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="wrap_content"
android:paddingTop="5dp"
android:paddingBottom="5dp"
>
<com.google.android.youtube.player.YouTubeThumbnailView
android:id="#+id/thumbnail"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/no_thumbnail"
android:adjustViewBounds="true" />
</LinearLayout>
These are code parent and child.
public class MoviesAdapter extends RecyclerView.Adapter<MoviesAdapter.MyViewHolder> {
private List<Videos> moviesList;
// private ThumbnailListener thumbnailListener;
public class MyViewHolder extends RecyclerView.ViewHolder {
// public VideoView videoView;
//public ImageView imageView;
// YouTubeThumbnailView thumbnail;
RecyclerView recyclerView1;
public MyViewHolder(View view) {
super(view);
// videoView = (VideoView) view.findViewById(R.id.videoView);
// imageView = (ImageView) view.findViewById(R.id.imageView);
// thumbnail = (YouTubeThumbnailView) view.findViewById(R.id.thumbnail);
recyclerView1 = (RecyclerView) view.findViewById(R.id.recycler_view1);
// LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
// recyclerView1.setLayoutManager(layoutManager);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getActivity());
recyclerView1.setLayoutManager(mLayoutManager);
}
}
public MoviesAdapter(List<Videos> moviesList) {
this.moviesList = moviesList;
//thumbnailListener = new ThumbnailListener();
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.test, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
Videos movie = moviesList.get(position);
System.out.println("first = " + movie.getImage());
String url = movie.getVideo_url();
final String m = url.substring(url.lastIndexOf('/') + 1);
final String txt = movie.getPlain_text2();
System.out.println("url = "+m);
List<String> l = new ArrayList<String>();
l.add(m);
l.add(m);
l.add(m);
l.add(m);
l.add(m);
final MoviesAdapterHorizontal adapter = new MoviesAdapterHorizontal(l);
holder.recyclerView1.setAdapter(adapter);
// holder.recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
adapter.notifyDataSetChanged();
}
#Override
public int getItemCount() {
return moviesList.size();
}
private final class ThumbnailListener implements
YouTubeThumbnailView.OnInitializedListener,
YouTubeThumbnailLoader.OnThumbnailLoadedListener {
#Override
public void onInitializationSuccess(
YouTubeThumbnailView view, YouTubeThumbnailLoader loader) {
loader.setOnThumbnailLoadedListener(this);
// thumbnailViewToLoaderMap.put(view, loader);
// view.setImageResource(R.drawable.loading_thumbnail);
String videoId = (String) view.getTag();
loader.setVideo(videoId);
}
#Override
public void onInitializationFailure(
YouTubeThumbnailView view, YouTubeInitializationResult loader) {
view.setImageResource(R.drawable.no_thumbnail);
}
#Override
public void onThumbnailLoaded(YouTubeThumbnailView view, String videoId) {
}
#Override
public void onThumbnailError(YouTubeThumbnailView view, YouTubeThumbnailLoader.ErrorReason errorReason) {
view.setImageResource(R.drawable.no_thumbnail);
}
}
}
//Horizontal images view.
public class MoviesAdapterHorizontal extends RecyclerView.Adapter<MoviesAdapterHorizontal.MyViewHolder> {
private List<String> moviesList;
private ThumbnailListener thumbnailListener;
public class MyViewHolder extends RecyclerView.ViewHolder {
YouTubeThumbnailView thumbnail;
public MyViewHolder(View view) {
super(view);
thumbnail = (YouTubeThumbnailView) view.findViewById(R.id.thumbnail);
}
}
public MoviesAdapterHorizontal(List<String> moviesList) {
this.moviesList = moviesList;
thumbnailListener = new ThumbnailListener();
System.out.println("called size = "+this.moviesList.size());
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.hotrow, parent, false);
System.out.println("onCreateViewHolder called");
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
final String url = moviesList.get(position);
System.out.println("rahul url" + url);
final String m = url.substring(url.lastIndexOf('/') + 1);
System.out.println("url = "+m);
holder.thumbnail.setTag(m);
holder.thumbnail.initialize("AIzaSyDW-sxPUqy2rD6ZWs3vTNb0jKEKA21RjrY", thumbnailListener);
holder.thumbnail.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(getActivity(), FullscreenDemoActivity.class);
intent.putExtra("url", m);
intent.putExtra("txt", "");
startActivity(intent);
}
});
}
#Override
public int getItemCount() {
System.out.println("moviesList 2 size = "+this.moviesList.size());
return this.moviesList.size();
}
private final class ThumbnailListener implements
YouTubeThumbnailView.OnInitializedListener,
YouTubeThumbnailLoader.OnThumbnailLoadedListener {
#Override
public void onInitializationSuccess(
YouTubeThumbnailView view, YouTubeThumbnailLoader loader) {
loader.setOnThumbnailLoadedListener(this);
String videoId = (String) view.getTag();
loader.setVideo(videoId);
}
#Override
public void onInitializationFailure(
YouTubeThumbnailView view, YouTubeInitializationResult loader) {
view.setImageResource(R.drawable.no_thumbnail);
}
#Override
public void onThumbnailLoaded(YouTubeThumbnailView view, String videoId) {
}
#Override
public void onThumbnailError(YouTubeThumbnailView view, YouTubeThumbnailLoader.ErrorReason errorReason) {
view.setImageResource(R.drawable.no_thumbnail);
}
}
}
kindly help me. i am trying to fix it last 4 days. but now able to fix.
UPDATE:-
i used it and now child all methods are calling but layout is not displaying.
MoviesAdapterHorizontal adapter = new MoviesAdapterHorizontal(l);
holder.recyclerView1.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false));
holder.recyclerView1.setAdapter(adapter);
adapter.notifyDataSetChanged();
i saw below error in log
04-21 11:40:50.571 27006-27006/com.androidbelieve.drawerwithswipetabs W/ResourcesManager: getTopLevelResources: com.androidbelieve.drawerwithswipetabs for user 0
In CoordinatorLayout layout ,you cannot set RecyclerView height to android:layout_height="wrap_content"
try to set
android:layout_height="200dp"
OR
android:layout_height="match_parent"

RecyclerView not generating list when it has a view above it

So I cannot make the RecyclerView generate the given list once I have another view above it. The view above it and the recycler view are both within a LinearLayout and which is the single child of a NestedScrollView (used for collapsing the toolbar). Once RecyclerView is the only view in the fragment everything works as expected.
StocksCompleteListFragment.java
public class StocksCompleteListFragment extends Fragment {
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
NestedScrollView sv = (NestedScrollView) inflater.inflate(
R.layout.fragment_stocks_completelist, container, false);
LinearLayout mylinear = (LinearLayout) sv.findViewById(R.id.mainLinear);
RecyclerView rv = (RecyclerView) mylinear.findViewById(R.id.recyclerview);
if (rv == null){
Toast.makeText(getActivity(),"Null", Toast.LENGTH_SHORT).show();
}
setupRecyclerView(rv);
return sv;
}
private void setupRecyclerView(RecyclerView recyclerView) {
recyclerView.setLayoutManager(new LinearLayoutManager(recyclerView.getContext()));
recyclerView.setAdapter(new SimpleStringRecyclerViewAdapter(getActivity(),
getRandomSublist(Cheeses.sCheeseStrings, 30)));
}
private List<String> getRandomSublist(String[] array, int amount) {
ArrayList<String> list = new ArrayList<>(amount);
Random random = new Random();
while (list.size() < amount) {
list.add(array[random.nextInt(array.length)]);
}
return list;
}
public static class SimpleStringRecyclerViewAdapter
extends RecyclerView.Adapter<SimpleStringRecyclerViewAdapter.ViewHolder> {
private final TypedValue mTypedValue = new TypedValue();
private int mBackground;
private List<String> mValues;
public static class ViewHolder extends RecyclerView.ViewHolder {
public String mBoundString;
public final View mView;
public final ImageView mImageView;
public final TextView mTextView;
public ViewHolder(View view) {
super(view);
mView = view;
mImageView = (ImageView) view.findViewById(R.id.avatar);
mTextView = (TextView) view.findViewById(android.R.id.text1);
}
#Override
public String toString() {
return super.toString() + " '" + mTextView.getText();
}
}
public String getValueAt(int position) {
return mValues.get(position);
}
public SimpleStringRecyclerViewAdapter(Context context, List<String> items) {
context.getTheme().resolveAttribute(R.attr.selectableItemBackground, mTypedValue, true);
mBackground = mTypedValue.resourceId;
mValues = items;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item, parent, false);
view.setBackgroundResource(mBackground);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.mBoundString = mValues.get(position);
holder.mTextView.setText(mValues.get(position));
holder.mView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Context context = v.getContext();
Intent intent = new Intent(context, CheeseDetailActivity.class);
intent.putExtra(CheeseDetailActivity.EXTRA_NAME, holder.mBoundString);
context.startActivity(intent);
}
});
Glide.with(holder.mImageView.getContext())
.load(Cheeses.getRandomCheeseDrawable())
.fitCenter()
.into(holder.mImageView);
}
#Override
public int getItemCount() {
return mValues.size();
}
}
}
And here's the layout xml fragment_stocks_completelist.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<LinearLayout
android:id="#+id/mainLinear"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="#+id/progressBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginBottom="4dp"
android:layout_marginTop="8dp"
android:background="#color/grayBackground"
android:gravity="center_vertical|center_horizontal"
android:padding="4dp"
android:visibility="gone">
<ProgressBar
android:id="#+id/progressBar1"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
You need to set
android:fillViewport="true"
on your NestedRecyclerView. If you put it into the CoordinatorLayout then also specify the behavior (which you've already done)

Categories

Resources