Why doesn't my Viewholder work? - nullpointerexception

So I'm creating a List for which I'm using my own implementation of the array adapter. I'm also using a viewholder for performance. But for some reason I get a nullpointer exception at this line:
holder.icon.setImageResource(R.drawable.no);
So I guess my holder isn't initialized? But I don't see how else my code should be?
public class NameViewAdapter extends ArrayAdapter<String>{
private String[] names;
private static class ViewHolder{
ImageView icon=null;
}
public NameViewAdapter(Context context, int textViewResourceId,String[] names) {
super(context, textViewResourceId, names);
this.names = names;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView==null)
{
LayoutInflater li =
(LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = li.inflate(R.layout.row,parent,false);
holder=new ViewHolder();
holder.icon=(ImageView) convertView.findViewById(R.id.icon);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
if (names[position].length() > 4)
holder.icon.setImageResource(R.drawable.ok);
else
holder.icon.setImageResource(R.drawable.no);
return convertView;
}
}
This is my XML-file:
<?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">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/imageView"
android:src="#drawable/ic_launcher"/>
<TextView
android:id="#+id/label"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>

K so it seemed that the next line:
holder.icon=(ImageView) convertView.findViewById(R.id.icon);
should be changed to
holder.icon=(ImageView) convertView.findViewById(R.id.imageView);
cause that's the id the ImageView has in the xml file

Related

i am generating pdf from recyclerView , but empty pdf is generated.Android Studio

i am generating pdf from recycler view, but getting empty pdf, probably recycler view is not getting converted to bitmap.
please help.
i have atttached the files here
the recycler view is properly shown but when pdf is generated , blank pdf is generated.
MainActivity.java
package com.example.recyclerview;
public class MainActivity extends AppCompatActivity {
// ArrayList for person names
ArrayList langNames = new ArrayList<>(Arrays.asList("Person 1", "Person 2", "Person 3", "Person 4", "Person 5", "Person 6", "Person 7","Person 8", "Person 9", "Person 10", "Person 11", "Person 12", "Person 13", "Person 14"));
ArrayList langText= new ArrayList<>(Arrays.asList("Person 1", "Person 2", "Person 3", "Person 4", "Person 5", "Person 6", "Person 7","Person 8", "Person 9", "Person 10", "Person 11", "Person 12", "Person 13", "Person 14"));
private Button btn;
private LinearLayout linear;
private Bitmap bitmap;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// get the reference of RecyclerView
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
// set a LinearLayoutManager with default horizontal orientation and false value for reverseLayout to show the items from start to end
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getApplicationContext(),LinearLayoutManager.VERTICAL,false);
recyclerView.setLayoutManager(linearLayoutManager);
// call the constructor of CustomAdapter to send the reference and data to Adapter
PDFadapter adapter = new PDFadapter(MainActivity.this, langNames,langText);
recyclerView.setAdapter(adapter); // set the Adapter to RecyclerView
linear=findViewById(R.id.linear);
btn=findViewById(R.id.btn1);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.d("size"," "+linear.getWidth()+" "+linear.getHeight());
bitmap=loadBitmap(adapter,linear.getWidth(),linear.getHeight());
try {
createPdf();
} catch (IOException e) {
e.printStackTrace();
}
}
});
// pdfConverter.createPdf((Context)MainActivity.this, (Activity)MainActivity.this);
}
private Bitmap loadBitmap(LinearLayout linear, int width, int height) {
Bitmap bitmap=Bitmap.createBitmap(width,height,Bitmap.Config.ARGB_8888);
Canvas canvas =new Canvas(bitmap);
linear.draw(canvas);
return bitmap;
}
private void createPdf() throws IOException {
WindowManager windowManager=(WindowManager)getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics dispalyMetrics=new DisplayMetrics();
this.getWindowManager().getDefaultDisplay().getMetrics(dispalyMetrics);
float width=dispalyMetrics.widthPixels;
float height=dispalyMetrics.heightPixels;
int convertwidth=(int)width;
int converthieght=(int)height;
PdfDocument document = new PdfDocument();
PdfDocument.PageInfo pageInfo=new PdfDocument.PageInfo.Builder(convertwidth,converthieght,1).create();
PdfDocument.Page page= document.startPage(pageInfo);
Canvas canvas= page.getCanvas();
Paint paint=new Paint();
canvas.drawPaint(paint);
bitmap=Bitmap.createScaledBitmap(bitmap,convertwidth,converthieght,true);
canvas.drawBitmap(bitmap,0,0,null);
document.finishPage(page);
File file=new File(getApplicationContext().getFilesDir(),"/abcd.pdf");
document.writeTo(new FileOutputStream(file));
document.close();
}
}
PDFadapter.java
public class PDFadapter extends RecyclerView.Adapter<PDFadapter.MyViewHolder> {
ArrayList langNames;
ArrayList langText;
Context context;
public PDFadapter(Context context, ArrayList langNames, ArrayList langText) {
this.context = context;
this.langNames = langNames;
this.langText= langText;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// infalte the item Layout
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout, parent, false);
// set the view's size, margins, paddings and layout parameters
MyViewHolder vh = new MyViewHolder(v); // pass the view to View Holder
return vh;
}
#Override
public void onBindViewHolder(MyViewHolder holder, final int position) {
// set the data in items
holder.name.setText((String) langNames.get(position));
holder.text.setText((String) langText.get(position));
// implement setOnClickListener event on item view.
}
#Override
public int getItemCount() {
return langNames.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
// init the item view's
TextView name;
TextView text;
public MyViewHolder(View itemView) {
super(itemView);
// get the reference of item view's
name = (TextView) itemView.findViewById(R.id.name);
text = (TextView) itemView.findViewById(R.id.texts);
}
}
}
layout.xml
<?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:id="#+id/linearlayout"
android:orientation="vertical">
<!--
items for a single row of RecyclerView
-->
<TextView
android:id="#+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:textColor="#color/black"
android:textSize="25sp" />
<TextView
android:id="#+id/texts"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:textColor="#color/black"
android:textSize="18sp" />
</LinearLayout>
activity_main.xml
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/btn1"
/>
<LinearLayout
android:layout_width="match_parent"
android:id="#+id/linear"
android:orientation="vertical"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/recyclerView"
tools:context=".MainActivity"
/>
</LinearLayout>
</LinearLayout>
blank pdf generated

