I have one list in which I have one image view .I need to show that image only when my one variable is true .Actually I make a custom adapter in which I have one variable "serviceAlertPresent" .If it is true I need to show image elese I don't want to show image on row.How I Will acheive this
Here is my code of each row .
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="#android:color/transparent"
android:padding="5dp" >
<TextView
android:id="#+id/item_platform"
android:layout_width="25dp"
android:layout_height="wrap_content"
android:layout_marginRight="16dp"
android:text="Ptf."
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="#+id/item_schDepart"
android:layout_width="35dp"
android:layout_height="wrap_content"
android:layout_alignBaseline="#+id/item_platform"
android:layout_alignBottom="#+id/item_platform"
android:layout_toRightOf="#+id/item_platform"
android:text="dpt"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="#+id/item_arrival"
android:layout_width="45dp"
android:layout_height="wrap_content"
android:layout_alignBaseline="#+id/item_schDepart"
android:layout_alignBottom="#+id/item_schDepart"
android:layout_marginLeft="20dp"
android:layout_toRightOf="#+id/item_expectdepart"
android:text="Arr."
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="#+id/item_expectdepart"
android:layout_width="45dp"
android:layout_height="wrap_content"
android:layout_below="#+id/item_schDepart"
android:layout_marginTop="14dp"
android:layout_toRightOf="#+id/item_platform"
android:text="Expert"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="#+id/item_expertarrival"
android:layout_width="45dp"
android:layout_height="wrap_content"
android:layout_alignBaseline="#+id/item_expectdepart"
android:layout_alignBottom="#+id/item_expectdepart"
android:layout_alignLeft="#+id/item_arrival"
android:text="exprt Arrival"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="#+id/item_stationName"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:layout_alignBaseline="#+id/item_arrival"
android:layout_alignBottom="#+id/item_arrival"
android:layout_marginLeft="17dp"
android:layout_toRightOf="#+id/item_expertarrival"
android:text="Des."
android:ellipsize="end"
android:textAppearance="?android:attr/textAppearanceMedium" />
<ImageView
android:id="#+id/alertStatus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="0dp"
android:layout_toRightOf="#+id/item_stationName"
android:src="#drawable/alert_icon" />
</RelativeLayout>
here is custom adapter
public class CustomListAdapter extends BaseAdapter{
ArrayList<deparaturedaseboarddto> deparaturedaseboarddto;
private Context context;
public CustomListAdapter( Context context, ArrayList<deparaturedaseboarddto> deparaturedaseboarddto){
this.deparaturedaseboarddto=deparaturedaseboarddto;
this.context = context;
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return deparaturedaseboarddto.size();
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return deparaturedaseboarddto.get(position);
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View v = convertView;
if (v == null) {
LayoutInflater mInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = mInflater.inflate(R.layout.row_listitem, null);
}
final TextView platFormName = (TextView) v
.findViewById(R.id.item_platform);
final TextView schDepart = (TextView) v
.findViewById(R.id.item_schDepart);
final TextView expDepart = (TextView) v
.findViewById(R.id.item_expectdepart);
final TextView arrival = (TextView) v
.findViewById(R.id.item_arrival);
final TextView exparrival = (TextView) v
.findViewById(R.id.item_expertarrival);
final TextView stationName = (TextView) v
.findViewById(R.id.item_stationName);
final String platformValue = deparaturedaseboarddto.get(position).getPlatformNo();
final String schDepartValue= deparaturedaseboarddto.get(position).getSchDepart();
final String schExpectValue= deparaturedaseboarddto.get(position).getExpDepart();
final String arrivalValue= deparaturedaseboarddto.get(position).getDestSchArrival();
final String exparrivalValue= deparaturedaseboarddto.get(position).getDestSchArrival();
String stationNameValue= deparaturedaseboarddto.get(position).getDestinationStation().getStationName();
platFormName.setText(platformValue);
schDepart.setText(schDepartValue);
expDepart.setText(schExpectValue);
arrival.setText(arrivalValue);
exparrival.setText(exparrivalValue);
stationName.setText(stationNameValue);
return v;
}
public void referhList( ArrayList<deparaturedaseboarddto> deparaturedaseboarddto){
this.deparaturedaseboarddto=deparaturedaseboarddto;
notifyDataSetChanged();
}
}
I am asking this image view
<ImageView
android:id="#+id/alertStatus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="0dp"
android:layout_toRightOf="#+id/item_stationName"
android:src="#drawable/alert_icon" />
I need to show this when "serviceAlertPresent" .I will get value like that deparaturedaseboarddto.get(position).isServiceAlertPresent()
In the adapter get the imageView and set the visibilite to INVISIBLE or VISIBLE.
final ImageView alertStatus = (ImageView) v
.findViewById(R.id.alertStatus);
if (condition){
alertStatus.setVisibility(View.VISIBLE);
}
else{
alertStatus.setVisibility(View.INVISIBLE);
}
And when the condition change, you should call notifyDataSetChanged() of your adapter.
Hope it helps you!
You can check boolean values of serviceAlertPresent inside getView() method itself.
If it's true then use mImageView.setVisibility(View.VISIBLE) else remove the presence of it by using mImageView.setVisibility(View.GONE).
Note: When you use GONE, it will be invisible and at the same time it will not take any space, where as when you use INVISIBLE it will be invisible and will take space in layout.
In ImageView, set android:setVisiblity="gone"; by default.
show that image only when your variable is true.
like,
imageView.setVisibility(View.GONE);
final ImageView alertStatus= (ImageView) v.findViewById(R.id.alertStatus);
v.alertStatus.setVisibility(View.INVISIBLE);
Related
so what I want is in my app there are few items which contain a media player so I want to put a 'play' icon on that list view item aligned at the right. The list view item contains an image view and text view(both having item icon and item name).
is there any way i can insert images to particular items
here's my code:
first.java:
public class first extends AppCompatActivity {
private ListView listView;
private String[] names = {"१. प्रार्थना",
"२. सुखकर्ता दु:खहर्ता",
"३. गजानना श्रीगणराया",
"४. येई हो विठ्ठले",
"५. लवथवती विक्राळा",
"६. दुर्गे दुर्घट भारी",
"७. आरती ज्ञानराजा",
"८. हे भोळ्या शंकरा",
"९. ओवाळू आरती",
"१०. मंगेशा महारूद्रा",
"११. आला गणराया",
"१२. शेंदुर लाल चढायो",
"१३. एकदंता",
"१४. कर्पूर गौरा",
"१५. हे गजवधना",
"१६. प्रथमेश्वरा",
"१७. जयदेवा हे साईनाथा",
"१८. श्री सत्यनारायणाची आरती",
"१९. श्री महालक्ष्मीची आरती",
"२०. ॐ जय लक्ष्मी माता",
"२१. आरती संतोषी माता की",
"२२. श्री हनुमंताची आरती",
"२३. सुखंकर्ता की दु:खहर्ता",
"२४. ॐ जय जगदीश",
"२५. जय श्री विश्वकर्मा",
"२६. हे गौरी गजानन",
"२७. हे गजानना गौरीनंदना",
"२८. आरती नवदुर्गेची",
"२९. हे साईनाथा जगदिश्वरा",
"३०. धन्य धन्य हो प्रदक्षिणा",
"३१. घालीन लोटांगण"};
private int imageid[] = {R.drawable.prath,
R.drawable.ganeshaji,
R.drawable.ganpati,
R.drawable.vita,
R.drawable.shivji,
R.drawable.durgamaa,
R.drawable.nyan,
R.drawable.bol,
R.drawable.krishna,
R.drawable.mangeshi,
R.drawable.ala,
R.drawable.shen,
R.drawable.ekdant,
R.drawable.karpur,
R.drawable.gajavad,
R.drawable.pratha,
R.drawable.saibaba,
R.drawable.satyanarayan,
R.drawable.laxmimaa,
R.drawable.omjailak,
R.drawable.santoshimaa,
R.drawable.hanuman,
R.drawable.ganeshaji,
R.drawable.skd,
R.drawable.vishwakarma,
R.drawable.ganpati,
R.drawable.ganeshaji,
R.drawable.navdurga,
R.drawable.saibaba,
R.drawable.danya,
R.drawable.gana};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_first);
ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayShowHomeEnabled(true);
actionBar.setIcon(R.mipmap.icon);
final CustomList CustomList = new CustomList(this, names, imageid);
listView = (ListView) findViewById(R.id.listView);
listView.setAdapter(CustomList);
}
}
arti.java:
public class arti {
private String names;
private int imageid;
public arti(String names,int imageid){
this.names=names;
this.imageid=imageid;
}
public String getNames(){
return this.names;
}
public int getImageid(){
return this.imageid;
}
}
customlist.java:
public class CustomList extends ArrayAdapter<String> {
private String[] names;
private int[] imageid;
private Activity context;
public CustomList(Activity context, String[] names, int[] imageid) {
super(context, R.layout.list_layout,names);
this.context = context;
this.names = names;
this.imageid = imageid;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View listViewItem = inflater.inflate(R.layout.list_layout, null, true);
TextView textViewName = (TextView) listViewItem.findViewById(R.id.textViewName);
ImageView image = (ImageView) listViewItem.findViewById(R.id.imageView);
textViewName.setText(names[position]);
image.setImageResource(imageid[position]);
return listViewItem;
}
first.xml:
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/listView"
android:dividerHeight="2dp"
android:layout_marginTop="3dp"
android:layout_marginBottom="1dp"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
listlayout.xml:
<ImageView
android:layout_width="80dp"
android:layout_height="80dp"
android:id="#+id/imageView" />
<TextView
android:layout_width="wrap_content"
android:layout_height="80dp"
android:gravity="center"
android:textSize="22dp"
android:text="New Text"
android:id="#+id/textViewName"
android:layout_alignParentTop="true"
android:layout_toRightOf="#+id/imageView"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true" />
I want the play image to be placed after the name of the items
Just check if the image is -1 in your getView() method like this:
if (imageid[position] != -1) {
image.setImageResource(imageid[position]);
} else {
image.setVisibility(View.GONE); //or View.INVISIBLE
}
But like this you have to set -1 as id for all items where you don't want an image
Yes, Try making the listlayout relative and use the option as below:
"To Right of" for image view to right of text view
"visibility" to show or hide the music icon. You have to enable the visibility in code as txtView.setVisibility(View.VISIBLE) as by default it is invisible.
<RelativeLayout
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:id="#+id/headerLinearLay"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="80dp"
android:gravity="center"
android:textSize="22dp"
android:text="New Text"
android:id="#+id/textViewName"
android:layout_alignParentTop="true"
android:layout_toRightOf="#+id/imageView"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true" />
<ImageView
android:layout_width="80dp"
android:layout_height="80dp"
android:id="#+id/imageView"
android:layout_toRightOf="#id/textViewName"
android:visibility="invisible" /> <!-- Enable when you want to show the play button -->
</RelativeLayout>
In your listlayout.xml
<Button
android:layout_width="80dp"
android:layout_height="80dp"
android:visibility="gone"
android:id="#+id/playButtonView" />
<ImageView
android:layout_width="80dp"
android:layout_height="80dp"
android:id="#+id/imageView" />
<TextView
android:layout_width="wrap_content"
android:layout_height="80dp"
android:gravity="center"
android:textSize="22dp"
android:text="New Text"
android:id="#+id/textViewName"
android:layout_alignParentTop="true"
android:layout_toRightOf="#+id/imageView"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true" />
Add a view to hold the Play button image. There may be another way to do this that makes more sense for you, but this should give you a good starting point.
In your customlist.java
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View listViewItem = inflater.inflate(R.layout.list_layout, null, true);
TextView textViewName = (TextView) listViewItem.findViewById(R.id.textViewName);
ImageView image = (ImageView) listViewItem.findViewById(R.id.imageView);
Button playButton = (ImageView) listViewItem.findViewById(R.id.playButtonView);
if(playButtonShouldBeVisible) //change to fit your logic
playButton.setVisibility(View.VISIBLE);
textViewName.setText(names[position]);
image.setImageResource(imageid[position]);
return listViewItem;
}
Edit 1:
Addressing the comments below. If you mean that You don't need a button for the play Image (OPTION 1), then simply change
<Button
android:layout_width="80dp"
android:layout_height="80dp"
android:visibility="gone"
android:id="#+id/playButtonView" />
to
<Button
android:layout_width="80dp"
android:layout_height="80dp"
android:visibility="gone"
android:id="#+id/playImageView" />
If by that comment you mean that you mean that you don't need an additional View, the Image View you'd already included was the one you'd use for your play image.(OPTION 2) I would change
<Button
android:layout_width="80dp"
android:layout_height="80dp"
android:visibility="gone"
android:id="#+id/playButtonView" />
<ImageView
android:layout_width="80dp"
android:layout_height="80dp"
android:id="#+id/imageView" />
to just
<ImageView
android:layout_width="80dp"
android:layout_height="80dp"
android:visibility="gone"
android:id="#+id/imageView" />
these changes would be reflected in customlist.java as either
OPTION 1:
ImageView image = (ImageView) listViewItem.findViewById(R.id.imageView);
Button playButton = (ImageView) listViewItem.findViewById(R.id.playButtonView);
if(playButtonShouldBeVisible) //change to fit your logic
playButton.setVisibility(View.VISIBLE);
gets changed to
ImageView image = (ImageView) listViewItem.findViewById(R.id.imageView);
ImageView playImage = (ImageView) listViewItem.findViewById(R.id.playImageView);
if(playImageShouldBeVisible) //change to fit your logic
playImage.setVisibility(View.VISIBLE);
OPTION 2:
ImageView image = (ImageView) listViewItem.findViewById(R.id.imageView);
Button playButton = (ImageView) listViewItem.findViewById(R.id.playButtonView);
if(playButtonShouldBeVisible) //change to fit your logic
playButton.setVisibility(View.VISIBLE);
gets change to
ImageView image = (ImageView) listViewItem.findViewById(R.id.imageView);
if(imageViewShouldBeVisible) //change to fit your logic
image.setVisibility(View.VISIBLE);
These changes should help indicate define a view in the listlayout.xml that is the play image you might wish to display, then locate that view in your Java code and provide a handle to it, then determine whether that view should be visible and based on that change the visibility property.
Just do this steps:
1. add Button invisible button with your icon to your xml:
`<Button
android:id="#+id/playButton"
android:background="your_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:visibility="invisible" />`
2. in adapter class create Set positions = new HashSet<>() and add positions that you need to this set.
3. in getView() method check:
if(positions.contains(position)){
Button play = (Button) listViewItem.findViewById(R.id.playButton);
play.setVisibility(View.VISIBLE);}
use BaseAdapter instead of ArrayAdapter, just extend BaseAdapter and implement it's methods, in getCount() return total number of list items, other methods leave empty.
In getView() do point 3 written above
Final code looks like this:
`public class Adapter extends ArrayAdapter {
private String[] names;
private int[] imageid;
private Activity mContext;
private Set set;
public Adapter(Context context, String[] names, int[] imageid) {
super(context, R.layout.item);
mContext = (Activity) context;
this.names = names;
this.imageid = imageid;
fillSet();
}
private void fillSet() {
set = new HashSet<>();
set.add(1);
set.add(2);
set.add(6);
}
#Override
public int getCount() {
return names.length;
}
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
LayoutInflater inflater = mContext.getLayoutInflater();
view = inflater.inflate(R.layout.item, null);
TextView tv = (TextView) view.findViewById(R.id.tv);
ImageView iv = (ImageView) view.findViewById(R.id.iv);
tv.setText(names[i]);
iv.setImageResource(imageid[i]);
if (set.contains(i)) {
Button button = (Button) view.findViewById(R.id.playButton);
button.setVisibility(View.VISIBLE);
}
return view;
}
}`
It should make what you want
I'm finding it hard to search for what I'm looking for so I thought I'd try and explain it here. I currently have a Custom ListView within a ScrollView. Each ListView item contains the Branch details for a shop, i.e. street address, city, phone. I've used the setListViewHeightBasedOnChildren function shown below to get around the "scrolling a ListView in a ScrollView" problem by expanding the ListView to it's full height.
What I would like to do now is, if a shop has greater than 2 branches, show 2 of the branches and then have a button at the bottom of the list view that says "Show More". If possible the button would sit on top of the list, partially showing the third branch to give it a transparent gradient effect something similar to this. Clicking on the button would ideally animate the ListView as it opens downward. I understand this is a big ask but I would just like to know if it is possible and a point in the right direction. I can work on a custom solution myself once I have an idea where to start.
My ListView implementation and Layout files can be seen below:
BranchListAdapter.java
public class BranchListAdapter extends ArrayAdapter<HashMap<String, String>> {
private Context mContext;
private LayoutInflater mLayoutInflater;
public BranchListAdapter(Context context) {
super(context, android.R.layout.simple_list_item_1);
mContext = context;
mLayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final View view;
if(convertView == null) {
view = mLayoutInflater.inflate(R.layout.fragment_shop_details_branch_list_item, parent, false);
} else {
view = convertView;
}
final HashMap<String, String> branch = getItem(position);
TextView address = (TextView) view.findViewById(R.id.branch_list_item_address);
TextView city = (TextView) view.findViewById(R.id.branch_list_item_city);
TextView phone = (TextView) view.findViewById(R.id.branch_list_item_phone);
address.setText(branch.get("address"));
city.setText(branch.get("city"));
phone.setText(branch.get("phone"));
return view;
}
public void setData(List<HashMap<String, String>> branches) {
clear();
if(branches != null) {
for(HashMap<String, String> branch : branches) {
if(!branch.get("address").equals(""))
add(branch);
}
}
}
}
fragment_shop_details_branch_list_adapter.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.GridLayout
android:id="#+id/branch_list_item_grid"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:grid="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
grid:columnCount="2"
grid:orientation="vertical"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="8dp"
xmlns:tools="http://schemas.android.com/tools">
<TextView
android:text="Address"
android:textColor="#000000"
android:textSize="16sp"
grid:layout_column="0"
grid:layout_gravity="center_vertical"
grid:layout_row="0"
/>
<TextView
android:id="#+id/branch_list_item_address"
android:layout_width="0dp"
android:gravity="center"
android:maxLines="2"
tools:text="31 Fitzwilliam Manor, The Island"
android:textColor="#000000"
android:textSize="16sp"
grid:layout_column="1"
grid:layout_gravity="fill_horizontal"
grid:layout_row="0"
/>
<TextView
android:text="City"
android:textColor="#000000"
android:textSize="16sp"
grid:layout_column="0"
grid:layout_gravity="center_vertical"
grid:layout_row="1"
/>
<TextView
android:id="#+id/branch_list_item_city"
android:layout_width="0dp"
android:gravity="center"
android:maxLines="2"
tools:text="Dublin"
android:textColor="#000000"
android:textSize="16sp"
grid:layout_column="1"
grid:layout_gravity="fill_horizontal"
grid:layout_row="1"
/>
<TextView
android:text="Phone"
android:textColor="#000000"
android:textSize="16sp"
grid:layout_column="0"
grid:layout_gravity="center_vertical"
/>
<TextView
android:id="#+id/branch_list_item_phone"
android:layout_width="0dp"
android:gravity="center"
android:maxLines="2"
tools:text="01 456 7890"
android:textColor="#000000"
android:textSize="16sp"
grid:layout_column="1"
grid:layout_gravity="fill_horizontal"
grid:layout_row="2"
/>
<Button
android:id="#+id/branch_list_item_button_showmap"
style="?android:attr/borderlessButtonStyle"
android:text="#string/show_on_map"
android:textColor="#0645AD"
android:textSize="14sp"
grid:layout_column="0"
grid:layout_columnSpan="2"
grid:layout_columnWeight="1"
grid:layout_gravity="center"
grid:layout_row="4"/>
</android.support.v7.widget.GridLayout>
Expand List View to Full Height function
public static void setListViewHeightBasedOnChildren(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
// pre-condition
return;
}
int totalHeight = listView.getPaddingTop() + listView.getPaddingBottom();
for (int i = 0; i < listAdapter.getCount(); i++) {
View listItem = listAdapter.getView(i, null, listView);
if (listItem instanceof ViewGroup) {
listItem.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
}
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
listView.setLayoutParams(params);
}
And finally this is how the ListView is implemented in the Fragment:
mBranchListAdapter = new BranchListAdapter(getActivity());
mBranchListAdapter.setData(mShop.getBranchDetails());
mBranchListView.setAdapter(mBranchListAdapter);
MiscUtils.setListViewHeightBasedOnChildren(mBranchListView);
I have a RecyclerView which has a custom adapter that inflates a rowLayout. Each Row contains a CardView and in it some text and images as buttons. In particular i have a "like" button(ImageView) that as for now only is supposed to change imageResource on click.
I was able to set an onClicklistener in the onBindViewHolder() method and it does indeed register when i click the button, however it not only changes that buttons image but it also changes some of the other like buttons and also when i scroll down and then up again the first like button sometimes get reset.
Here is my adapter code.
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> implements View.OnClickListener {
private ArrayList<WallPost> wallPosts;
#Override
public void onClick(View v) {
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public View view;
public ViewHolder(View v) {
super(v);
view = v;
}
}
public MyAdapter(ArrayList<WallPost> wallPosts) {
this.wallPosts = wallPosts;
}
#Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_layout, parent, false);
ViewHolder vh = new ViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(ViewHolder holder, final int position) {
TextView name = (TextView) holder.view.findViewById(R.id.person_name);
TextView age = (TextView) holder.view.findViewById(R.id.person_age);
ImageView profile = (ImageView) holder.view.findViewById(R.id.person_photo);
TextView description = (TextView) holder.view.findViewById(R.id.description_text);
AppCompatImageView mainImage = (AppCompatImageView) holder.view.findViewById(R.id.main_image);
final ImageView likeButton = (ImageView) holder.view.findViewById(R.id.like_button);
name.setText(wallPosts.get(position).getName());
age.setText(wallPosts.get(position).getAge());
profile.setImageResource(wallPosts.get(position).getPhotoId());
description.setText(wallPosts.get(position).getDescription());
mainImage.setImageResource(wallPosts.get(position).getMainPhotoId());
likeButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
likeButton.setImageResource(R.drawable.favourite_red);
}
});
}
#Override
public int getItemCount() {
return wallPosts.size();
}
}
Here is the item layout
<?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"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/cv"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="10dp"
card_view:cardCornerRadius="5dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"
>
<de.hdodenhof.circleimageview.CircleImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:id="#+id/person_photo"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginRight="16dp"
android:src="#drawable/placeholderprofilepic"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/person_name"
android:text="Name"
android:layout_toRightOf="#+id/person_photo"
android:layout_alignParentTop="true"
android:textSize="30sp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/person_age"
android:text="19"
android:layout_toRightOf="#+id/person_photo"
android:layout_below="#+id/person_name"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/description_text"
android:text="This is the description of the image"
android:layout_below="#id/person_age"/>
<android.support.v7.widget.AppCompatImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/main_image"
android:src="#drawable/placeholderfoodimage"
android:layout_below="#+id/description_text"
android:elevation="4dp"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/like_button"
android:src="#drawable/favoruite_hollow"
android:layout_marginTop="10dp"
android:layout_below="#+id/main_image"
/>
</RelativeLayout>
</android.support.v7.widget.CardView>
This is due to recycling of views . You need to modify your getView() method and do these 2 things -
Modify your WallPost class to have a flag to set the like flag. Set this flag in onClickListener and update your wallPosts dataset .
wallPosts.get(position).setLike(true);
Set the like/not like image resource everytime based on the like flag you own in your list objects -
if(wallPosts.get(position).isLiked()){
likeButton.setImageResource(R.drawable.favourite_red);
} else{
likeButton.setImageResource(R.drawable.favoruite_hollow);
}
I have spent hours trying to figure this issue out and while I have come close, I am not getting the results I need. I have a messaging application that has a custom adapter and a listview with about 5 textviews. My issue is retrieving the text when a user long-presses on a message. After trying various methods, the closest I came was with:
mListView.setOnItemLongClickListener( new AdapterView.OnItemLongClickListener
(){
public boolean onItemLongClick(AdapterView<?> av, View v, int pos, long id) {
final String test = ((TextView)v).getText().toString();
Log.i(TAG, "Received: " + test);
return true;
}
});
The silly (read:frustrating) part about this code is that it works about 3-4 times successfully when clicked, however after that it force closes my application. The error I get is:
FATAL EXCEPTION: main
java.lang.ClassCastException: android.widget.RelativeLayout cannot be cast to android.widget.TextView
at android.widget.AbsListView.performLongPress(AbsListView.java:3347)
at android.widget.AbsListView$CheckForLongPress.run(AbsListView.java:3294)
at android.os.Handler.handleCallback(Handler.java:725)
The weird part is that I get the correct String of the message successfully the first few times, then it just doesn't want to work. After looking up the error, I tried cleaning the project multiple times, deleting the R.java file, and closing out Eclipse, but nothing has made a difference.
I have also tried using the position number of the messaging. The application never force closed when getting the position number of the message, however I couldn't get it to get the String that was attached to message at that location. The error was something about trying to convert from integer to string:
String test = ((EditText)av.getItemAtPosition(pos)).getText().toString();
My xml file consists of:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="horizontal" >
<LinearLayout
android:id="#+id/left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_margin="20dip"
android:background="#drawable/bubble_yellow"
android:gravity="left"
android:orientation="vertical"
android:visibility="invisible" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="right"
android:paddingBottom="1dip"
android:paddingLeft="15dip"
android:paddingRight="20dip"
android:paddingTop="1dip"
android:singleLine="false"
android:text="Large Text"
android:longClickable="true"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="#+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:gravity="right"
android:paddingRight="20dip"
android:longClickable="true"
android:text="TextView" />
</LinearLayout>
<LinearLayout
android:id="#+id/right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_margin="20dip"
android:background="#drawable/bubble_green"
android:orientation="vertical"
android:visibility="invisible" >
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="1dip"
android:paddingLeft="15dip"
android:paddingRight="20dip"
android:paddingTop="1dip"
android:singleLine="false"
android:longClickable="true"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="#+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:gravity="right"
android:longClickable="true"
android:paddingRight="20dip"
android:text="TextView" />
</LinearLayout>
</RelativeLayout>
Update 1: Added requested xml file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/background2"
android:orientation="vertical" >
<ListView
android:id="#+id/lv"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:divider="#null"
android:dividerHeight="0dp"
android:longClickable="true"
android:stackFromBottom="true" >
</ListView>
<View
android:layout_width="match_parent"
android:layout_height="1dp" />
<LinearLayout
android:id="#+id/sendMsgLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:layout_marginTop="20dp"
android:orientation="horizontal" >
<EditText
android:id="#+id/messageText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_weight="1"
android:hint="Type Message"
android:inputType="textCapSentences|textMultiLine"
android:textColor="#FFFFFF"
android:maxLines="3" >
<requestFocus />
</EditText>
<ImageView
android:id="#+id/imageSend"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:src="#drawable/send512" />
</LinearLayout>
</LinearLayout>
Update2: My adapter contains the following:
ViewHolder viewHolder;
MessageModel array = data.get(position);
if (convertView == null) {
viewHolder = new ViewHolder();
convertView = inflater.inflate(R.layout.message_item, null);
viewHolder.left =(LinearLayout)convertView.findViewById(R.id.left);
viewHolder.right =(LinearLayout)convertView.findViewById(R.id.right);
viewHolder.txt1 = (TextView) convertView
.findViewById(R.id.textView1);
viewHolder.txt3 = (TextView) convertView
.findViewById(R.id.textView3);
viewHolder.txt2 = (TextView) convertView
.findViewById(R.id.textView2);
viewHolder.txt4 = (TextView) convertView
.findViewById(R.id.textView4);
convertView.setTag(viewHolder);
Update 3: Tried my best to follow #MDragon00's advice, unfortunately my app is still crashing when long pressing. I now have:
mListView.setOnItemLongClickListener( new AdapterView.OnItemLongClickListener
(){
public boolean onItemLongClick(AdapterView<?> av, View v, int pos, long id) {
TextView textView1 = (TextView) v.findViewById(R.id.textView1);
TextView textView2 = (TextView) v.findViewById(R.id.textView2);
TextView textView3 = (TextView) v.findViewById(R.id.textView3);
TextView textView4 = (TextView) v.findViewById(R.id.textView4);
View.OnLongClickListener listener = new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
TextView textView = (TextView) v;
String text = textView.getText().toString();
Log.i(TAG, "Text Selected = " + text);
return false;
}
};
textView1.setOnLongClickListener(listener);
textView2.setOnLongClickListener(listener);
textView3.setOnLongClickListener(listener);
textView4.setOnLongClickListener(listener);
return true;
}
});
}
The description of what each parameter does in onItemLongClick: http://developer.android.com/reference/android/widget/AdapterView.OnItemLongClickListener.html
The issue here is that av is the entire ListView, while v is the entire row. Your row doesn't simply consist of a TextView, so you can't cast it to a TextView. In other words,
final String test = ((TextView)v).getText().toString();
isn't a good idea as the parent view is a RelativeLayout. A better solution would be to do the following:
TextView textView = (TextView) v.findViewById(R.id.idOfTextView);
String text = textView.getText().toString();
As a small side suggestion, it sounds like you want to simply click on the item, not long click it. Use an OnItemClickListener instead of a OnItemLongClickListener if it suits your needs.
Edit:
According to your comments, the user will click/tap on a certain TextView out of several TextViews within some abstract row, and you want to get one of those four TextViews.
To do so, you'll need a new listener on each TextView. I can't give an exact answer without seeing your adapter, but when you inflate/get the row view to give to the ListView in the adapter, set an OnClickListener to the TextViews. For example with some pseudo-code:
// Get the textViews, to assign a listener to them
TextView textView1 = (TextView) v.findViewById(R.id.textView1);
TextView textView2 = (Textview) v.findViewById(R.id.textView2);
..... // Etc and so on
// Create this listener anywhere, including via making the adapter/class
// implement the listener and passing it in instead
View.OnClickListener listener = new View.OnClickListener(
#Override
public void onClick(View v) {
// Get the view as a TextView, as this will only be used
// with TextViews, so the only view to be passed
// will be Textviews
TextView textView = (TextView) v;
// Do whatever with that text, or however you want to use the view
String text = textView.getText().toString();
someFunction(text);
}
);
textView1.setOnClickListener(listener);
textView2.setOnClickListener(listener);
..... // Etc and so on
Now then, if you need the exact row that was clicked AND the text from an exact TextView, then you'll need to use both of the listeners [ie, one on the ListView and ones on the TextViews] to get the appropriate data.
Edit Hopefully Final:
public class TestAdapter extends BaseAdapter {
Context mContext;
public TestAdapter (Context context, Data someData) {
this.mContext = context;
// Set up the data for your listView however
}
#Override
public int getCount() {
return howManyRows;
}
#Override
public Object getItem(int position) {
return objectAtPosition;
}
#Override
public long getItemId(int position) {
return 0;
} // Unnecessary, unless using databases
// The listener for the textViews, feel free to use different listeners
View.OnClickListener TextViewListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
// Get the view as a TextView, as this will only be used
// with TextViews, so the only view to be passed
// will be Textviews
TextView textView = (TextView) v;
// Do whatever with that text, or however you want to use the view
String text = textView.getText().toString();
someFunction(text);
}
};
// Using the efficient pattern for recycling the views rather than using
// findViewById repeatedly
public static class ViewHolder{
public TextView textView1;
public TextView textView2;
public TextView textView3;
public TextView textView4;
// And any other view that's part of the row view that you need
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = null;
ViewHolder holder;
if(convertView == null) {
// Then gotta set up this row for the first time
LayoutInflater inflater =
(LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.row_layout.xml, parent, false);
// Create a ViewHolder to save all the different parts of the row
holder = new ViewHolder();
holder.textView1 = (TextView) row.findViewById(R.id.textView1);
holder.textView2 = (TextView) row.findViewById(R.id.textView2);
holder.textView3 = (TextView) row.findViewById(R.id.textView3);
holder.textView4 = (TextView) row.findViewById(R.id.textView4);
// Make the row reuse the ViewHolder
row.setTag(holder);
}
else { // Otherwise, use the recycled view
row = convertView;
holder = (ViewHolder) row.getTag();
}
// Set the current row's Textview onClickListeners
// Note: You MAY be able to only set these once- feel free to set that
holder.textView1.setOnClickListener(TextViewListener);
holder.textView2.setOnClickListener(TextViewListener);
holder.textView3.setOnClickListener(TextViewListener);
holder.textView4.setOnClickListener(TextViewListener);
// Set up the rest of the views however you need
/*.....
......
*/
return row;
}
}
getItemAtPosition(pos) returns the view used as each of the item in the listView. According to your xml, the root element is RelativeLayout, so this method will return an RelativeLayout, not a TextView.
what you can do is:
String test = ((TextView)((View)av.getItemAtPosition(pos)).findViewById(R.id.textView1))
.getText().toString();
I'm trying to use a custom adapter for a list. This list has 2 types of rows but I only use one layout (keeping the items that I don't need with visibility set to View.GONE). However I keep getting a Class cast exception when trying to access the editbox-style row. I have very little experience with custom adapters. Your help is really appreciated :D
Here's the code(I removed the setonclicklisteners to keep it short):
public class SubEventListAdapter extends ArrayAdapter<MobileSubEvent>
{
private ArrayList<MobileSubEvent> _items;
private Context _context;
public SubEventListAdapter(Context context, ArrayList<MobileSubEvent> items)
{
super(context, R.layout.view_select_event_item3, items);
this._items = items;
this._context = context;
}
static class ViewHolder
{
TextView text;
ImageButton imagebutton;
ImageView check;
EditText editText;
Button button;
}
#Override
public int getCount()
{
return this._items.size();
}
#Override
public View getView(final int position, View convertView, ViewGroup parent)
{
View v = convertView;
final ViewHolder viewHolder;
final MobileSubEvent event = _items.get(position);
if (v == null)
{
LayoutInflater _inflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = _inflater.inflate(R.layout.view_select_event_item3, null);
viewHolder = new ViewHolder();
viewHolder.imagebutton = (ImageButton) v.findViewById(R.id.ibNext);
viewHolder.text = (TextView) v.findViewById(R.id.EVENT);
viewHolder.check = (ImageView) v.findViewById(R.id.ivCheck);
viewHolder.button = (Button) v.findViewById(R.id.bScanOrSign);
viewHolder.editText = (EditText) v.findViewById(R.id.etInput);
v.setTag(viewHolder);
} else
{
v = convertView;
viewHolder = (ViewHolder) v.getTag(); //here is where the class cast exception occurs
}
if (viewHolder.text != null)
viewHolder.text.setText(this._items.get(position).get_description());
v.setTag(this._items.get(position));
...
return v;
}
Logcat:
view_select_event_item3:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#android:color/transparent"
android:padding="5dip" >
<ImageView
android:id="#+id/ivCheck"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_gravity="center_vertical"
android:background="#drawable/check"
android:focusable="false"
android:visibility="invisible" />
<TextView
android:id="#+id/EVENT"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/ivCheck"
android:background="#android:color/transparent"
android:padding="5dp"
android:text="Sample text"
android:textSize="20sp"
android:textStyle="bold"
android:visibility="visible"
/>
<EditText
android:id="#+id/etInput"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="130dp"
android:maxWidth="165dp"
android:layout_toRightOf="#id/ivCheck"
android:background="#android:drawable/editbox_background"
android:padding="5dp"
android:hint="Hint text"
android:singleLine="true"
android:text=""
android:textSize="20sp"
android:visibility="invisible"
/>
<Button
android:id="#+id/bScanOrSign"
android:layout_width="62dp"
android:layout_height="32dp"
android:layout_gravity="center_vertical"
android:layout_toLeftOf="#id/ibNext"
android:text="Scan"
android:visibility="invisible"
/>
<ImageButton
android:id="#+id/ibNext"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_gravity="right|center_vertical"
android:background="#drawable/right"
android:visibility="invisible" />
</RelativeLayout>
Try this in the getView, check for class name of the convertView object (The View Holder object) if it does not matches class name of your ViewHolder (in my case it is VisitsListViewHolder) - set it as null so new instance is created for the view holder
if(convertView != null)
{
String className = convertView.getTag().getClass().getName();
if(!className.equalsIgnoreCase("VisitsListViewHolder"))
{
convertView = null;
}
}