CheckBox in RecyclerView not working when pressed - android

I have basic RecyclerView item with TextView and CheckBox. But when I click CheckBox, it does not work. All the more amazing it works when I long pressed.
I made a research and found android:descendantFocusability="blocksDescendants" , android:clickable="false", android:focusable="false" , android:longClickable="false" but they didn't help me
Here is my RecyclerView Item layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants">
<TextView
android:id="#+id/item_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="TextView"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:layout_marginLeft="10dp"
android:layout_marginStart="10dp"
android:textColor="#000000"/>
<android.support.v7.widget.AppCompatCheckBox
android:id="#+id/item_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:layout_marginEnd="10dp"
app:buttonTint="#color/colorAccent"
android:focusable="false"
android:focusableInTouchMode="false"/>
</LinearLayout>
Here is my Adapter class
public class FilterTypeAdapter extends RecyclerView.Adapter<FilterTypeAdapter.MyViewHolder> {
private ArrayList<String> mData;
private Context mContext;
public FilterTypeAdapter() {
}
public FilterTypeAdapter(Context mContext, ArrayList<String> mData) {
this.mContext = mContext;
this.mData = mData;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int i) {
View v = LayoutInflater.from(mContext).inflate(R.layout.recycler_view_single_row, parent, false);
MyViewHolder vh = new MyViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.mText.setText(mData.get(position));
holder.mCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
Toast.makeText(mContext, "Status is: " + isChecked + "", Toast.LENGTH_SHORT).show();
}
});
}
#Override
public int getItemCount() {
return mData.size();
}
// View Holder
public class MyViewHolder extends RecyclerView.ViewHolder {
private TextView mText;
private CheckBox mCheckBox;
public MyViewHolder(View itemView) {
super(itemView);
mText = itemView.findViewById(R.id.item_text);
mCheckBox = itemView.findViewById(R.id.item_checkbox);
}
}
}

I found everything working correctly here.
package <your_package>;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.AppCompatCheckBox;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.TextView;
import android.widget.Toast;
import <your_package>.R;
import java.util.ArrayList;
public class TestActivity extends AppCompatActivity {
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_recyclerview);
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
ArrayList<String> data = new ArrayList<>();
for(int i =0; i < 1000; i++) {
data.add(String.valueOf(i));
}
recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext(), LinearLayoutManager.VERTICAL, false));
recyclerView.setAdapter(new FilterTypeAdapter(getApplicationContext(), data));
}
public class FilterTypeAdapter extends RecyclerView.Adapter<MyViewHolder> {
private ArrayList<String> mData;
private HashMap<String, Boolean> mChecked;
private Context mContext;
public FilterTypeAdapter() {
}
public FilterTypeAdapter(Context mContext, ArrayList<String> mData) {
this.mContext = mContext;
this.mData = mData;
this.mChecked = new HashMap<>();
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int i) {
View v = TestActivity.this.getLayoutInflater().inflate(R.layout.test_recyclerview_item, parent, false);
MyViewHolder vh = new MyViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
holder.mText.setText(mData.get(position));
holder.mCheckBox.setOnCheckedChangeListener(null);
if(mChecked.containsKey(mData.get(position))) {
holder.mCheckBox.setChecked(mChecked.get(mData.get(position)));
}
else {
holder.mCheckBox.setChecked(false);
}
holder.mCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mChecked.put(mData.get(holder.getAdapterPosition()), isChecked);
Toast.makeText(mContext, "Status is: " + isChecked + "", Toast.LENGTH_SHORT).show();
}
});
}
#Override
public int getItemCount() {
return mData.size();
}
}
// View Holder
public class MyViewHolder extends RecyclerView.ViewHolder {
private TextView mText;
private AppCompatCheckBox mCheckBox;
public MyViewHolder(View itemView) {
super(itemView);
mText = (TextView) itemView.findViewById(R.id.item_text);
mCheckBox = (AppCompatCheckBox) itemView.findViewById(R.id.item_checkbox);
}
}
}
R.layout.test_recyclerview
<android.support.v7.widget.RecyclerView android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="30dp"
android:layout_marginEnd="10dp"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
xmlns:android="http://schemas.android.com/apk/res/android" />
R.layout.testrecyclerview_item
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/item_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:layout_marginLeft="10dp"
android:layout_marginStart="10dp"
android:textColor="#000000"/>
<android.support.v7.widget.AppCompatCheckBox
android:id="#+id/item_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:layout_marginEnd="10dp"
app:buttonTint="#color/colorAccent"
/>
</LinearLayout>

