Image in row of recyclerview disappears after rotation - android

In my recyclerview I set an image (in recyclerview row) visible or not visible according some condition.
However after I rotate the screen the image disappears, how do I keep the image visible on it`s position in the recyclerview after rotating the screen?
Thank you for your help and happy holidays ;)
I am using an implementation of the SimpleAdapter.
public class SimpleAdapter extends RecyclerView.Adapter<SimpleAdapter.SimpleViewHolder> implements FollowRedirectsCallback {
public static class SimpleViewHolder extends RecyclerView.ViewHolder {
...
public final View icCancel;
public SimpleViewHolder(View view) {
super(view);
...
icCancel = view.findViewById(R.id.icCancel);
}
}
public SimpleAdapter(Context context, String[] data, long userId, int dlTypeValue) {
mContext = context;
userID = userId;
DLTypeValue = dlTypeValue;
if (data != null)
mData = new ArrayList<String>(Arrays.asList(data));
else mData = new ArrayList<String>();
}
public SimpleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final View view = LayoutInflater.from(mContext).inflate(R.layout.simple_item, parent, false);
return new SimpleViewHolder(view);
}
#Override
public void onBindViewHolder(final SimpleViewHolder holder, final int position) {
...
// How to keep this image visible after rotation of the screen?
if (somecondition) {
holder.icCancel.setVisibility(View.VISIBLE);
}
}
EDIT: I initialze my adapter in the the corresponsent activity:
public class DownloadsActivity extends BaseActivity {
RecyclerView recyclerView;
Parcelable state;
SimpleAdapter mAdapter;
SimpleSectionedRecyclerViewAdapter mSectionedAdapter;
SimpleSectionedRecyclerViewAdapter.Section[] dummy;
#AfterViews
public void init() {
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
//setLayout Manager
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.setHasFixedSize(true);
dummy = new SimpleSectionedRecyclerViewAdapter.Section[sections.size()];
mSectionedAdapter = new
SimpleSectionedRecyclerViewAdapter(this, R.layout.section, R.id.section_text, mAdapter);
mSectionedAdapter.setSections(sections.toArray(dummy));
//Apply this adapter to the RecyclerView
recyclerView.setAdapter(mSectionedAdapter);
}
#Override
protected void onPause() {
super.onPause();
// save RecyclerView state
state = recyclerView.getLayoutManager().onSaveInstanceState();
}
#Override
protected void onResume() {
super.onResume();
if (inProgress) {
progresstxt.setVisibility(View.VISIBLE);
downloadprogress.setVisibility(View.VISIBLE);
}
// restore RecyclerView state
recyclerView.getLayoutManager().onRestoreInstanceState(state);
}
}

You might be able to save the visibility state of the images in an ArrayList, then pass it as a parameter to the adapter. In your Activity, save that ArrayList using onSaveInstanceState.
public class YourActivity extends BaseActivity {
/* some codes */
// possible values are: VISIBLE, INVISIBLE, or GONE
private ArrayList<Integer> imagesState = new ArrayList<>();
/* some codes */
#Override
protected void onCreate(Bundle savedInstanceState) {
if(savedInstanceState != null) {
imagesState = savedInstanceState.getIntegerArrayList("key");
}
// Pass the imagesState to the adapter as a parameter here
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putIntegerArrayList("key", imagesState);
}
/* some codes */
}
Then in your Adapter:
public class SimpleAdapter extends RecyclerView.Adapter<SimpleAdapter.SimpleViewHolder> implements FollowRedirectsCallback {
/* some codes */
public SimpleAdapter(Context context, String[] data, long userId, int dlTypeValue, ArrayList<Integer> imagesState) {
/* some codes */
this.imagesState = imagesState;
}
#Override
public void onBindViewHolder(SimpleViewHolder holder, int position) {
/* some codes */
if (imagesState.get(position) == View.VISIBLE)
holder.icCancel.setVisibility(View.VISIBLE);
else if(imagesState.get(position) == View.INVISIBLE)
holder.icCancel.setVisibility(View.INVISIBLE);
else
holder.icCancel.setVisibility(View.GONE);
}
}

use
int position = recyclerView.getLayoutManager().findFirstVisibleItemPosition();
to get the first position visible. then just scroll to the position
recyclerView.getLayoutManager().scrollToPosition( <position of interest> );

Related

Reference recyclerView elements from fragment

Good afternoon!
I have a fragment containing a recyclerView which holds bookmarked elements. The element layout has a star icon to delete the chosen item from SQLite database. When the icon is clicked, i need to set its tint to white then the position of that item needs to be saved in a list declared in my fragment. I am wondering how to do that.
Since we use adapters to bind elements I couldn't reference the icon from fragment to change the tint. Note that, It shouldn't refresh the page. After user presses back, It will save changes in db
Fragment
public class BookMarksFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener, View.OnClickListener {
private BookMarksAdapter listAdapter;
private List<BookmarksModel> bookmarks = new ArrayList<>();
private FragmentBookmarksBinding binding;
private DBHelper dbHelper;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Functions.setLanguages(App.getCurrentActivity());
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_bookmarks, container, false);
binding.refresher.setColorSchemeResources(R.color.drawer_background);
binding.refresher.setOnRefreshListener(this);
binding.refresher
.post(new Runnable() {
#Override
public void run() {
binding.refresher.setRefreshing(true);
setRefreshingState(true);
}
}
);
listAdapter = new BookMarksAdapter(getActivity(), bookmarks, this);
binding.bookmarkList.setLayoutManager(new LinearLayoutManager(getActivity()));
binding.bookmarkList.setAdapter(listAdapter);
listAdapter.notifyDataSetChanged();
return binding.getRoot();
}
private void setRefreshingState(final boolean b) {
binding.refresher.post(new Runnable() {
#Override
public void run() {
binding.refresher.setRefreshing(b);
getNews();
}
});
}
private void getNews() {
dbHelper = new DBHelper(getActivity(), "kunuz", null, 1);
bookmarks.clear();
bookmarks.addAll(dbHelper.getBookmarks());
if(bookmarks.size()==0){
binding.bookmarkList.setVisibility(View.GONE);
binding.emptyView.setVisibility(View.VISIBLE);
}else{
binding.emptyView.setVisibility(View.GONE);
binding.bookmarkList.setVisibility(View.VISIBLE);
}
binding.refresher.setRefreshing(false);
listAdapter.notifyDataSetChanged();
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case Constants.BOOKMARK_REQUEST_CODE:
if (resultCode == Constants.BOOKMARK_RESULT_CODE) {
binding.refresher
.post(new Runnable() {
#Override
public void run() {
binding.refresher.setRefreshing(true);
setRefreshingState(true);
}
}
);
}
break;
}
}
#Override
public void onRefresh() {
getNews();
}
#Override
public void onClick(View v) {
if (v.getId()==R.id.star){
dbHelper.deleteFavorites(v.getTag().toString());
onRefresh();
}else if(v.getId()==R.id.bookmark_card_view){
Intent intent = new Intent(App.getInstance(), NewsViewActivity.class);
intent.putExtra(Constants.NEWS_CODE, v.getTag().toString());
getActivity().startActivity(intent);
}
}
}
Adapter
public class BookMarksAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context context;
private List<BookmarksModel> data;
private LayoutInflater inflater;
private View.OnClickListener listener;
public BookMarksAdapter(Context context, List<BookmarksModel> data, View.OnClickListener listener) {
this.context = context;
this.data = data;
this.listener = listener;
this.inflater = LayoutInflater.from(context);
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
BookmarksItemBinding binding
= DataBindingUtil.inflate(inflater, R.layout.bookmarks_item, parent, false);
return new BookmarksHolder(binding.getRoot());
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
final BookmarksModel item = data.get(position);
((BookmarksHolder)holder).binding.setNewsItem(item);
((BookmarksHolder)holder).binding.categoryIcon.setImageResource(Utils.getCategoryColorByName(item.getCategory()));
if (item.getImage_url() != null && !item.getImage_url().isEmpty()) { // TODO get image from cache
ImageLoader.getInstance()
.displayImage(item.getImage_url(), ((BookmarksHolder)holder).binding.newsImageView);
} else {
((BookmarksHolder)holder).binding.
newsImageView.setImageResource(R.drawable.kun_uz_logo_no_image);
}
((BookmarksHolder)holder).binding.star.setTag(item.getCode());
((BookmarksHolder)holder).binding.star.setOnClickListener(listener);
((BookmarksHolder)holder).binding.bookmarkCardView.setTag(item.getCode());
((BookmarksHolder)holder).binding.bookmarkCardView.setOnClickListener(listener);
}
#Override
public int getItemCount() {
return data.size();
}
public class BookmarksHolder extends RecyclerView.ViewHolder {
BookmarksItemBinding binding;
BookmarksHolder(View root) {
super(root);
binding = DataBindingUtil.bind(root);
}
}
}
OnClick listener on star icon sends clicked adapterPosition back to Fragment.
Fragment stores the change in database, updates list in the adapter.
Fragment calls adapters notifyItemChanged(position).
Adapters onBindViewHolder re-reads item on this position and sets star color appropriately.
You need to have some flag in BookmarksModel class to know whether the bookmarks is active(in db)/inactive(not in db) as in your case.
public BookmarksModel{
....
....
public isSaved;
}
Now in you onBindViewHolder method.
final BookmarksModel item = data.get(position);
((BookmarksHolder)holder).binding.setNewsItem(item);
.....
.....
if(item.isSaved){
((BookmarksHolder)holder).star.setAlpha(1f); //set your tint value
}else{
((BookmarksHolder)holder).star.setAlpha(0.5ff); //set your tint value
}
((BookmarksHolder)holder).binding.star.setTag(position); // just set the position
((BookmarksHolder)holder).binding.star.setOnClickListener(listener);
((BookmarksHolder)holder).binding.bookmarkCardView.setTag(position);
((BookmarksHolder)holder).binding.bookmarkCardView.setOnClickListener(listener);
In your fragment onClick()
public void onClick(View v) {
if (v.getId()==R.id.star){
int pos = (Integer)v.getTag();
BookmarksModel model = listAdapter.getList(pos); //create a getter in your
if(!model.isSaved) //toggled to saved bookmark
///////////////// your code to save bookmark
else
dbHelper.deleteFavorites(v.getTag().toString()); ///// your code for deleting bookmark
model.isSaved = !model.isSaved;
listAdapter.notifyItemChanged(pos); // refreshes your recyclerView item
}
}
Hope this helps.

Getting Android RecyclerView to update view inside React Native component

I am making a mobile application using React Native and included list components didn't have high enough performance for it so I started using Android's RecyclerView as the list component. There is a problem though with it. The RecyclerView doesn't update its contents views until I scroll or change RecyclerView's size. What could cause this problem and how I can fix it? I have tried notifyDatasetChanged, notifyItemChanged, forceLayout, invalidate, postInvalidate and many different variations with each.
Try this one this.setIsRecyclable(true);
It will referesh your views
public class MainActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private ArrayList<String> mSingleItemLists = new ArrayList<>();
private SingleListItemAdapter mSingleListItemAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view_single_item);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(linearLayoutManager);
setDummyData();
}
private void setDummyData() {
for (int i = 0; i <= 30; i++)
mSingleItemLists.add("item" + i);
}
#Override
protected void onResume() {
super.onResume();
mSingleListItemAdapter = new SingleListItemAdapter(mSingleItemLists);
mRecyclerView.setAdapter(mSingleListItemAdapter);
}
class SingleListItemAdapter extends RecyclerView.Adapter<SingleListItemAdapter.SingleListItemHolder> {
private ArrayList<String> mSingleItemLists;
private SingleListItemAdapter(ArrayList<String> singleItemLists) {
mSingleItemLists = singleItemLists;
//You can do notifydatasetchange if u r having any saved value
}
#Override
public SingleListItemAdapter.SingleListItemHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View inflatedView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.row_recyclerview, parent, false);
return new SingleListItemHolder(inflatedView);
}
#Override
public void onBindViewHolder(SingleListItemAdapter.SingleListItemHolder holder, int position) {
holder.mItemDate.setText(mSingleItemLists.get(position));
}
#Override
public int getItemCount() {
return mSingleItemLists.size();
}
class SingleListItemHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private TextView mItemDate;
SingleListItemHolder(View v) {
super(v);
mItemDate = (TextView) v.findViewById(R.id.textview_recycler_list_item);
v.setOnClickListener(this);
this.setIsRecyclable(true); // This will help u
}
#Override
public void onClick(View v) {
//do your stuff
notifyDataSetChanged();
}
}
}
}

RecyclerView: wrong position in filtered List

I have a RecyclerView list of CardView items. I then use a simple filter method with a SearchView widget to filter the list. When I then click on a filtered CardView to launch a CardViewDetails Activity, the UI is showing the CardView from the original List and not the filtered List. For example, I have a list of twenty items in the original List. When I enter a search constraint the filtered List correctly shows three CardViews in the RecyclerView. When I click on the third CardView in the List, the UI returns the third CardView from the original List and not the third CardView from the filtered List. What am I missing here?
Adapter:
public class MyRecylerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<ListItem> mListItems, filteredList;
Context mContext;
private RecyclerItemClickListener recyclerItemClickListener;
private RecyclerView mRecyclerView;
/**********************************************************/
private String searchString = "";
/**********************************************************/
public MyRecylerAdapter(Context context, List<ListItem> listItems) {
this.mContext = context;
this.mListItems = listItems;
this.filteredList = new ArrayList<>();
this.filteredList.addAll(this.mListItems);
}
// RecyclerItemClickListener is the public interface file used to reach the MainActivity
public void setOnItemClickListener(RecyclerItemClickListener recyclerItemClickListener) {
this.recyclerItemClickListener = recyclerItemClickListener;
}
// Get the Item's position.
public ListItem getItem(int position) {
return filteredList.get(position);
}
#Override
public int getItemCount() {
if (filteredList.size() >0) {
return filteredList.size();
}
else {
return mListItems.size();
}
}
public void setFilter(List<ListItem> listItems, String searchString) {
// Note: the String is to get s.toString() from the Main Activity SearchView.
filteredList = new ArrayList<>();
filteredList.addAll(listItems);
this.searchString = searchString;
notifyDataSetChanged();
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_contact_item, parent, false);
final ItemHolder itemHolder = new ItemHolder(view);
// Attach a Click listener to the items's (row) view.
// itemView is from the ItemHolder() below.
// onItemClick is the click method in MainActivity.
itemHolder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int adapterPos = itemHolder.getAdapterPosition(); // get the item position.
if (adapterPos != RecyclerView.NO_POSITION) {
if (recyclerItemClickListener != null) {
// pass the item to the Main Activity
// through the RecyclerItemClickListener file and its
// public interface.
recyclerItemClickListener.onItemClick(itemHolder.itemView,adapterPos);
}
}
}
});
return itemHolder;
}
private static class ItemHolder extends RecyclerView.ViewHolder {
private TextView cardBlankText2;
private ItemHolder(View itemView) {
super(itemView);
cardBlankText2 = (TextView) itemView.findViewById(R.id.cardBlankText2);
}
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
final ListItem listItem = filteredList.get(position);
final ItemHolder itemHolder = (ItemHolder) holder;
itemHolder.cardBlankText2.setText(listItem.getTodo());
}
Activity:
public class MainActivity extends AppCompatActivity implements
RecyclerItemClickListener {
private List<ListItem> allList = new ArrayList<>();
private RecyclerView mRecyclerView;
private SQLiteDB sqLiteDB;
private MyRecylerAdapter adapter;
private CardView cardview;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sqLiteDB = SQLiteDB.getInstance(this);
mRecyclerView = (RecyclerView)findViewById(R.id.list_recyclerview);
final LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
mRecyclerView.setLayoutManager(layoutManager);
allList = sqLiteDB.getAllDBItems();
adapter = new MyRecylerAdapter(this, allList);
adapter.setOnItemClickListener(this);
mRecyclerView.setAdapter(adapter);
}
#Override
public void onItemClick(View view, int position) {
cardview = (CardView) view;
cardview.setEnabled(false);
// Create a new intent to send data from this MainActivity to the CardViewDetails
// Activity.
Intent intent = new Intent(this,CardViewDetails.class);
ListItem listItem = adapter.getItem(position);
// Add the item object to the Intent. The item object can be used because the
// model class implements Parcelable so it holds all of the getters
// that can be snagged in the next Activity with the
// getParcelableExtra method.
intent.putExtra("item",listItem);
intent.putExtra("position",position);
startActivity(intent);
finish();
}
// SearchView
final EditText mSearchEditText = (EditText) mSearchView.findViewById(android.support.v7.appcompat.R.id.search_src_text);
mSearchEditText.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
final ArrayList<ListItem> filteredModelList = filter(allList, s.toString());
if (!mSearchView.isIconified() && filteredModelList.size() == 0) {
Toast.makeText(MainActivity.this, "Not Found", Toast.LENGTH_SHORT).show();
// re-load the list so the Adapter refreshes the RecyclerView list View.
adapter.clear();
adapter.addAll(allList);
} else if (!mSearchView.isIconified() && filteredModelList.size() > 0) {
adapter.setFilter(filteredModelList, s.toString());
mRecyclerView.scrollToPosition(0);
}
}
}
});
private ArrayList<ListItem> filter(List<ListItem> models, String query) {
query = query.toLowerCase();
final ArrayList<ListItem> filteredModelList = new ArrayList<>();
for (ListItem listItem : models) {
final String text = listItem.getTodo().toLowerCase();
final String text2 = listItem.getNote1().toLowerCase();
final String text3 = listItem.getNote2().toLowerCase();
if (text.contains(query) || text2.contains(query) ||
text3.contains(query)) {
filteredModelList.add(listItem);
}
}
return filteredModelList;
}
RecyclerItemClickListener:
public interface RecyclerItemClickListener {
void onItemClick(View view, int position);
}
CardViewDetails:
public class CardViewDetails extends AppCompatActivity {
private int position;
private SQLiteDB helper;
List<ListItem> listItems;
private CardView cardview;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_details);
final CardView cardView = (CardView) findViewById(R.id.dets);
// Create a variable for the skychill footer text.
final TextView skychilltext5;
// A db helper instance is needed for the removeItem() below
// when the user Longclicks the skycard for deletion.
helper = new SQLiteDB(this);
// Get the position of the clicked on R. list CardView from
// the MainActivity's intent bundle.
Bundle extras = getIntent().getExtras();
if (extras != null) {
// get the CardView item using the int position from the
// MainActivity's onItemClick() and the putExtra in the intent.
position = extras.getInt("position",0); // 0 is default value
}
cb2 = (TextView) findViewById(R.id.cb2);
helper = new SQLiteDB(this);
listItems = new ArrayList<>();
listItems = helper.getAllDBItems();
cb2.setText(listItems.get(position).getTodo());
...
}
After applying filter the sql DB (getAllDBItems ) data remain same. You are passing only position to CardViewDetail. And the sql data is of original list.
You should pass your ListItem as parcelable to CardViewDetails instead of position. your problem will be solved.

Why is this custom listener null?

I am trying to create an interface between my Recyclerview Adapter and an Activity, so that when an item in the adapter is clicked, the Activity will react accordingly but the listener is always null.
Interface
public interface UrlTagCatClickedListener {
public void onUrlTagCatClicked (String chemicalURL);
}
Adapter
public class TagCatAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context mContext;
private List<TagCatItem> mTagCatItems;
private int lastPosition = -1;
private UrlTagCatClickedListener mTagCatClickedListener;
public TagCatAdapter(List<TagCatItem> tagCatItems, Context context) {
super();
this.mTagCatItems = tagCatItems;
this.mContext = context;
this.mTagCatClickedListener = null;
}
public void setTagCatClickedListener (UrlTagCatClickedListener tagCatClickedListener) {
this.mTagCatClickedListener = tagCatClickedListener;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.tag_cat_item, parent, false);
return new ItemViewHolder(v);
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
final TagCatItem tagCatItem = mTagCatItems.get(position);
((ItemViewHolder) holder).chemicalTitle.setText(Html.fromHtml(tagCatItem.getChemicalTitle()));
((ItemViewHolder) holder).chemicalDate.setText(tagCatItem.getChemicalDate());
((ItemViewHolder) holder).chemicalTitle.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mTagCatClickedListener != null) { // mTagCatClickedListener is always null
mTagCatClickedListener.onUrlTagCatClicked(tagCatItem.getChemicalURL());
}
}
});
}
public class ItemViewHolder extends RecyclerView.ViewHolder{
public TextView chemicalTitle, chemicalDate;
public ItemViewHolder(final View mView) {
super(mView);
chemicalTitle = (TextView) mView.findViewById(R.id.tagcat_title);
chemicalDate = (TextView) mView.findViewById(R.id.tagcat_date);
}
}
#Override
public int getItemCount() {
return mTagCatItems.size();
}
}
Activity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate called")
//Skipped a lot of codes that doesn't relate to the queation
List<TagCatItem> mTagCatItems = new ArrayList<>();
TagCatAdapter tagCatAdapter = new TagCatAdapter(mTagCatItems, this);
tagCatAdapter.setTagCatClickedListener(new UrlTagCatClickedListener() {
#Override
public void onUrlTagCatClicked(String chemicalURL) {
Log.d(TAG, "I go the url!!!!!!!!!! and it is + " + chemicalURL);
}
});
}
Please, do you have an idea why it's null and how I can fix it?
You have two different instances of TagCatAdapter in your given setup; one in the Activity, and one in the Fragment. You're setting the UrlTagCatClickedListener you've posted on the one created in the Activity, but it's the Fragment's TagCatAdapter instance that you're setting on the RecyclerView. That one doesn't have the listener set, so its mTagCatClickedListener is always null.
You just need to move the given UrlTagCatClickedListener to the TagCatAdapter in the Fragment, and remove the TagCatAdapter from the Activity, as you're not using that one anyway.

Impossible : No layout manager attached; Skipping layout

I'm completely lost with this bug, I understand it, but I don't know what's wrong.
For the code :
// In the OnCreate of my activity
historyRecyclerView = (RecyclerView)findViewById(R.id.recycler_suggestions);
SearchBarHistoryAdapter searchBarHistoryAdapter = new SearchBarHistoryAdapter();
searchBarHistoryAdapter.setActivity(this);
historyRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
historyRecyclerView.setAdapter(searchBarHistoryAdapter);
searchBarDisplayManager.setTypeAdapter(SearchBarDisplayManager.SEARCH_TYPE.HISTORY, searchBarHistoryAdapter);
The SearchDisplayManager just contains a list of adapters.
The adapter :
public class SearchBarHistoryAdapter extends SearchBarAdapter {
private ArrayList<String> historyList;
private HistoryTask historyTask;
private void setHistoryList(ArrayList<String> history) {
historyList = history;
notifyDataSetChanged();
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.search_list_item, parent, false);
final HistoryViewHolder historyViewHolder = new HistoryViewHolder(v);
return historyViewHolder;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
((HistoryViewHolder) holder).bind(historyList.get(position));
}
#Override
public int getItemCount() {
return historyList == null ? 0 : historyList.size();
}
#Override
public void startSearch(String searchString) {
if(TextUtils.isEmpty(searchString)) {
if (historyTask != null) {
historyTask.cancel(true);
}
historyTask = new HistoryTask();
historyTask.execute();
}else{
setHistoryList(null);
}
}
private class HistoryTask extends AsyncTask<Void, Void, ArrayList<String>> {
#Override
protected ArrayList<String> doInBackground(Void... params) {
String history = HelperUI.getSearchbarHistory(activity);
if (!TextUtils.isEmpty(history)) {
return new ArrayList<>(Arrays.asList(history.split("--")));
}
return new ArrayList<>(0);
}
#Override
protected void onPostExecute(ArrayList<String> results) {
super.onPostExecute(results);
if (!results.isEmpty()) {
setHistoryList(results);
}
historyTask = null;
}
}
private class HistoryViewHolder extends RecyclerView.ViewHolder {
TextView hint, name;
ImageView img;
public HistoryViewHolder(View v) {
super(v);
name = (TextView) v.findViewById(R.id.app_label);
hint = ((TextView) v.findViewById(R.id.type_label));
img = ((ImageView) v.findViewById(R.id.item_icon));
}
public void bind(String suggestion) {
name.setText(Html.fromHtml(suggestion));
img.setImageDrawable(activity.getResources().getDrawable(R.drawable.ic_public_grey600_48dp));
img.setTag(suggestion);
}
}
}
Here is the crazy part, when I update the list in setHistoryList, I know the recycler view has the right adapter and it is not null ... but then it kinda loses it, no more adapter in the Recycler view when it tries to update by notifyDatasetChanged() ... it just disappears and, of cours, displays nothing.
Any idea what's wrong ?
You Have to Add a layoutmanager as you regularly do with any Adapter you create for a RecyclerView.
historyRecyclerView.setLayoutManager(new LinearLayoutManager(context));
Just add this line below of code below setAdpater where you are setting your recycler view with the adpapter.
You can add this to xml also (Thanks #Indra Kumar S)
app:layoutManager="android.support.v7.widget.LinearLayoutManager"
For those using AndroidX, a slight modification of #Doongsil's solution:
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
My private Variable here
private RecyclerView recycleViewtask;
private RecyclerView.LayoutManager mLayoutManager;
Then I assign following things
recycleViewtask = findViewById(R.id.recycleViewtask);
recycleViewtask.setHasFixedSize(true);
// use a linear layout manager
mLayoutManager = new LinearLayoutManager(this);
recycleViewtask.setLayoutManager(mLayoutManager);

Categories

Resources