I have an Adapter with rows from View, and each row contains some information. I am trying to make a Actioncall, so if someone clicks the row with the phone number, then it starts dialing. This work but the problem is I don't get the phone number from the TextView, I get a random number.
This is the code
The function for when the users clicks on the phone number
private void TelSelected(TextView obj)
{
mTelefonNumar = FindViewById<TextView>(Resource.Id.textView3);
Toast.MakeText(this, mTelefonNumar.ToString(), ToastLength.Long).Show();
string stringtelefon = mTelefonNumar.ToString();
var uri = Android.Net.Uri.Parse("tel:" + stringtelefon);
var intent = new Intent(Intent.ActionCall, uri);
StartActivity(intent);
}
The Toast returns this android.widget.TextView{2e4a768b V.ED..C...... 0, 198-698,264 #7f0b0055 app:id/textView3}
And the Intent.ActionCall, calls this number 247 680 but the number another one/
public override View GetView(int position, View convertView, ViewGroup parent)
{
View row = convertView;
if (row == null)
{
row = LayoutInflater.From(mContext).Inflate(mLayout, parent, false);
}
row.FindViewById<TextView>(Resource.Id.textView3).Text = Linfo[position].TelClient;
row.FindViewById<TextView>(Resource.Id.textView3).Click += InformatiiListAdapter_Click;
return row;
}
void InformatiiListAdapter_Click(object sender, EventArgs e)
{
//He clicked on the Telephone Number
mNrApasat.Invoke((TextView)sender);
}
.ToString() on a TextView will show information about the View, not the text it displays. The following would fix it :
((TextView)sender).Text;
instead of
((TextView)sender).ToString();
An cleaner way (because the displayed text might not always be exactly a usable phone number) would be to store the number in the row 'tag' property (in which you can store anything).
And to set the event on the row.
public override View GetView(int position, View convertView, ViewGroup parent)
{
View row = convertView;
if (row == null)
{
row = LayoutInflater.From(mContext).Inflate(mLayout, parent, false);
}
row.SetTag(Linfo[position].TelClient);
row.Click += InformatiiListAdapter_Click;
row.FindViewById<TextView>(Resource.Id.textView3).Text = (string)row.GetTag();
return row;
}
void InformatiiListAdapter_Click(object row, EventArgs e)
{
//He clicked on the Telephone Number
string phoneNumber = (string)(((View)row).GetTag());
// do stuff with the phone number
}
also, on a side note, FindViewByID is very expensive processing-wise, avoid doing it too much, you might want to look into the ViewHolder pattern, it'll make scrolling smoother
also, it would be better to set the item click listener on the list itself, instead of registering an event on each convertView.
Related
I have a listview having height width both is "match-parent" which gets populated using adapter and the "position" which I am getting in getview is correct but viewholder.image.click event always give position according to visible area. Like if I change the listview height to some static dp then the visible area increase to 4 element 0,1,2,3 after that it again show 0,1,2,3 which should be 5,6...
This problem resolve on creating the convertView every time which is actually a wrong approach.
public override View GetView(int position, View convertView, ViewGroup parent)
{
MyDealViewHolder viewHolder = null;
View rowView = convertView;
Toast.MakeText (baseActivity, string.Format (position.ToString ()), ToastLength.Short).Show ();
if (rowView == null)
{
rowView = baseActivity.LayoutInflater.Inflate(Resource.Layout.DealListItem, parent, false);
viewHolder = new MyDealViewHolder();
viewHolder.LikeImage= rowView.FindViewById<ImageView>(Resource.Id.imgDealImage);
viewHolder.LikeImage.Click += delegate(object sender, EventArgs e) {
Toast.MakeText (baseActivity, string.Format (position.ToString ()), ToastLength.Short).Show ();
viewHolder.LikeImage.SetImageResource (Resource.Drawable.heart_red_icon);
};
rowView.Tag = viewHolder;
}
else
{
viewHolder= (MyDealViewHolder)rowView.Tag;
}
return rowView;
}
Here both toast giving different position. First one is correct and second one is acc to visible area of listview
Thanks
I have an app whereby i am accessing a RESt webservice and presenting the request in listview (ListFrragment). It is essentially a list of articles. What i am trying to achieve is when a user clicks on an item in listview (expands article in ViewPager) is stays highlighted (indicating that the article has been read). The next time the user reloads this listview, all the item that have been read is still highlighted.
I have have created a boolean variable "read" for each article. When a user clicks on this item, the "read" variable is assigned to TRUE. Then in the custom Adapter(extends arrayAdpater), i assign the background colour (in this case green) in getView for articles whose "read" value is TRUE. This does work, but what i am finding is that other items in the listview is also randomly turning green when i start to scroll up and down the listview without actually clicking on it. I'm really stuck as i do not understand what is happening. Please can someone advise?
public void onListItemClick(ListView l, View v, int postion, long id) {
Article a = ((toReadListAdapter) getListAdapter()).getItem(postion);
// set read attribute to TRUE
a.setRead(true);
saveToReadList(toReadList);
// Open via ViewPager
Intent i = new Intent(getActivity(), ReadingList_PagerActivity.class);
startActivity(i);
Customer Adapter:
// Defining custom adapter
private class toReadListAdapter extends ArrayAdapter<Article> {
public toReadListAdapter(ArrayList<Article> listToRead) {
super(getActivity(), 0, listToRead);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = getActivity().getLayoutInflater().inflate(R.layout.new_articlelistfragment, null);
}
Article en = getItem(position);
Log.d(TAG, "Showing articles: " + position + "/ pmid: " + en.getId());
Log.e(TAG, "isRead value: " + en.isRead());
if(en.isRead() == true){
convertView.setBackgroundColor(Color.parseColor("#C8E6C9"));
}
......
return convertView;
Inside the getView
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = getActivity().getLayoutInflater().inflate(R.layout.new_articlelistfragment, null);
}
Article en = getItem(position);
if(en.isRead() == true){
convertView.setBackgroundColor(Color.parseColor("#C8E6C9"));
}
else{
// put the default color
convertView.setBackgroundColor( );
}
......
return convertView;
}
You are not applying the default color. Add an else statement in get view method
I have a listview and it's scrolable. I have few listview items and it's pulled from database. My problem is, each listview items have a button and i've setOnclickListener to the button inside getView. Now let's say there's 5 items and i tap on button for item number 1, the position is 0 and when i scroll to the end of the list, i can see the button for item number 5 is clicked. When i scroll till middle of the list, sometimes the button randomly clicked and i can see from my logcat, the particullar button's position is 0. How come?
Here is my getView' code
public View getView(final int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.newsfeed_layout, parent, false);
}
final Button btnLike = (Button) v.findViewById(R.id.buttonLike);
btnLike.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String buttonText = btnLike.getText().toString();
if(buttonText.equals("LIKE")){
Toast.makeText(postedItems.this, "Liked This item" + position, Toast.LENGTH_SHORT).show();
btnLike.setPadding(4,0,12,0);
btnLike.setText("UNLIKE");
btnLike.setTextColor(Color.parseColor("#ffffff"));
btnLike.setBackgroundResource(R.drawable.likedredbutton);
}else if(buttonText.equals("UNLIKE")){
Toast.makeText(postedItems.this, "Unlike This Item" + position, Toast.LENGTH_SHORT).show();
btnLike.setPadding(4,0,20,0);
btnLike.setText("LIKE");
btnLike.setTextColor(Color.parseColor("#737373"));
btnLike.setBackgroundResource(R.drawable.cornerstyledbutton);
}
}
});
return v;
}
First, to understand the problem: this occurs because ListView reuses views as you scroll, to improve performance. That's the explanation for the convertView parameter.
Because of this, you need to make sure that whatever state you want to store for each item is stored in the adapter itself or wherever you store its backing data -- and that when you implement getView(), the UI is fully updated to reflect this data (since it will have whatever properties you set on it the last time it was used).
In this case, you need to store whether each item is "liked" or "unliked". And then, always set the properties of btnLike to reflect this before returning.
As an example, your code would have to be more or less like this:
public View getView(final int position, View convertView, ViewGroup parent)
{
View v = convertView;
if (v == null) {
LayoutInflater vi = ...;
}
final Button btnLike = (Button) v.findViewById(R.id.buttonLike);
if (isLiked(position))
setButtonAsUnlike(btnLike);
else
setButtonAsLike(btnLike);
btnLike.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
if (!isLiked(position))
{
// Not liked before, so like now.
setLiked(position, true); // store this value.
setButtonAsUnlike(btnLike); // the button is now "unlike"
}
else
{
// Liked before, unliked now.
setLiked(position, false); // store this value.
setButtonAsLike(btnLike); // the button is now "like"
}
}
});
return v;
}
where isLiked(position) queries the data, setLiked(position, boolean) updates it, and setButtonAsLike(Button) and setButtonAsUnlike(Button) update the visual properties of the Button as you are doing now.
I'm trying to put a text above the Image in grid view but i'm not able to do this.
My app will have a gridview with pictures, and when I click over the each picture, I have put the quantity of clicks above of this image in real time.
I create an Adapter and My images are appearing on my Activity.
How I can do this, on Android?
You can do it through the onItemClickListener
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if (view == null) {
// Create the view here
Holder tag = new Holder();
tag.textView = (TextView) view.findViewById(textViewId);
view.setTag(tag);
}
if (counts[position] == 0) {
tag.textView.setVisibility(View.INVISIBLE);
else {
tag.textView.setVisibility(View.VISIBLE);
tag.textView.setText("" + counts[position]);
}
...
}
gridView.setAdapter(adapter);
int[] counts = new int[// item count];
gridView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Holder tag = (Holder) view.getTag();
if (tag != null) {
counts[position] = counts[position] + 1;
tag.textView.setText("" + counts[position]);
}
}
}
You need to track the count outside as a member variable.
In your adapter (or wherever appropriate to store this data depending on how long lived this click data should be), add some sort of data structure to maintain the number of clicks per position. In your adapter's getView(), you should set the text at that position according to the number of clicks you have stored in your data structure.
In your list item click listener, increment the click count in your data structure, and call notifyDatasetChanged() on your Adapter.
i've built a chat application.
inside my chat messages Activity, i have a ListView which shows all text message.
inside each text messages i have a TextView which will by default write "Sending..." and i want it to be updated after the message is sent.
inside each ChatMessage object i have a sent and time property. if sent is true i will show in the TextView the time, and if it's false i will write "Sending" as written above.
when i'm sending a new message, i'm adding a new view to the ListView adapter, and from some reason it shows that message was sent although it didn't... can't really understand why.
this is my ArrayAdapter's getView() and holder class:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
ChatMessage chatMessage = chatMessagesArrayList.get(position);
ChatMessageHolder chatMessageHolder = null;
if (row == null)
{
if (chatMessage.getSenderId() == app.getFacebookCurrentUser().getId())
row = LayoutInflater.from(context).inflate(layoutResourceId, null);
else
row = LayoutInflater.from(context).inflate(R.layout.chat_green, null);
chatMessageHolder = new ChatMessageHolder();
chatMessageHolder.message = (TextView) row.findViewById(R.activity_chat.message);
chatMessageHolder.sentTime = (TextView) row.findViewById(R.activity_chat.sent_time);
chatMessageHolder.isSent = chatMessage.isSent();
row.setTag(chatMessageHolder);
}
else
{
chatMessageHolder = (ChatMessageHolder) row.getTag();
}
chatMessageHolder.message.setText(chatMessage.getMessage());
if (chatMessageHolder.isSent)
chatMessageHolder.sentTime.setText(app.getDateTime(chatMessage.getTime()));
return row;
}
private static class ChatMessageHolder
{
TextView message, sentTime;
boolean isSent = false;
}
i can't really understand why doesn't it write the time or "Sending..." according to the isSent boolean flag...
It's because the ListView recycles previous views (that's what the convertView variable is). Likely it's recycling another view that was already set to "Sent", and you're never handling the alternate case where chatMessagerHolder.isSent is false. You should avoid setting chatMessageHolder.isSent = chatMessage.isSent(); until after that first if-else block. That first if-else should just be to initialize the view or recycle the object. Also, when you check if(chatMessageHolder.isSent) you should also handle what the TextView should say if that is false (i.e. in a followup else statement) since the views are recycled.