remove these lines from checkbox widget
android:focusable="false"
android:focusableInTouchMode="false"
i think this may help

Related

Not being able to place an onClickListener on the Grid Items provided by a custom BaseAdapter

I currently have a grid view using a base adapter inside a fragment and I am trying to transfer to a different fragment when one of the items is clicked but none of the solutions I found on stack overflow has worked. I might miss something.
Adapter
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.licenta.joberfrontend.R;
import com.licenta.joberfrontend.rest.backend_entieties.Category;
import java.util.ArrayList;
import java.util.List;
public class CategoriesAdapter extends BaseAdapter {
public class ViewHolder {
TextView textName;
ImageView imageView;
}
private ArrayList<Category> categoryList;
public Context context;
public CategoriesAdapter(List<Category> apps, Context context) {
this.context = context;
this.categoryList = (ArrayList<Category>) apps;
}
#Override
public int getCount() {
return categoryList.size();
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View view, ViewGroup parent) // inflating the layout and initializing widgets
{
ViewHolder viewHolder;
if (view == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.category_list_content, parent, false);
viewHolder = new ViewHolder();
viewHolder.textName = view.findViewById(R.id.textName);
viewHolder.imageView = view.findViewById(R.id.iconView);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
// here we are setting up the names and images
viewHolder.textName.setText(categoryList.get(position).getName());
viewHolder.imageView.setImageResource(this.context.getResources().getIdentifier(categoryList.get(position).getCategoryIconId(), "mipmap", this.context.getPackageName()));
return view;
}
}
Fragment's OnCreate
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final LocalStorageSaver localStorageSaver = new LocalStorageSaver(Objects.requireNonNull(getContext()));
final ToastShower toastShower = new ToastShower();
//REST services creation
final RetrofitCreator retrofitCreator = new RetrofitCreator();
final Retrofit retrofit = retrofitCreator.getRetrofit();
final CategoryService categoryService = retrofit.create(CategoryService.class);
final Call<List<Category>> getCategoriesRequest = categoryService.getAllCategoriesAndTheirJobs(localStorageSaver.getValueFromStorage(Constants.TOKEN));
getCategoriesRequest.enqueue(
new Callback<List<Category>>() {
#Override
public void onResponse(Call<List<Category>> call, Response<List<Category>> response) {
toastShower.showToast("Categories succesfully retrieved from backend.", getContext());
final GridView gridView = Objects.requireNonNull(getView()).findViewById(R.id.gridViewNewContract);
gridView.setAdapter(new CategoriesAdapter(response.body(), getActivity()));
}
#Override
public void onFailure(Call<List<Category>> call, Throwable t) {
toastShower.showToast("There has been a problem with retrieving the categories data!", getContext());
}
}
);
}
Items inside the grid view
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.cardview.widget.CardView
android:layout_width="100dp"
android:layout_height="100dp"
app:cardCornerRadius="15dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal|center_vertical"
android:layout_marginLeft="10dp"
android:layout_marginTop="15dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="15dp"
android:orientation="vertical">
<ImageView
android:id="#+id/iconView"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="center_horizontal"
android:src="#mipmap/ic_list"
android:tint="#color/colorAccent" />
<TextView
android:id="#+id/textName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:fontFamily="sans-serif"
android:maxLength="12"
android:text="#string/appName"
android:textColor="#color/colorAccent"
android:textSize="13sp" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</RelativeLayout>
If you need any more information I will gladly provided.
I can mention that I've tried placing listeners both in the adapter and in the fragment directly on the grid.
please try this
viewHolder.imageView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//do stuff
}
});

RecyclerView item onClickListener doesn't work on a first click, but works on a second one