RecyclerView view doesn't change using background_selector

I'm Trying to toggle item background color upon item selection.
I can see it's logic is working yet the background wouldn't change.
The log prints show the selctions indeed work, yet the background not.
From background_selector:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#android:color/holo_green_light" android:state_pressed="false" android:state_selected="true" />
<item android:drawable="#android:color/holo_purple" android:state_selected="false" />
</selector>
from task_row.xml:
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
app:cardCornerRadius="3dp"
app:cardElevation="3dp"
android:id="#+id/tasksCardView"
android:background="#drawable/background_selector"
app:cardUseCompatPadding="true">
From Adapter code:
class MyTasksAdapter (
val arrayList: ArrayList<Task>,
val selectedItemsList: ArrayList<Task>,
val deletedItemsList: ArrayList<String>) :
RecyclerView.Adapter<MyTasksAdapter.ViewHolder>() {
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
private var cardView: CardView = itemView.tasksCardView
private val selectedItems = SparseBooleanArray()
override fun onClick(view: View) {
if (selectedItems[adapterPosition, false]) {
selectedItems.delete(adapterPosition)
cardView.isSelected = false
Log.d("Item selected AA", "position: $position")
}
else {
selectedItems.put(adapterPosition, true)
view.isSelected = true
Log.d("Item selected BB", "position: $position")
}
}
init {
itemView.setOnClickListener(this)
}
Tried also changing cardview to view, but it didn't help either.
class MyTasksAdapter (
val arrayList: ArrayList<Task>,
val selectedItemsList: ArrayList<Task>,
val deletedItemsList: ArrayList<String>) :
RecyclerView.Adapter<MyTasksAdapter.ViewHolder>() {
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
//private lateinit var item: ClipData.Item
private var cardView: CardView = itemView.tasksCardView
private val selectedItems = SparseBooleanArray()
override fun onClick(view: View) {
if (selectedItems[adapterPosition, false]) {
selectedItems.delete(adapterPosition)
view.isSelected = false
Log.d("Item selected AA", "position: $position")
}
else {
selectedItems.put(adapterPosition, true)
view.isSelected = true
Log.d("Item selected BB", "position: $position")
}
}
init {
itemView.setOnClickListener(this)
}
Appreciate your kind help.
Working now.
Moved it to the relative_layout header: instead of cardview_layout header
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
app:cardCornerRadius="3dp"
app:cardElevation="3dp"
android:id="#+id/tasksCardView"
android:hapticFeedbackEnabled="true"
app:cardUseCompatPadding="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
**android:background="#drawable/background_selector"**
android:padding="16dp">

Android: Attempt to invoke virtual method on a null object reference in onBindViewHolder

My app is supposed to parse JSON data and display it in a recycler view. When I run the app, it crashes with the following error:
I've re-checked my code multiple times to make sure I am calling the correct resource files, but I still cant find the source of the issue. The logcat tells me the issue is in the onBindViewHolder method in the recycler view adapter class, but everything looks normal to me. Can anyone point me in the right direction? Here is the relevant code:
Recycler View Adapter:
public class IndRvAdapter extends RecyclerView.Adapter<IndRvAdapter.MyViewHolder> {
private Context context;
private List<Ind> indList;
public IndRvAdapter(Context context, List<Ind> indList) {
this.context = context;
this.indList = indList;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view;
LayoutInflater inflater = LayoutInflater.from(context);
view = inflater.inflate(R.layout.ind_card, viewGroup, false);
final MyViewHolder viewHolder = new MyViewHolder(view);
viewHolder.indView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i = new Intent(context, SingleInd.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.putExtra("pacshort", indList.get(viewHolder.getAdapterPosition()).getPacshort());
i.putExtra("supopp", indList.get(viewHolder.getAdapterPosition()).getSuppopp());
i.putExtra("candname", indList.get(viewHolder.getAdapterPosition()).getCandname());
i.putExtra("district", indList.get(viewHolder.getAdapterPosition()).getDistrict());
i.putExtra("amount", indList.get(viewHolder.getAdapterPosition()).getAmount());
i.putExtra("party", indList.get(viewHolder.getAdapterPosition()).getExpParty());
i.putExtra("payee", indList.get(viewHolder.getAdapterPosition()).getPayee());
i.putExtra("date", indList.get(viewHolder.getAdapterPosition()).getDate());
i.putExtra("origin", indList.get(viewHolder.getAdapterPosition()).getOrigin());
i.putExtra("source", indList.get(viewHolder.getAdapterPosition()).getSource());
context.startActivity(i);
}
});
return viewHolder;
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder myViewHolder, int i) {
myViewHolder.pacshorts.setText(indList.get(i).getPacshort());
myViewHolder.supOpp.setText(indList.get(i).getSuppopp());
myViewHolder.candName.setText(indList.get(i).getCandname());
myViewHolder.district.setText(indList.get(i).getDistrict());
}
#Override
public int getItemCount() {
return indList.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder{
TextView pacshorts, supOpp, candName, district;
LinearLayout indView;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
pacshorts = itemView.findViewById(R.id.tv_pacshort);
supOpp = itemView.findViewById(R.id.tv_suppopp);
candName = itemView.findViewById(R.id.tv_candname);
district = itemView.findViewById(R.id.tv_district);
indView = itemView.findViewById(R.id.ind_view);
}
}
}
Card View resource:
<?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"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:id="#+id/ind_view">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="250dp"
android:layout_gravity="center"
android:layout_margin="5dp"
android:elevation="3dp"
card_view:cardCornerRadius="15dp"
card_view:cardElevation="4dp"
card_view:cardUseCompatPadding="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorPrimaryDark">
<TextView
android:id="#+id/pacshort"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="TextView" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/pacshort"
android:id="#+id/tv_suppop"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/tv_candname"
android:layout_below="#+id/tv_suppop"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/tv_district"
android:layout_below="#+id/tv_candname"/>
</RelativeLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
Recycler View:
<?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:background="#color/background_color"
tools:context=".IndExpend">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/ind_rv">
</android.support.v7.widget.RecyclerView>
</RelativeLayout>
Main Activity that parses the JSON data
public class IndExpend extends AppCompatActivity {
/*
* Open secrets API: Returns the 50 latest independent expenditures transactions
* Updated every 4 days
*/
private static final String url = "http://www.opensecrets.org/api/?method=independentExpend&output=json&apikey=d1ff8f708ca0745d75e9ffa0ee6f3d09";
private LinearLayoutManager linearLayoutManager;
private List <Ind> indList;
private RecyclerView myrv;
private RecyclerView.Adapter adapter;
public IndExpend(){}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ind_expend);
linearLayoutManager = new LinearLayoutManager(this);
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
myrv = findViewById(R.id.ind_rv);
indList = new ArrayList<>();
adapter = new IndRvAdapter(this, indList);
myrv.setHasFixedSize(true);
myrv.setLayoutManager(linearLayoutManager);
myrv.setAdapter(adapter);
getData();
}
private void getData() {
final ProgressDialog progressDialog = new ProgressDialog(this);
progressDialog.setMessage("Loading...");
progressDialog.show();
StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
progressDialog.dismiss();
try {
JSONObject object = new JSONObject (response);
JSONObject responseObj = object.getJSONObject("response");
JSONArray array = responseObj.getJSONArray("indexp");
for (int i = 0; i < array.length(); i++){
JSONObject attributesObj = array.getJSONObject(i).getJSONObject("#attributes");
Ind ind = new Ind(attributesObj.getString("pacshort"),
attributesObj.getString("suppopp"),
attributesObj.getString("candname"),
attributesObj.getString("district"),
attributesObj.getString("amount"),
attributesObj.getString("party"),
attributesObj.getString("payee"),
attributesObj.getString("date"),
attributesObj.getString("origin"),
attributesObj.getString("source"));
indList.add(ind);
}
adapter = new IndRvAdapter(getApplicationContext(), indList);
myrv.setAdapter(adapter);
}catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("Volley", error.toString());
progressDialog.dismiss();
}
});
RequestQueue requestQueue = Volley.newRequestQueue(this );
requestQueue.add(stringRequest);
}
}
Can anyone help me find the source of the problem?
I think it is because you are trying to bind the view with this id:
pacshorts = itemView.findViewById(R.id.tv_pacshort);
But on the layout file the id for that element its just pacshort:
<TextView
android:id="#+id/pacshort"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="TextView" />
Generally on these type of null pointer exceptions when working on Android happens for one of two reasons. First, the res file that's being inflated is not the right one or, second, the id used to bind the views is misspelled or doesn't exist in that view.

