I have a RecycleView that has cards inside of it. Each card has a list of companies and prices.
In my onBindViewHolder I have a click event where I would like to get the price of the TextView in that row inside of the Cardview.
Every time I click I always get the value/price of the top item inside of the individual card and never get the price of the item I am clicking.
The data param of the bindData method is what I am using to create the list of items inside of the Cardview.
Any help would be greatly appreciated. I just need to get the value of the correct TextView where I am clicking.
public class StockCardAdapter extends RecyclerView.Adapter<StockCardAdapter.ViewHolder> {
public static class ViewHolder extends RecyclerView.ViewHolder {
protected RelativeLayout mCardBodyLayout;
protected TextView mTitleTextView;
public ViewHolder(View v) {
super(v);
mCardBodyLayout = (RelativeLayout) v.findViewById(R.id.card_body);
mTitleTextView = (TextView) v.findViewById(R.id.card_title);
}
public void bindData(StockCategoryModel data, Context ctx) {
this.mTitleTextView.setText(data.getCategoryName());
TableLayout tableLayout = new TableLayout(ctx);
int rows = data.getStockList().size();
for (int r = 0; r < rows; r++) {
TableRow row = new TableRow(ctx);
TableLayout.LayoutParams rowParams = new TableLayout.LayoutParams (TableLayout.LayoutParams.MATCH_PARENT,TableLayout.LayoutParams.WRAP_CONTENT);
rowParams.setMargins(0, 0, 0, 16);
row.setLayoutParams(rowParams);
LinearLayout rl = new LinearLayout(ctx);
rl.setOrientation(LinearLayout.VERTICAL);
Integer priceColor = SharedUtilities.getColor(data.getStockList().get(r).priceChange, ctx);
//price row
LinearLayout priceLayout = new LinearLayout(ctx);
priceLayout.setOrientation(LinearLayout.HORIZONTAL);
priceLayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
priceLayout.setWeightSum(4);
LinearLayout.LayoutParams textViewParams = new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f);
final TextView price_text = new TextView(ctx);
price_text.setTag("priceTag");
price_text.setText(data.getStockList().get(r).price);
price_text.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
price_text.setTextColor(Color.BLACK);
price_text.setLayoutParams(textViewParams);
priceLayout.addView(price_text);
//company row
final TextView name_text = new TextView(ctx);
name_text.setText(data.getStockList().get(r).company);
name_text.setTextColor(Color.GRAY);
name_text.setLayoutParams( new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT));
name_text.setMaxWidth(700);
name_text.setEllipsize(TextUtils.TruncateAt.END);
name_text.setMaxLines(1);
name_text.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
rl.addView(priceLayout);
rl.addView(name_text);
row.addView(rl);
tableLayout.setStretchAllColumns(true);
tableLayout.addView(row);
}
mCardBodyLayout.addView(tableLayout);
}
}
private List<StockCategoryModel> mDataset;
private Context mContext;
// Constructor
public StockCardAdapter(List<StockCategoryModel> dataset, Context ctx) {
this.mDataset = dataset;
this.mContext = ctx;
}
#Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
// Create new views (invoked by the layout manager)
#Override
public StockCardAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup,
int viewType) {
// create a new view
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.card_layout, viewGroup, false);
ViewHolder vh = new ViewHolder(v);
return vh;
}
// Replace the contents of a view (invoked by the layout manager)
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override public void onClick(View v2) {
final TextView textViewName = (TextView) v2.findViewWithTag("priceTag"); ;
final String priceTag = textViewName.getText().toString();
}
});
holder.bindData(mDataset.get(position), mContext);
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return mDataset.size();
}
}
What you need to do is to set a click listener to every row separately.
Why do you always get the first row value?
This code,
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override public void onClick(View v2) {
final TextView textViewName = (TextView) v2.findViewWithTag("priceTag"); ;
final String priceTag = textViewName.getText().toString();
}
});
Sets a click listener to every list item - the whole card. This means that every time the user clicks inside the card view bounds - this callback will be fired. BUT, who will be v2? It will always be the view to which we set the listener to - in this case - the whole card.
This means that every time you call v2.findViewWithTag("priceTag"); you are searching the first child of the entire card that has the tag "priceTag" - which is the "top" item in the card.
How to solve this issue?
If you want to identify which child is being clicked - you will have to set a click listener to each child directly.
As an example, try this code (see ADDED comments):
public class StockCardAdapter extends
RecyclerView.Adapter<StockCardAdapter.ViewHolder> {
public static class ViewHolder extends RecyclerView.ViewHolder {
protected RelativeLayout mCardBodyLayout;
protected TextView mTitleTextView;
public ViewHolder(View v) {
super(v);
mCardBodyLayout = (RelativeLayout) v.findViewById(R.id.card_body);
mTitleTextView = (TextView) v.findViewById(R.id.card_title);
}
public void bindData(StockCategoryModel data, Context ctx, View.OnClickListener listener) {
this.mTitleTextView.setText(data.getCategoryName());
TableLayout tableLayout = new TableLayout(ctx);
int rows = data.getStockList().size();
for (int r = 0; r < rows; r++) {
TableRow row = new TableRow(ctx);
TableLayout.LayoutParams rowParams = new TableLayout.LayoutParams (TableLayout.LayoutParams.MATCH_PARENT,TableLayout.LayoutParams.WRAP_CONTENT);
rowParams.setMargins(0, 0, 0, 16);
row.setLayoutParams(rowParams);
LinearLayout rl = new LinearLayout(ctx);
rl.setOrientation(LinearLayout.VERTICAL);
Integer priceColor = SharedUtilities.getColor(data.getStockList().get(r).priceChange, ctx);
//price row
LinearLayout priceLayout = new LinearLayout(ctx);
priceLayout.setOrientation(LinearLayout.HORIZONTAL);
priceLayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
priceLayout.setWeightSum(4);
LinearLayout.LayoutParams textViewParams = new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f);
final TextView price_text = new TextView(ctx);
price_text.setTag("priceTag");
price_text.setText(data.getStockList().get(r).price);
price_text.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
price_text.setTextColor(Color.BLACK);
price_text.setLayoutParams(textViewParams);
priceLayout.addView(price_text);
//company row
final TextView name_text = new TextView(ctx);
name_text.setText(data.getStockList().get(r).company);
name_text.setTextColor(Color.GRAY);
name_text.setLayoutParams( new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT));
name_text.setMaxWidth(700);
name_text.setEllipsize(TextUtils.TruncateAt.END);
name_text.setMaxLines(1);
name_text.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
rl.addView(priceLayout);
rl.addView(name_text);
row.addView(rl);
tableLayout.setStretchAllColumns(true);
tableLayout.addView(row);
// *ADDED* set the listener directly to each row
row.setOnClickListener(listener);
}
mCardBodyLayout.addView(tableLayout);
}
}
private List<StockCategoryModel> mDataset;
private Context mContext;
// Constructor
public StockCardAdapter(List<StockCategoryModel> dataset, Context ctx) {
this.mDataset = dataset;
this.mContext = ctx;
}
#Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
// Create new views (invoked by the layout manager)
#Override
public StockCardAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup,
int viewType) {
// create a new view
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.card_layout, viewGroup, false);
ViewHolder vh = new ViewHolder(v);
return vh;
}
// Replace the contents of a view (invoked by the layout manager)
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
// *ADDED* Send the callback to the bind method
holder.bindData(mDataset.get(position), mContext, new View.OnClickListener() {
#Override public void onClick(View v2) {
final TextView textViewName = (TextView) v2.findViewWithTag("priceTag"); ;
final String priceTag = textViewName.getText().toString();
}
}));
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return mDataset.size();
}
}
NOTE:
This is NOT the proper way to handle a RecyclerView - You never want to create a new object (in this case new View.OnClickListener() {}) inside the data binding - that will reduce performance. But this is another issue :)
The tag of textView is same in all the cases and that's why it is repeating, only the value of first item. Assign unique tag usually by concatenating "priceTag" with position. Make changes in your code as follows:
public void bindData(StockCategoryModel data, Context ctx, int position) {
//All your code
//..
//...
final TextView price_text = new TextView(ctx);
price_text.setTag("priceTag"+String.valueOf(position));
}
and in your onBindViewHolder:
final TextView textViewName = (TextView) v2.findViewWithTag("priceTag"+String.valueOf(position));
holder.bindData(mDataset.get(position), mContext,position);
Find child view from Tag
please call it.
TextView priceTagTextView =(TextView)getViewsByTag(mCardBodyLayout, "priceTag").get(0);
private ArrayList<View> getViewsByTag(ViewGroup root, String tag){
ArrayList<View> views = new ArrayList<View>();
final int childCount = root.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = root.getChildAt(i);
if (child instanceof ViewGroup) {
getViewsByTag((ViewGroup) child, tag));
}
final Object tagObj = child.getTag();
if (tagObj != null && tagObj.equals(tag)) {
views.add(child);
}
}
return views;
}
Related
I Am working on project where users recognizes text(OCR) and then see all their text(OCR) history in another activity
App Link : https://play.google.com/store/apps/details?id=com.thetechroot.vision
I added shared preference and recycle view,
but i am only getting the first Text that was recognized
Working :-
Users Recognize Text(OCR) in Textactivity, then to view users history of scanned text(OCR) the history is shown in different activity
How Can I Saved Textview From One Activity to diff activity, and show it into recycleview using shared preference
TEXTACTIVTY.JAVA
textRecognizer.processImage(image)
.addOnSuccessListener(new OnSuccessListener<FirebaseVisionText>() {
#Override
public void onSuccess(final FirebaseVisionText firebaseVisionText) {
translatelan(firebaseVisionText);
cd_text_re.setVisibility(View.VISIBLE);
spinnerlan.setVisibility(View.VISIBLE);
txtrecog.setText(firebaseVisionText.getText());
String th = SharedCommon.getSharedPreferencesString(getApplicationContext(), texthistory,firebaseVisionText.getText());
//int i = SharedCommon.getPreferencesInt(getApplicationContext(), key1,50);
final SharedCommon scth = new SharedCommon();
if (txtrecog.equals("")){
Toast.makeText(TextActivity.this, "Text: "+th, Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(TextActivity.this, "Text: "+th, Toast.LENGTH_SHORT).show();
scth.putSharedPreferencesString(getApplicationContext(), SharedCommon.texthistory, th);
}
/* SharedPreferences.Editor editor = getSharedPreferences(MY_PREFS_NAME, MODE_PRIVATE).edit();
editor.putString("name", String.valueOf(txtrecog.getText()));
editor.putInt("idName", 1);
editor.apply();*/
drawtextvision(firebaseVisionText);
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
MyAdapter.java
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private List<String> values;
ArrayList personNames;
Context context;
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public class ViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public TextView txtHeader;
public TextView txtFooter;
public View layout;
public ViewHolder(View v) {
super(v);
layout = v;
txtHeader = (TextView) v.findViewById(R.id.firstLine);
txtFooter = (TextView) v.findViewById(R.id.secondLine);
}
}
public void add(int position, String item) {
values.add(position, item);
notifyItemInserted(position);
}
public void remove(int position) {
values.remove(position);
notifyItemRemoved(position);
}
public MyAdapter(Context context, ArrayList personNames) {
this.context = context;
this.personNames = personNames;
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(List<String> myDataset) {
values = myDataset;
}
// Create new views (invoked by the layout manager)
#Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
/*final String th = SharedCommon.getSharedPreferencesString(getApplicationContext(), texthistory,"");
*/
LayoutInflater inflater = LayoutInflater.from(
parent.getContext());
View v =
inflater.inflate(R.layout.layout_history_text, parent, false);
// set the view's size, margins, paddings and layout parameters
ViewHolder vh = new ViewHolder(v);
return vh;
}
// Replace the contents of a view (invoked by the layout manager)
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
final String name = values.get(position);
holder.txtHeader.setText(name);
holder.txtHeader.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
holder.txtFooter.setText("Footer: " + name);
}
});
//holder.txtFooter.setText("Footer: " + name);
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return values.size();
}
}
HISTORYACTIVITY.JAVA
public class AboutActivity extends AppCompatActivity {
/* WebView webView;*/
ProgressDialog mprogreeinternet;
String apppackagename = "com.thetechroot.vision";
int versionCode = BuildConfig.VERSION_CODE;
String versionName = BuildConfig.VERSION_NAME;
String appid = BuildConfig.APPLICATION_ID;
Button btnlimit;
WebView webview;
/* private RecyclerView recyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager layoutManager;*/
private RecyclerView recyclerView;
private MyAdapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
LinearLayout layouthide,layoutcredit;
int[] photos={R.drawable.logoam, R.drawable.iconshandwrit52,R.drawable.productsearch52,R.drawable.iconsqrcode52};
ImageButton arrdown,arrup,arrcre,arrcreup;
TextView txthistory;
TextView mItemDescription;
ImageButton mDescriptionImg,mupImg;
CardView cdhistory;
#SuppressLint("WrongViewCast")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_about);
/* btnlimit = (Button) findViewById(R.id.btnlimit);*/
final String th = SharedCommon.getSharedPreferencesString(getApplicationContext(), texthistory,"");
// Toast.makeText(this, ""+th, Toast.LENGTH_SHORT).show();
recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
// use this setting to improve performance if you know that changes
// in content do not change the layout size of the RecyclerView
// recyclerView.setHasFixedSize(true);
// use a linear layout manager
mLayoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(mLayoutManager);
// Use the default animator
// recyclerView.setItemAnimator(new DefaultItemAnimator());
// you could add item decorators
// RecyclerView.ItemDecoration itemDecoration = new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST);
// recyclerView.addItemDecoration(itemDecoration);
ArrayList<String> values = new ArrayList<String>();
/*for (int i = 0; i < 100; i++) {
values.add("Test" + i);
}*/
Toast.makeText(this, ""+String.valueOf(th), Toast.LENGTH_SHORT).show();
values.add(""+String.valueOf(th));
// specify an adapter (see also next example)
mAdapter = new MyAdapter(values);
recyclerView.setAdapter(mAdapter);
ItemTouchHelper.SimpleCallback simpleItemTouchCallback =
new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
#Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder
target) {
return false;
}
#Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
// input.remove(viewHolder.getAdapterPosition());
mAdapter.notifyItemRemoved(viewHolder.getAdapterPosition());
}
};
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback);
itemTouchHelper.attachToRecyclerView(recyclerView);
}
#Override
public void onBackPressed() {
super.onBackPressed();
Intent startIntent = new Intent(AboutActivity.this, TextActivity.class);
startActivity(startIntent);
finish();
}
}
It's a position issue, you have to use setTag() and getTag(), check this
final String name = values.get(position);
**holder.txtFooter.setTag(name);**
holder.txtHeader.setText(name);
holder.txtHeader.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
**holder.txtFooter.setText("Footer: " + v.getTag());**
}
});
Here TEXTACTIVTY.JAVA you are using single string, so instead of appending it to previous strings in shared preference you are replacing the history. Ideally you should save Strings array and retrieve the same. Currently values have size one because it has only one string.
First use Sting Array. To save String Array in shared preferences do the following
StringBuilder sb = new StringBuilder();
for (int i = 0; i < playlists.length; i++) {
sb.append(playlists[i]).append(",");
}
prefsEditor.putString(PLAYLISTS, sb.toString());
Then when you get the String from SharedPreferences simply parse it like this:
String[] playlists = playlist.split(",");
Refer Put and get String array from shared preferences
And https://blog.fossasia.org/storing-a-data-list-in-phimpme-android/ for more.
I am using RecyclerView and new items appear in it only at the top of the list. I want to use default insert animation for this action, but it breaks OnClick() method inside ViewHolder.
If I have inserted new item, OnClick() uses data from the previous item of ArrayList. If I use NotifyDataSetChanged(), data is ok, but of course, there is no animation. Looks like there is problem with ViewHolder.bind() method being not called. How can I update index of every item after NotifyItemInserted(0)?
RecyclerAdapter.java
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder> {
private Context context;
private LayoutInflater inflater;
private ArrayList<Song> data = new ArrayList<>();
//то, что ниже - для анимации
private static final int UNSELECTED = -1;
private RecyclerView recyclerView;
private int selectedItem = UNSELECTED;
public RecyclerAdapter(Context context, ArrayList<Song> data, RecyclerView recyclerView) {
this.context = context;
inflater = LayoutInflater.from(context);
this.data = data;
this.recyclerView = recyclerView;
}
public void insert(Song song)
{
data.add(0, song);
recyclerView.scrollToPosition(0);
notifyItemInserted(0);
}
public void swap(ArrayList<Song> datas){
data.clear();
data.addAll(datas);
notifyDataSetChanged();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView tv_songName;
TextView tv_songGenreID;
TextView tv_songUserInfo;
ExpandableLayout expandableLayout;
private CardView expandButton;
private int position;
private TextView youtubeButton;
private TextView shareButton;
public ViewHolder(View itemView) {
super(itemView);
tv_songName = (TextView) itemView.findViewById(R.id.tv_songName);
tv_songGenreID = (TextView) itemView.findViewById(R.id.tv_songGenreID);
tv_songUserInfo = (TextView) itemView.findViewById(R.id.tv_songUserInfo);
youtubeButton = (TextView) itemView.findViewById(R.id.youtube_button);
shareButton = (TextView) itemView.findViewById(R.id.share_button);
expandableLayout = (ExpandableLayout) itemView.findViewById(R.id.expandable_layout);
expandableLayout.setInterpolator(new OvershootInterpolator());
expandButton = (CardView) itemView.findViewById(R.id.card_view);
expandButton.setOnClickListener(this);
youtubeButton.setOnClickListener(this);
shareButton.setOnClickListener(this);
}
public void bind(int position) {
this.position = position;
Song current = data.get(position);
StringBuilder songInfo = new StringBuilder();
songInfo.append(context.getString(R.string.genre));
songInfo.append(current.songGenreID);
songInfo.append(System.getProperty("line.separator"));
songInfo.append(context.getString(R.string.album));
this.tv_songName.setText(current.songName);
this.tv_songGenreID.setText(songInfo);
this.tv_songUserInfo.setText(current.songUserInfo);
expandButton.setSelected(false);
expandableLayout.collapse(false);
}
#Override
public void onClick(View view) {
switch (view.getId())
{
case R.id.youtube_button:
String youtubeURL = data.get(position).songName.replaceAll(" ", "%20");
youtubeURL = "https://www.youtube.com/results?search_query=" + youtubeURL;
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(youtubeURL));
context.startActivity(browserIntent);
break;
case R.id.share_button:
String songName = data.get(position).songName;
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_TEXT, songName);
shareIntent.setType("text/plain");
context.startActivity(shareIntent);
break;
default:
ViewHolder holder = (ViewHolder) recyclerView.findViewHolderForAdapterPosition(selectedItem);
if (holder != null) {
holder.expandButton.setSelected(false);
holder.expandableLayout.collapse();
}
if (position == selectedItem) {
selectedItem = UNSELECTED;
} else {
expandButton.setSelected(true);
expandableLayout.expand();
selectedItem = position;
}
break;
}
}
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v=inflater.inflate(R.layout.recycler_item, parent,false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.bind(position);
setAnimation(holder.itemView, position);
}
private int lastPosition = -1;
private void setAnimation(View viewToAnimate, int position) {
if (position > lastPosition) {
Animation anim = AnimationUtils.loadAnimation(context, android.R.anim.fade_in);
viewToAnimate.startAnimation(anim);
lastPosition = position;
}
}
#Override
public int getItemCount() {
return data.size();
}
}
OnCreate() of Activity.java
protected void onCreate(Bundle savedInstanceState) {
setTheme(R.style.AppTheme_NoActionBar);
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
layout = (CoordinatorLayout)findViewById(R.id.coordinator1);
FloatingActionButton myFab = (FloatingActionButton) findViewById(R.id.floatingActionButton);
mRecyclerView = (RecyclerViewEmptySupport) findViewById(R.id.my_recycler_view);
mRecyclerView.setEmptyView(findViewById(R.id.list_empty));
myFab.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
FragmentManager fm = getSupportFragmentManager();
AddSongDialogFragment addSongDialogFragment = new AddSongDialogFragment();
addSongDialogFragment.show(fm, "add_song");
}
});
mAdapter = new RecyclerAdapter(MainActivity.this, data, mRecyclerView);
mLayoutManager = new LinearLayoutManager(MainActivity.this);
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(mLayoutManager);
dbHelper = new DBHelper(this);
mAdapter.swap(dbHelper.readFromDB());
RecyclerView.ItemAnimator itemAnimator = new DefaultItemAnimator();
itemAnimator.setAddDuration(700);
itemAnimator.setRemoveDuration(1000);
mRecyclerView.setItemAnimator(itemAnimator);
}
Use getAdapterPosition() to get correct position of your item from your VIewHolder. That way the positions will not be mixed up after moving/deleting items from the RecyclerView.
NOTE: If the user clicks on the empty space during the animationgetAdapterPosition() might return -1: make sure to handle the case.
Good luck
You can use notifyItemRangeChanged(position, data.size()); to notify the other items after you added the new item.
You can also animate the swap() function if you use the functions notifyItemRemoved() notifyItemInserted() and notifyItemMoved() instead of notifyDataSetChanged(). You only have to check if the new list includes the items of the old list.
I am using RecyclerView to display an ArrayList and I plan on having alot of combos of TextViews so instead of making 10 layout files I just made one with ALL my TextViews.
Certain rows I want to display only some of the TextViews so I leave them blank (" ") but obviously the TextView still takes up that blank space.
So I think I must use setVisibility Gone for the blanks and must probably go under the onBindViewHolder but I am not sure how the if statement must look.
public class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> {
List<AdapterData> mItems;
public Adapter() {
super();
mItems = new ArrayList<>();
AdapterData data = new AdapterData();
data.setName("dummy text");
data.setNameTwo("");
data.setNameThree("");
mItems.add(data);
data = new AdapterData();
data.setName("dummy text");
data.setNameTwo("dummy text");
data.setNameThree("");
mItems.add(data);
data = new AdapterData();
data.setName("");
data.setNameTwo("dummy text");
data.setNameThree("");
mItems.add(data);
data = new AdapterData();
data.setName("");
data.setNameTwo("dummy text");
data.setNameThree("dummy text");
mItems.add(data);
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.recycler_view_card_item, viewGroup, false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {
AdapterData data = mItems.get(i);
viewHolder.mName.setText(data.getName());
viewHolder.mNameTwo.setText(data.getNameTwo());
viewHolder.mNameThree.setText(data.getNameThree());
}
#Override
public int getItemCount() {
return mItems.size();
}
class ViewHolder extends RecyclerView.ViewHolder{
public TextView mName;
public TextView mNameTwo;
public TextView mNameThree;
public ViewHolder(View itemView) {
super(itemView);
mName = (TextView)itemView.findViewById(R.id.layoutName);
mNameTwo = (TextView)itemView.findViewById(R.id.layoutNameTwo);
mNameThree = (TextView)itemView.findViewById(R.id.layoutNameThree);
}
}
}
Use TextUtils.isEmpty
if(TextUtils.isEmpty(data.getName())){
viewHolder.mName.setVisibility(GONE);
}else{
viewHolder.mName.setVisibility(VISIBLE);
}
if(TextUtils.isEmpty(data.getNameTwo())){
viewHolder. mNameTwo.setVisibility(GONE);
}else{
viewHolder.mNameTwo.setVisibility(VISIBLE);
}
and soo on..
In ListView I have list of LinearLayouts(LL). Each LinearLayout(LL) have 2 LinearLayouts(LL1 and LL2). And the second LinearLayout(LL2) haveTextView I want get TextView's value in LinearLayout via OnButtonCliclListener
Here is code of my Adapter:
int resource;
TextView tt;
LinearLayout LL;
LinearLayout LL2;
LinearLayout LL1;
TextView currentText;
public Vk_row_adapter(Context _context, List<? extends Map<String, ?>> data, int _resource, String[] from, int[] to) {
super(_context, data, _resource, from, to);
this.results = data;
context = _context;
resource = _resource;
}
#Override
public View getView(int position, View view, ViewGroup parent){
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(resource, parent, false);
LL= (LinearLayout)v.getRootView();
LL1 = (LinearLayout)LL.getChildAt(0);
LL1.setOnClickListener(onButtonClickListener);
LL2 = (LinearLayout)LL.getChildAt(1);
LL2.setOnClickListener(onButtonClickListener);
currentText = (TextView)LL2.getChildAt(0);
tt = (TextView) v.findViewById(R.id.vk_name);
tt.setText((CharSequence) results.get(position).get(ATTRIBUTE_NAME_TEXT_NAME));
//other elements
return v;
}
private View.OnClickListener onButtonClickListener = new View.OnClickListener()
{
Toast.makeText(context, currentText.getText(), Toast.LENGTH_LONG).show();
};
It gives me only the last TextView's text. I know why. But I don't know to make it correctly. Any ideas?
Really...
You have one variable storing the current text for LL2 and non storing it for LL1, yet you are using the same onclicklistener for both...
There are several solutions here, lets go with the make a second variable and onclicklistener for simplicity
Here is my sollution
public class Vk_row_adapter extends SimpleAdapter {
final String ATTRIBUTE_NAME_TEXT_NAME = "text_name";
final String ATTRIBUTE_NAME_TEXT_RAITING = "text_place";
final String ATTRIBUTE_NAME_IMAGE = "image";
private List<? extends Map<String, ?>> results;
Context context;
String Name=null;
int resource;
TextView tt;
LinearLayout LL;
LinearLayout LL2;
LinearLayout LL1;
TextView currentText;
public Vk_row_adapter(Context _context, List<? extends Map<String, ?>> data, int _resource, String[] from, int[] to) {
super(_context, data, _resource, from, to);
this.results = data;
context = _context;
resource = _resource;
}
#Override
public View getView(int position, View view, ViewGroup parent){
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(resource, parent, false);
LL= (LinearLayout)v.getRootView();
LL.setOnClickListener(onButtonClickListener);
tt = (TextView) v.findViewById(R.id.vk_name);
tt.setText((CharSequence) results.get(position).get(ATTRIBUTE_NAME_TEXT_NAME));
TextView bt = (TextView) v.findViewById(R.id.vk_raiting);
bt.setText((CharSequence) results.get(position).get(ATTRIBUTE_NAME_TEXT_RAITING));
ImageView vt = (ImageView)v.findViewById(R.id.vk_photo);
vt.setImageBitmap((android.graphics.Bitmap) results.get(position).get(ATTRIBUTE_NAME_IMAGE));
return v;
}
private View.OnClickListener onButtonClickListener = new View.OnClickListener()
{
#Override
public void onClick(View view) {
LinearLayout asd = (LinearLayout)view;
LL2 = (LinearLayout)asd.getChildAt(1);
currentText = (TextView)LL2.getChildAt(0);
new AlertDialog.Builder(context)
.setTitle(currentText.getText())
.setMessage("Перейти на страницу Вконтакте?")
.setNegativeButton(android.R.string.no, null)
.setPositiveButton("Да",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {
}
}).create().show();
}
};
private String getName()
{
int i = Top_Tab2.VkRowListView2.indexOfChild(tt);
return String.valueOf(i);
}
}
Befor using the viewholder i was able to change the background of one element (that with te position == numEmission) of my listview but now each tiem i scroll the colored item change and i can have even 3 colored item, can any one help me.
public class ItemAdapterProgramme extends ArrayAdapter<Programme> {
public ArrayList<Programme> resultats;
public Bitmap bm;
public Context context;
public ImageLoader imageLoader = ImageLoader.getInstance();
public DisplayImageOptions options;
static ViewHolder holder;
public LayoutInflater mInflater ;
public int numEmission;
public Calendar c;
public int cHour;
Typeface typeface_date, typeface_title;
public ItemAdapterProgramme(Context context, ArrayList<Programme> resultat) {
super(context, R.layout.feed_view_programme, resultat);
this.context = context;
resultats = resultat;
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
typeface_date = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto/Roboto-Medium.ttf");
typeface_title = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto/Roboto-Condensed.ttf");
}
public View getView(final int position, View convertView, final ViewGroup parent) {
if (convertView == null) {
convertView = mInflater.inflate(R.layout.feed_view_programme,parent, false);
holder = new ViewHolder();
holder.image = (ImageView) convertView.findViewById(R.id.prog_logo);
holder.titre = (TextView) convertView.findViewById(R.id.prog_title);
holder.animator = (TextView) convertView.findViewById(R.id.prog_anim);
holder.start = (TextView) convertView.findViewById(R.id.prog_start);
holder.end = (TextView) convertView.findViewById(R.id.prog_end);
holder.description = (TextView) convertView.findViewById(R.id.prog_description);
holder.animator.setTypeface(typeface_date);
holder.titre.setTypeface(typeface_title);
holder.start.setTypeface(typeface_title);
holder.end.setTypeface(typeface_title);
holder.description.setTypeface(typeface_title);
holder.pb = (ProgressBar) convertView.findViewById(R.id.prog_progressBar1);
holder.relativeLout_emission = (RelativeLayout)convertView.findViewById(R.id.layout_prog);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.titre.setText(resultats.get(position).getTitle());
holder.animator.setText(resultats.get(position).getAnimateur());
holder.start.setText("Début: "+resultats.get(position).getStart());
holder.end.setText(" Fin: "+resultats.get(position).getEnd());
holder.description.setText(resultats.get(position).getDescription());
File cacheDir = StorageUtils.getOwnCacheDirectory(context, "UniversalImageLoader/Cache");
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
.denyCacheImageMultipleSizesInMemory()
.offOutOfMemoryHandling()
.memoryCache(new UsingFreqLimitedMemoryCache(2 * 1024 * 1024))
.discCache(new UnlimitedDiscCache(cacheDir))
.discCacheFileNameGenerator(new HashCodeFileNameGenerator())
.imageDownloader(new URLConnectionImageDownloader(5 * 1000, 20 * 1000))
.defaultDisplayImageOptions(DisplayImageOptions.createSimple())
.enableLogging()
.build();
imageLoader.init(config);
options = new DisplayImageOptions.Builder()
.showStubImage(R.drawable.error)
.showImageForEmptyUri(R.drawable.error)
.cacheInMemory()
.cacheOnDisc()
.imageScaleType(ImageScaleType.IN_SAMPLE_INT)
.build();
imageLoader.displayImage(resultats.get(position).getImageUrl(), holder.image, options, new ImageLoadingListener() {
#Override
public void onLoadingStarted() {
holder.pb.setVisibility(View.VISIBLE); }
#Override
public void onLoadingFailed(FailReason failReason) {
holder.pb.setVisibility(View.GONE);
}
#Override
public void onLoadingComplete(Bitmap loadedImage) {
holder.pb.setVisibility(View.GONE);
}
#Override
public void onLoadingCancelled() {
// Do nothing
}
});
c = Calendar.getInstance();
cHour=c.get(Calendar.HOUR_OF_DAY);
Log.d("Adapter cHour", cHour+"");
numEmission=findEmission(cHour);
Log.d("Adapter numEmission", numEmission+"");
if(position==numEmission){
holder.relativeLout_emission.setBackgroundColor(context.getResources().getColor(R.color.grey));
}
return convertView;
}
public int findEmission(int hour){
for(int i=0;i < resultats.size()-1;i++){
String start=resultats.get(i).getStart();
String end=resultats.get(i).getEnd();
String[] P0=start.split(":");
String[] P1=end.split(":");
start=P0[0];
end=P1[0];
int intStart=Integer.parseInt(start);
int intEnd=Integer.parseInt(end);
if(intStart<=hour && hour<=intEnd) {
numEmission=i;
break;
}
}
return numEmission;
}
static class ViewHolder {
TextView titre, animator, start, end, description;
ImageView image;
ProgressBar pb;
RelativeLayout relativeLout_emission;
}
The problem is not in holder, but in convertView. ListView can use one convertView several times to increase perfomance. So if you colored item once, each time it is reused you will have one more colored item. You can remove holder and inflate new view each time, but it is not good to do so.
Try modifiying your code like this
if (position==numEmission) {
holder.relativeLout_emission.setBackgroundColor(context.getResources().getColor(R.color.grey));
} else {
// set default background color
holder.relativeLout_emission.setBackgroundColor(context.getResources().getColor(R.color.default_list_element_background));
}