Adapter
public class MoviesAdapter extends
RecyclerView.Adapter<MoviesAdapter.MoviesViewHolder> {
private static final String baseMovieUrl = "http://image.tmdb.org/t/p/w500";
private ArrayList<Movie> movies;
private Context context;
public MoviesAdapter(ArrayList<Movie> movies, Context context) {
this.movies = movies;
this.context = context;
}
#NonNull
#Override
public MoviesViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
return new MoviesViewHolder(layoutInflater.inflate(R.layout.movie_square, parent, false));
}
#Override
public void onBindViewHolder(#NonNull MoviesViewHolder holder, int position) {
holder.setData(position);
}
#Override
public int getItemCount() {
return movies.size();
}
public class MoviesViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private ConstraintLayout movieConstraint;
private TextView movieName;
private TextView movieRate;
private ImageView moviePoster;
public MoviesViewHolder(View itemView) {
super(itemView);
movieConstraint = itemView.findViewById(R.id.movie_holder_constraints);
movieName = itemView.findViewById(R.id.movie_name_tv);
movieRate = itemView.findViewById(R.id.movie_rating_tv);
moviePoster = itemView.findViewById(R.id.movie_iv);
movieConstraint.setOnClickListener(this);
}
public void setData(int position) {
movieConstraint.setTag(position);
movieName.setText(movies.get(position).getMovieName());
movieRate.setText(movies.get(position).getMovieRating() + "");
if (!Objects.equals(movies.get(position).getMovieUrl(), "") && movies.get(position).getMovieUrl() != null) {
Glide.with(moviePoster).load
(baseMovieUrl + movies.get(position).getMovieUrl())
.into(moviePoster);
} else Log.i("No url!", "No url!");
}
#Override
public void onClick(View view) {
int pos = (int) view.getTag();
view.setEnabled(false);
changeActivity(pos);
view.setEnabled(true); // TODO Find a way to prevent 2 acctivites to open simultaniously
}
private void changeActivity(int pos) {
Movie movie = movies.get(pos);
Intent intent = new Intent(context, MovieInfo.class);
intent.putExtra("movie", movie);
ActivityOptionsCompat options = ActivityOptionsCompat.
makeSceneTransitionAnimation((Activity) context, moviePoster, "profile");
context.startActivity(intent, options.toBundle());
}
}
}
and the xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/movie_holder_constraints"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="3dp">
<android.support.v7.widget.CardView
android:id="#+id/movie_cv"
android:layout_width="185dp"
android:layout_height="250dp"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:focusable="false"
android:focusableInTouchMode="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<android.support.constraint.ConstraintLayout
android:id="#+id/inside_movie_constraints"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="false"
android:focusableInTouchMode="false"
>
<ImageView
android:id="#+id/movie_iv"
android:layout_width="185dp"
android:layout_height="180dp"
android:scaleType="fitXY"
android:focusable="false"
android:focusableInTouchMode="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#mipmap/ic_launcher" />
<TextView
android:id="#+id/movie_rating_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="16dp"
android:layout_marginTop="2dp"
android:text="9.5"
android:textColor="#color/colorAccent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/movie_name_tv"
app:layout_constraintVertical_bias="1.0" />
<TextView
android:id="#+id/movie_name_tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="Guardian's Of The Galaxy"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintHorizontal_weight="1"
android:gravity="center"
android:includeFontPadding="false"
app:layout_constraintTop_toBottomOf="#+id/movie_iv" />
</android.support.constraint.ConstraintLayout>
</android.support.v7.widget.CardView>
When clicking on the item in the recyclerView it wont open the activity or call the OnClickListener, after clicking another time the function is being called.
scrolling would also allow me to click on the items aswell.
I have heared changing the foucsable to false might solve this problem but as you can see in the xml it didn't.
Edit for adapter:
I changed the onClick to the onBindViewHolder, It fixed the problem although it doesn't feel to me like the right way to do it.
what do you say?
package com.example.galzaid.movies;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.support.annotation.NonNull;
import android.support.constraint.ConstraintLayout;
import android.support.v4.app.ActivityOptionsCompat;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import java.util.ArrayList;
import java.util.Objects;
public class MoviesAdapter extends
RecyclerView.Adapter<MoviesAdapter.MoviesViewHolder> implements
View.OnClickListener {
private static final String baseMovieUrl = "http://image.tmdb.org/t/p/w500";
private ArrayList<Movie> movies;
private Context context;
public MoviesAdapter(ArrayList<Movie> movies, Context context) {
this.movies = movies;
this.context = context;
}
#NonNull
#Override
public MoviesViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
return new MoviesViewHolder(layoutInflater.inflate(R.layout.movie_square, parent, false));
}
#Override
public void onBindViewHolder(#NonNull MoviesViewHolder holder, int position) {
holder.setData(position);
holder.itemView.setOnClickListener(this);
holder.getAdapterPosition();
}
#Override
public int getItemCount() {
return movies.size();
}
#Override
public void onClick(View view) {
ImageView moviePoster = view.findViewById(R.id.movie_iv);
changeActivity((int) view.getTag(), moviePoster);
}
private void changeActivity(int pos, ImageView moviePoster) {
Movie movie = movies.get(pos);
Intent intent = new Intent(context, MovieInfo.class);
intent.putExtra("movie", movie);
ActivityOptionsCompat options = ActivityOptionsCompat.
makeSceneTransitionAnimation((Activity) context, moviePoster, "profile");
context.startActivity(intent, options.toBundle());
}
public class MoviesViewHolder extends RecyclerView.ViewHolder {
private ConstraintLayout movieConstraint;
private TextView movieName;
private TextView movieRate;
private ImageView moviePoster;
public MoviesViewHolder(View itemView) {
super(itemView);
movieConstraint = itemView.findViewById(R.id.movie_holder_constraints);
movieName = itemView.findViewById(R.id.movie_name_tv);
movieRate = itemView.findViewById(R.id.movie_rating_tv);
moviePoster = itemView.findViewById(R.id.movie_iv);
}
public void setData(int position) {
movieConstraint.setTag(position);
movieName.setText(movies.get(position).getMovieName());
movieRate.setText(movies.get(position).getMovieRating() + "");
if (!Objects.equals(movies.get(position).getMovieUrl(), "") && movies.get(position).getMovieUrl() != null) {
Glide.with(moviePoster).load
(baseMovieUrl + movies.get(position).getMovieUrl())
.into(moviePoster);
} else Log.i("No url!", "No url!");
}
}
}
I believe your problem is in this line
movieConstraint.setOnClickListener(this);
You shouldn't set it to ConstraintLayout, change the above line to this
itemView.setOnClickListener(this);
And there is nothing wrong in setting your onClickListener in a ViewHolder constructor.
EDIT:
In order to get the position in onClick you can use getAdapterPosition() method.
Set the OnClickListener in binding method, which in your case is public void setData(int position)
RecyclerView as its name says is reusing the views it created, so for every item you should set all the info from the start, including onClick listeners
That should fix your problems, and you will be able to resign from using setTag to differentiate the views
Avoid setting onClick listeners in ViewHolder constructors.