How to apply an onClick Listener to an imageView within a CardView

I'm trying to setup an onClick Listener where that listener already has a button. The purpose is to provide a second way to access an intent (in this case a "ReadActivity" class. An example of this is
Here is my code:
#Override
public void onBindViewHolder(MyViewHolder holder, final int position) {
holder.tv_book_title.setText(mData.get(position).getBookTitle());
holder.tv_book_author.setText("by " + mData.get(position).getBookAuthor());
holder.img_book_thumbnail.setImageResource(mData.get(position).getBookId());
holder.actionButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(mContext, ReadActivity.class);
// passing data to the book activity
intent.putExtra("Id", mData.get(position).getPhotoId());
intent.putExtra("Title", mData.get(position).getBookTitle());
intent.putExtra("Author", mData.get(position).getBookAuthor());
intent.putExtra("Description", mData.get(position).getContentUrl());
intent.putExtra("Thumbnail", mData.get(position).getBookId());
// start the activity
mContext.startActivity(intent);
}
});
And this is my cardview_item xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView 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/card_view"
android:layout_width="match_parent"
android:layout_height="#dimen/card_height"
android:layout_gravity="center"
android:layout_marginBottom="#dimen/md_keylines"
android:layout_marginLeft="#dimen/md_keylines"
android:layout_marginRight="#dimen/md_keylines"
android:foreground="?attr/selectableItemBackground">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/book_img_id"
**android:onClick="imageClick"**
android:layout_width="match_parent"
android:layout_height="#dimen/card_image_height"
android:scaleType="centerCrop"
android:contentDescription="#string/todo" />
<TextView
android:id="#+id/book_title_id"
android:layout_width="match_parent"
android:layout_height="#dimen/card_title_height"
android:layout_alignBottom="#+id/book_img_id"
android:layout_marginStart="#dimen/md_keylines"
android:textAppearance="#style/TextAppearance.AppCompat.Title"
android:textColor="#color/white" />
<TextView
android:id="#+id/book_author_id"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/book_img_id"
android:layout_marginLeft="#dimen/md_keylines"
android:layout_marginTop="#dimen/md_keylines"
android:layout_marginBottom="#dimen/md_keylines"
android:layout_marginRight="#dimen/md_keylines"
android:ellipsize="end"
android:singleLine="true"
android:textColor="#color/dark_grey"
android:textSize="#dimen/article_subheading" />
<Button
android:id="#+id/action_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/book_author_id"
style="?android:attr/borderlessButtonStyle"
android:textColor="?attr/colorPrimary"
android:text="#string/read" />
</RelativeLayout>
</android.support.v7.widget.CardView>
In the xml, I tried to set a onClick line, but I'm not sure how to setup the onClick listener. Is there a way to do this without affecting the originial code? Or would it be easier to copy to actionButton.setOnClickListener and just change the holder setting to the thumbnail?
You should not use `android:onClick" attribute for handling click. You better handle it in code so that your Layout and logic not tightly coupled.
You need to use setOnClickListener like at the actionButton. Or you can slightly change your code to handle the click inside your ViewHolder. Change your code like this:
// use View.OnClickListener so that the click listener won't
// be recreated when the View is recycled
public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public Button actionButton;
public ImageView img_book_thumbnail;
public ViewHolder(Context context, View itemView) {
super(itemView);
// find actionButton and img_book_thumbnail
...
// Attach a click listener to both of them
actionButton.setOnClickListener(this);
img_book_thumbnail.setOnClickListener(this);
}
// Handles clicked
#Override
public void onClick(View view) {
if(view.getId == R.id.action_button) {
// do something
} else if(view.getId == R.id.book_img_id) {
// do something
}
}
}
Instead of directly handling the click in Adapter, you should delegate the click handling to the parent activity / fragment of the Adapter by using a Listener/Callback mechanism.

QuickReturn with RecyclerView

I am trying to have a CheckBox (which is above the RecyclerView) as QuickReturn. The simple idea would be to hide the checkbox, when scroling up and make it visible, when scrolling down. (as in https://github.com/dbleicher/recyclerview-grid-quickreturn.)
And, it kind of works, but I have a strange flickering when scrolling.
Any thoughts on that?
MainActivity.java:
public class MainActivity extends ActionBarActivity {
private CheckBox mCheckbox;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mCheckbox = (CheckBox) findViewById(R.id.checkbox);
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recview);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
// Simple check if moved vertically.
// React to scrolls of a minimum amount (3, in this case)
if (dy > 3) {
if (mCheckbox.getVisibility() == View.VISIBLE) {
mCheckbox.setVisibility(View.GONE);
}
} else if (dy < -3) {
if (mCheckbox.getVisibility() == View.GONE) {
mCheckbox.setVisibility(View.VISIBLE);
}
}
}
});
List<String> dataset = Arrays.asList("one", "two", "three", "four", "five");
CustomAdapter adapter = new CustomAdapter(dataset);
recyclerView.setAdapter(adapter);
}
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> {
private List<String> mDataset;
public CustomAdapter(List<String> dataset) {
mDataset = dataset;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup arg0, int arg1) {
View v = LayoutInflater.from(arg0.getContext())
.inflate(R.layout.address_card, arg0, false);
return new ViewHolder(v);
}
public void onBindViewHolder(ViewHolder viewHolder, int position) {
viewHolder.mText.setText(mDataset.get(position));
}
#Override
public int getItemCount() {
return mDataset.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
private TextView mText;
public ViewHolder(View v) {
super(v);
mText = (TextView) v.findViewById(R.id.cardText);
}
}
}
}
activity_main.xml:
<LinearLayout 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:orientation="vertical"
tools:context="${relativePackage}.${activityClass}" >
<CheckBox
android:id="#+id/checkbox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Check me" />
<android.support.v7.widget.RecyclerView
android:id="#+id/recview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical" />
</LinearLayout>
adress_card.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/card_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:elevation="#dimen/cardview_default_elevation"
card_view:cardCornerRadius="#dimen/cardview_default_radius" >
<TextView
android:id="#+id/cardText"
android:layout_width="wrap_content"
android:layout_height="100dp"
android:text="TextView" />
</android.support.v7.widget.CardView>
In your activity_main.xml, you have both the checkbox and RV in a LinearLayout. Whenever you set the checkbox to View.GONE, not only does it remove that view, but it has to recalculate the layout of the RV (and grow it to full_size). That's a lot of work on the main thread. Instead of a LinearLayout, add both items to a FrameLayout (RV first, then the Checkbox). This will make the checkbox float on-top of the RV, but the RV size will no longer change when you hide the checkbox. I suspect this will eliminate the flickering.
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="${relativePackage}.${activityClass}" >
<android.support.v7.widget.RecyclerView
android:id="#+id/recview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical" />
<CheckBox
android:id="#+id/checkbox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Check me" />
</FrameLayout>
Using Gravity settings, you can position the checkbox to where you want it to appear (in front of the RV). If you want it at the top, and you don't want it to obscure the top-most items in the RV (when it's scrolled to the top), the look at the ItemDecorator class (QRBarDecoration) in the same project you reference above.
Hope that helps.