White screen in listview?

Can someone tell me what's wrong with this adapter? I'm getting an empty RecyclerView but a list that has 11 items in it? we have checked the customer class and the MainActivity and it seems to be correct. we log the customers.size in the getitems and find that there should be no trouble. could it be something wrong with the viewHolder class?
package com.example.jenso.test1yay;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.List;
import static android.content.ContentValues.TAG;
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private List<Customer> customers;
private Context context;
public MyAdapter(List<Customer> listItems ,Context context){
this.customers = listItems;
this.context = context;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item,parent, false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Customer customer = customers.get(position);
if (holder != null) {
holder.textViewHead.setText(customer.getName());
holder.textViewDesc.setText(customer.getLastName());
}
}
#Override
public int getItemCount() {
Log.d(TAG, "getItemCount: "+ customers.size());
return customers.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
public TextView textViewHead;
public TextView textViewDesc;
public ViewHolder(View itemView) {
super(itemView);
textViewHead = (TextView) itemView.findViewById(R.id.textViewHead);
textViewDesc = (TextView) itemView.findViewById(R.id.textViewDesc);
}
}
}
package com.example.jenso.test1yay;
import android.nfc.Tag;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private RecyclerView.Adapter adapter;
private List<Customer> customers;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
customers = new ArrayList<>();
for(int i = 1; i <= 10; i++){
Customer customer = new Customer("Jens" + (i+1),
"Svensson"
);
customers.add(customer);
}
adapter = new MyAdapter(customers, this);
recyclerView.setAdapter(adapter);
}
}
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.constraint.ConstraintLayout
android:id="#+id/cardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="#+id/textViewDesc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="2dp"
android:text="Description"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textViewHead" />
<TextView
android:id="#+id/textViewHead"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="2dp"
android:text="Heading"
android:textAppearance="#style/Base.TextAppearance.AppCompat.Large"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
</android.support.constraint.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.jenso.test1yay.MainActivity">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0"
tools:listitem="#layout/list_item" />
</android.support.constraint.ConstraintLayout>
Try change size of TextView android:layout_width="0dp" to 100dp
Late to the party, but try to pass the activity's Context into the adapter and then use that context in LayoutInflater.from instead of parent.getContext()
i make some correction in your code try it.
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private List<Customer> customers=new ArrayList<>();
private Context context;
public MyAdapter(List<Customer> listItems, Context context) {
this.customers = listItems;
this.context = context;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item, parent, false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Customer customer = customers.get(position);
if (holder != null) {
holder.textViewHead.setText(customer.getName());
holder.textViewDesc.setText(customer.getLastName());
}
}
#Override
public int getItemCount() {
Log.d(TAG, "getItemCount: " + customers.size());
return customers.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView textViewHead;
public TextView textViewDesc;
public ViewHolder(View itemView) {
super(itemView);
textViewHead = (TextView) itemView.findViewById(R.id.textViewHead);
textViewDesc = (TextView) itemView.findViewById(R.id.textViewDesc);
}
}
}
in main activity..
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private MyAdapter adapter;
private List<Customer> customers;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
customers = new ArrayList<>();
for(int i = 1; i <= 10; i++){
Customer customer = new Customer("Jens" + (i+1),
"Svensson"
);
customers.add(customer);
}
adapter = new MyAdapter(customers, this);
recyclerView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
}

Firebase Recycler Adapter not working with recycler view of children

I have a database where my data looks like this.
I have used Firebase Recycler Adapter to the info for S1, S2 and so on, to represent that data in a recycler view. However the data is not showing only in my application. The application is for a teacher to see whether the student is present or not by retrieving data from Firebase.
AttendaceFrag.java
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import com.firebase.ui.database.FirebaseRecyclerAdapter;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
public class AttendanceFrag extends Fragment {
RecyclerView recyclerView;
DatabaseReference databaseReference;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.activity_attendance_frag, container, false);
recyclerView = (RecyclerView) v.findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
databaseReference = FirebaseDatabase.getInstance().getReference().child("Student");
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot != null) {
Toast.makeText(getContext(), "Data to show", Toast.LENGTH_LONG).show();
startShowing();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
return v;
}
private void startShowing() {
FirebaseRecyclerAdapter<Student, AttendanceFrag.RequestViewHolder> firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<Student, AttendanceFrag.RequestViewHolder>(
Student.class,
R.layout.custom_row,
AttendanceFrag.RequestViewHolder.class,
databaseReference
) {
#Override
protected void populateViewHolder(AttendanceFrag.RequestViewHolder viewHolder, Student model, int position) {
viewHolder.setName(model.getName());
viewHolder.setAp(model.getAp());
viewHolder.setRegno(model.getRegno());
}
};
recyclerView.setAdapter(firebaseRecyclerAdapter);
}
public static class RequestViewHolder extends RecyclerView.ViewHolder {
View mView;
public RequestViewHolder(View itemView) {
super(itemView);
mView = itemView;
}
public void setName(String name) {
TextView stname = (TextView) mView.findViewById(R.id.st_name);
stname.setText(name);
}
public void setRegno(String regno) {
TextView stregno = (TextView) mView.findViewById(R.id.st_regno);
stregno.setText(regno);
}
public void setAp(String ap) {
TextView stap = (TextView) mView.findViewById(R.id.st_ap);
stap.setText(ap);
}
}
}
Student.java
public class Student {
private String name, regno,ap;
public Student(String name, String regno, String ap) {
this.name = name;
this.regno = regno;
this.ap = ap;
}
public Student() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRegno() {
return regno;
}
public void setRegno(String regno) {
this.regno = regno;
}
public String getAp() {
return ap;
}
public void setAp(String ap) {
this.ap = ap;
}
}
activity_attendance_frag.xml
<?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:padding="3dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.xxx.AttendanceFrag">
<TableLayout
android:id="#+id/table_lay"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TableRow
android:id="#+id/firstrow"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:background="#drawable/r1"
android:text="Sr. No."
android:id="#+id/srnohead"
android:textAlignment="center"
android:padding="5dp"
android:textColor="#color/colorPrimaryDark"
/>
<TextView
android:padding="5dp"
android:textAlignment="center"
android:background="#drawable/r1"
android:text="Reg. Number"
android:layout_width="135dp"
android:id="#+id/regNohead"
android:textColor="#color/colorPrimaryDark"/>
<TextView
android:padding="5dp"
android:background="#drawable/r1"
android:text="Name"
android:textAlignment="center"
android:layout_height="wrap_content"
android:layout_width="120dp"
android:id="#+id/namehead"
android:textColor="#color/colorPrimaryDark"/>
<TextView
android:padding="5dp"
android:background="#drawable/r1"
android:text="P/A"
android:layout_height="wrap_content"
android:id="#+id/attnhead"
android:textColor="#color/colorPrimaryDark"/>
</TableRow>
</TableLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/table_lay"
android:layout_alignParentStart="true"
android:layout_marginTop="33dp" />
</RelativeLayout>
custom_row.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="1"
android:padding="3dp">
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:background="#drawable/r1"
android:text="Sr. No."
android:id="#+id/st_sr"
android:textAlignment="center"
android:padding="5dp"
android:textColor="#color/colorPrimaryDark"
/>
<TextView
android:layout_height="wrap_content"
android:layout_width="135dp"
android:padding="5dp"
android:textAlignment="center"
android:background="#drawable/r1"
android:text="Reg. Number"
android:id="#+id/st_regno"
android:textColor="#color/colorPrimaryDark"/>
<TextView
android:padding="5dp"
android:background="#drawable/r1"
android:text="Name"
android:textAlignment="center"
android:layout_height="wrap_content"
android:layout_width="120dp"
android:id="#+id/st_name"
android:textColor="#color/colorPrimaryDark"/>
<TextView
android:layout_width="wrap_content"
android:padding="5dp"
android:background="#drawable/r1"
android:text="P/A"
android:layout_height="wrap_content"
android:id="#+id/st_ap"
android:textColor="#color/colorPrimaryDark"/>
</LinearLayout>
put this in your App level gradle : implementation 'com.firebaseui:firebase-ui-database:3.2.1'
In your onStart method put this :
#Override
protected void onStart() {
super.onStart();
Query query = FirebaseDatabase.getInstance()
.getReference()
.child("Blog")
.limitToLast(50);
FirebaseRecyclerOptions<BlogModel> options =
new FirebaseRecyclerOptions.Builder<BlogModel>()
.setQuery(query, BlogModel.class)
.build();
FirebaseRecyclerAdapter adapter = new FirebaseRecyclerAdapter<BlogModel, BlogViewHolder>(options) {
#Override
public BlogViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// Create a new instance of the ViewHolder, in this case we are using a custom
// layout called R.layout.message for each item
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.row_blog, parent, false);
return new BlogViewHolder(view);
}
#Override
protected void onBindViewHolder(BlogViewHolder holder, int position, BlogModel model) {
holder.setTitleBlog(model.getTitle());
holder.setTitleDesc(model.getDescription());
holder.setImage(getApplicationContext(), model.getImage_url());
}
};
adapter.startListening();
mRecycler.setAdapter(adapter);
}
in your BlogViewHolder put this :
public static class BlogViewHolder extends RecyclerView.ViewHolder {
View view;
public BlogViewHolder(View itemView) {
super(itemView);
view = itemView;
}
public void setTitleBlog(String title) {
TextView tvTitle = (TextView) view.findViewById(R.id.tv_title);
tvTitle.setText(title);
}
public void setTitleDesc(String desc) {
TextView tvDesc = (TextView) view.findViewById(R.id.tv_desc);
tvDesc.setText(desc);
}
public void setImage(Context context, String url) {
ImageButton ib = (ImageButton) view.findViewById(R.id.ib_blog);
Picasso.with(context).load(url).into(ib);
}
}
And your are all set to go :)
Your database reference pointing wrong node you can use it like this:
FirebaseDatabase.getInstance().getReferenceFromUrl("https://facapp-bee2.firebaseio.com/");
Then .child("Faculty/Student") and recylerview don't use addValueListener. Here you can find how to use recycler view in firebase

I tries to implement recycler view with multiple view but I am not getting the desired result

Check out my code:
import android.content.Context;
import android.content.Intent;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import org.w3c.dom.ls.LSException;
import java.util.ArrayList;
import java.util.Arrays;
/**
* Created by Ankit on 3/25/2016.
*/
public class CustomAdapterRecyclerView extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
Context context;
private ArrayList<String> questionsList;
LayoutInflater layoutInflater;
public CustomAdapterRecyclerView(Context context, ArrayList<String> questionsList) {
this.context = context;
this.questionsList = questionsList;
layoutInflater = LayoutInflater.from(context);
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case 1:
final View view = layoutInflater.inflate(R.layout.recycler_view_list, parent, false);
MyViewHolder myViewHolder = new MyViewHolder(view, context);
return myViewHolder;
default:
final View view1 = layoutInflater.inflate(R.layout.single_item_in_list, parent, false);
MyExpandedViewHolder myExpandedViewHolder= new MyExpandedViewHolder(view1, context,new ArrayList<String>(Arrays.asList("A","Aa")));
return myExpandedViewHolder;
}
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
switch (holder.getItemViewType())
{
case 1:
MyViewHolder vh = (MyViewHolder) holder;
vh.questionTitle.setText(questionsList.get(position));
break;
default:
MyExpandedViewHolder viewHolder= (MyExpandedViewHolder) holder;
viewHolder.getListView();
}
}
/*
#Override
public void onBindViewHolder(RecyclerView.V holder, int position) {
holder.questionTitle.setText(questionsList.get(position));
}*/
#Override
public int getItemCount() {
return questionsList.size();
}
#Override
public int getItemViewType(int position) {
if(position ==0|| position==1|| position==2)
{
return 0;
}
else
return 1;
}
public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView questionTitle;
private Context context;
public MyViewHolder(final View itemView, Context context) {
super(itemView);
this.context = context;
itemView.setOnClickListener(this);
questionTitle = (TextView) itemView.findViewById(R.id.question);
questionTitle.setOnClickListener(this);
}
#Override
public void onClick(View v) {
Toast.makeText(context, "" + getAdapterPosition() + questionTitle.getText().toString(), Toast.LENGTH_LONG).show();
Log.d("TAG", "" + getAdapterPosition());
Intent intent = new Intent(context, ProgramViewer.class);
intent.putExtra("titlePos",getAdapterPosition());
intent.putExtra("title",questionTitle.getText().toString());
context.startActivity(intent);
}
}
public class MyExpandedViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener
{
private Context context;
ListView listView;
public MyExpandedViewHolder(View itemView, Context context,ArrayList<String> mobileArray) {
super(itemView);
this.context = context;
ArrayAdapter adapter = new ArrayAdapter<String>(context, R.layout.expanded_list_inside_recycler_view, mobileArray);
listView= (ListView) itemView.findViewById(R.id.list_view);
listView.setAdapter(adapter);
}
public ListView getListView()
{
return this.listView;
}
#Override
public void onClick(View v) {
Toast.makeText(context,getAdapterPosition()+"",Toast.LENGTH_LONG).show();
}
}
}
What I tried to do is to expand the RecyclerView item on click but first I have to implement recycler view and list view together. I am getting NullPointerException. Please tell me the problem in my code. The answer would be greatly appreciated.
Log file:
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ListView.setAdapter(android.widget.ListAdapter)' on a null object reference
at kole.technicalbird.CustomAdapterRecyclerView$MyExpandedViewHolder.<init>(CustomAdapterRecyclerView.java:113)
at kole.technicalbird.CustomAdapterRecyclerView.onCreateViewHolder(CustomAdapterRecyclerView.java:43)
at android.support.v7.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:5476)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4701)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(
Layout File: single_item_in_list.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/textView"
android:text="a"/>
</LinearLayout>
**recycler_view_list**
<?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:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<android.support.v7.widget.CardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:elevation="8dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/question"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:fontFamily="sans-serif"
android:text="ques"
android:padding="8dp"
android:layout_marginRight="32dp"
android:textSize="16dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginRight="8dp"
android:fontFamily="sans-serif"
android:layout_centerVertical="true"
android:padding="8dp"
android:text=">" />
</RelativeLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
<ImageView
android:src="#android:drawable/divider_horizontal_dark"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="fitXY"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:paddingBottom="0.2dp"
android:paddingTop="0.2dp" />
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/list_view">
</ListView>
</LinearLayout>
expanded_list_inside_recycler_view
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/list_view">
</ListView>
</LinearLayout>
Where is your listview in your single_item_in_list.xml.
Your single_item_in_list.xml don't have listview,so when you use getListView() ,the listview is null.I guess this is the reason!

Categories

Resources