I have a recyclerview which has some cards inside it. Each card has a button and a listview inside it. I want listview to appear only when button is clicked. Initially I set onClickListener for button and onTouchListener for recyclerview but it didn't work for button. It only identified recyclerview listener, not button click listener. How can I set both listeners independently? Such that recyclerview touchlistener doesn't interfere in button click listener.
Secondly, I have two adapter here- one for listview and one for recyclerview. Listview adapter is called inside recyclerview adapter. If I call listview adapter when button is clicked, context is not found which I initially passed in recyclerview adapter.
This is recyclerview adapter:
public class ChatAdapter extends RecyclerView.Adapter<ChatAdapter.ViewHolder>{
static Context activity;
ArrayList<ChatModel> chats = new ArrayList<ChatModel>();
boolean visible = false;
public ChatAdapter(Context a,ArrayList<ChatModel> _chats){
activity = a;
chats = _chats;
}
public static class ViewHolder extends RecyclerView.ViewHolder{
ImageButton expand;
ListView comments;
public ViewHolder(View v) {
super(v);
expand = (ImageButton)v.findViewById(R.id.chat_open);
comments = (ListView)v.findViewById(R.id.commentList);
}
}
#Override
public int getItemCount() {
// TODO Auto-generated method stub
if(chats.size()<=0)
return 0;
return chats.size();
}
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
// TODO Auto-generated method stub
try{
holder.comments.setVisibility(View.GONE);
holder.expand.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("TAG","Expand clicked");
if (visible) {
visible = false;
holder.comments.setVisibility(View.GONE);
} else {
visible = true;
CommentsAdapter adap = new CommentsAdapter(activity, chats.get(position).getCommentList());
holder.comments.setAdapter(adap);
holder.comments.setVisibility(View.VISIBLE);
}
}
});
}catch(Exception e){
e.printStackTrace();
}
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int arg1) {
// TODO Auto-generated method stub
View v = LayoutInflater.from(parent.getContext()).inflate(
R.layout.chat_item_card, parent, false);
ViewHolder vh = new ViewHolder(v);
return vh;
}
}
This is listview adapter:
public class CommentsAdapter extends ArrayAdapter<CommentModel>{
public Context context;
ArrayList<CommentModel> data;
CommentModel detail;
public CommentsAdapter(Context a, ArrayList<CommentModel> d) {
super(a, R.layout.comment_item, d);
context = a;
data=d;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
detail = data.get(position);
View vi = inflater.inflate(R.layout.comment_item, parent, false);
TextView comment = (TextView) vi.findViewById(R.id.comment);
comment.setText(detail.getComment());
return vi;
}
}
This is cardview layout (row of recyclerview):
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_margin="5dp"
android:background="#e6e6e6"
card_view:cardCornerRadius="5dp"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#272626">
<ImageButton
android:layout_width="30dp"
android:layout_height="30dp"
android:background="#drawable/expand"
android:id="#+id/chat_open"
android:layout_marginRight="4dp"
android:padding="2dp"
android:clickable="true"/>
<ListView
android:layout_width="match_parent"
android:layout_height="150dp"
android:layout_below="#+id/chat_open"
android:layout_marginTop="5dp"
android:layout_alignLeft="#+id/chat_open"
android:layout_marginRight="4dp"
android:layout_marginBottom="3dp"
android:id="#+id/commentList">
</ListView>
</RelativeLayout>
</android.support.v7.widget.CardView>
Related
I have an ListView with BaseAdapter now I just make some listener to item when I click on item I show some hidden view in item.
Every time I click on some item, I show the hidden view or hide them if views are visible. But the problem I face is that I want to hide the other visible item when the I show a new item.
Here I click on some item and its shows the message date and detail:
Now when I click on other items, I want to hide the first one and show the second, like this:
But here in my code when I click on other item its of course will not hide the previous view. How can I do this trick ?
Simply keep a reference to the last view that was clicked, let's call it mLastViewShown;
new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (mLastViewShown != null)
hideDetails();
mLastViewShown = view;
showDetails();
}
};
Now you have a variable to hide the details from the last user click.
So you want to hide all item's additional field when you click on some other item. In addition to this you also want to toggle visibility of an item's additional view on click on same item.
Here is your main activity:
public class MainActivity extends AppCompatActivity {
private List<ListData> list=new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//get the toolbar instance
handleListClick();
list.add(new ListData("George","Surgeon"));
list.add(new ListData("Nancy","Dentist"));
list.add(new ListData("Henry","Nurse"));
}
private void handleListClick() {
ListView listView=findViewById(R.id.listView);
final CustomBaseAdapter customBaseAdapter=new CustomBaseAdapter(this,list);
listView.setAdapter(customBaseAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
customBaseAdapter.setCurrentSelected(position);
customBaseAdapter.notifyDataSetChanged();
}
});
}
}
Here is your custom base adapter:
public class CustomBaseAdapter extends BaseAdapter {
private List<ListData> myList = new ArrayList<ListData>();
private LayoutInflater inflater;
private Context context;
private int previousSelected=-1;
public CustomBaseAdapter(Context context, List<ListData> myList) {
this.myList = myList;
this.context = context;
inflater = LayoutInflater.from(this.context);
}
public void setCurrentSelected(int currentSelected){
if(previousSelected==currentSelected)
previousSelected=-1;
else
previousSelected=currentSelected;
}
#Override
public int getCount() {
return myList.size();
}
#Override
public ListData getItem(int position) {
return myList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
MyViewHolder mViewHolder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.row_item, parent, false);
mViewHolder = new MyViewHolder(convertView);
convertView.setTag(mViewHolder);
} else {
mViewHolder = (MyViewHolder) convertView.getTag();
}
ListData currentListData = getItem(position);
mViewHolder.tvMain.setText(currentListData.getMainText());
if(previousSelected==position){
mViewHolder.tvAdditional.setVisibility(TextView.VISIBLE);
mViewHolder.tvAdditional.setText(currentListData.getAdditionalText());
}else{
mViewHolder.tvAdditional.setVisibility(TextView.GONE);
}
return convertView;
}
private class MyViewHolder {
TextView tvMain, tvAdditional;
public MyViewHolder(View item) {
tvMain = (TextView) item.findViewById(R.id.main_text);
tvAdditional = (TextView) item.findViewById(R.id.additional_text);
}
}
}
Here is your ListData:
public class ListData {
private String mainText;
private String additionalText;
public ListData(String mainText, String additionalText) {
this.mainText = mainText;
this.additionalText = additionalText;
}
public String getMainText() {
return mainText;
}
public void setMainText(String mainText) {
this.mainText = mainText;
}
public String getAdditionalText() {
return additionalText;
}
public void setAdditionalText(String additionalText) {
this.additionalText = additionalText;
}
}
Here is your row_item.xml layout file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/main_text"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/additional_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone" />
</LinearLayout>
Here is activity_main.xml layout file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.dexter.stackoverflow.MainActivity">
<ListView
android:id="#+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
I have created a custom ListView, where the layout is definited in two XML, one which contain the definition of the ListView in a layout
For example activity_main.xml :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:id="#+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="#+id/myListView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
</RelativeLayout>
The other part of the XML is in another file, for example custom_list.xml:
<?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="wrap_content"
android:background="#drawable/list_row_selector">
<LinearLayout
android:id="#+id/photoList"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/takePhoto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
android:src="#drawable/camera"/>
</LinearLayout>
</RelativeLayout>
In my activity i have declared actvivity_main.xml as main layout:
public class MainActivity extends AppCompatActivity{
private List<CustomRow> imageList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.cmp_details);
/* Initialization structures, variable, ecc */
ListView lv = (ListView) findViewById(R.id.imageList);
adapter = new CustomList(this, imageList);
lv.setAdapter(adapter);
}
/* Add element list in ListView */
private void addList(int idC){
CustomRow cr = new CustomRow();
cr.setId(idC);
cr.setTitle("xxx "+ (idC+1));
cr.setThumbnailUrl(R.drawable.no_image);
imageList.add(cr);
adapter.notifyDataSetChanged();
}
private void takePhoto(){
//Do something
}
}
Custom List.java
public class CustomList extends BaseAdapter {
private Activity activity;
private LayoutInflater inflater;
private List<CustomRow> ListItem;
private ImageLoader imageLoader = AppController.getInstance().getImageLoader();
public CustomList(Activity activity, List<CustomRow> listPhotoItems) {
this.activity = activity;
this.ListItem = listPhotoItems;
}
#Override
public int getCount() {
return ListItem.size();
}
#Override
public Object getItem(int location) {
return ListItem.get(location);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (inflater == null)
inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null)
convertView = inflater.inflate(R.layout.custom_list, null);
if (imageLoader == null)
imageLoader = AppController.getInstance().getImageLoader();
ImageView thumbNail = (ImageView) convertView.findViewById(R.id.thumbnail);
TextView title = (TextView) convertView.findViewById(R.id.title);
CustomRow m = ListItem.get(position);
thumbNail.setImageResource(m.getThumbnailUrl());
title.setTag(m.getId());
title.setText(m.getTitle());
return convertView;
}
}
Now I have to implement the OnClickListener of takePhoto, how I can do this ?
How I can bind onClickListener from the activity ?
I tried this solution but not work...
you could use setonitemclicklistener
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
imageList.get(position); // here you will get the clicked item from
//your imagelist and you can check by getting a title by using this
String title= imageList.get(position).getTitle();
if(title.equals("you title to match")){
//do your action or you can get a particular position and click there
}
}
});
This is the final solution, I have solve my problem with this code:
lv.setAdapter(adapter);
lv.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
View convertView = v;
final ImageView photo = (ImageView) convertView.findViewById(R.id.takePhoto);
photo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(CmpDetails.this, "Click", Toast.LENGTH_SHORT).show();
}
});
return false;
}
});
tv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
list.get(position);
String str= list.get(position).getTitle();
if(str.equals("")){
//put your code here
}
}
});
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
TextView tv = (TextView) v.findViewById(R.id.textView1);
tv.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//do your code on click event
}
});
return super.getView(position, convertView, parent);
}
I am currently working on a very basic android application and have encountered an obstacle I cannot solve on my own.
In my application I want to have a start screen with a ListView. In each Line of this ListView there should be a Button and a TextView. I want to have approximately 5 Lines. When you click on each of the Button you should be able to get to different Activities. How do I do that? I read something about adapters but I am still not sure how to build this.
Here's my xml code for the TextView and the Button:
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/textView"
android:id="#+id/rl01">
<TextView
android:layout_width= "wrap_content"
android:layout_height="50dp"
android:id="#+id/text01"
android:text="hello"
android:textSize="24dp"
android:textColor="#color/abc_search_url_text_normal"
android:paddingRight="#dimen/activity_horizontal_margin"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_toRightOf="#id/text01"
android:text="Press Me!"
/>
</RelativeLayout>
The xml layout you have posted, will be used as each listview item.
Step 1:
Create a class which extends BaseAdapter;
public class CustomAdapter extends BaseAdapter
{
Context con;
String[] data;
public CustomAdapter (Context context, String[] data)
{
this.con = context;
this.data = data;
}
#Override
public int getCount() {
return data.length;
}
#Override
public Object getItem(int position) {
return data[position];
}
#Override
public long getItemId(int position) {
return 0;
}
//this method will be called for every item of your listview
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) con.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView= inflater.inflate(R.layout.customview, parent, false);
TextView text = (TextView) view.findViewById(your text view id); //recognize your view like this
text.setText(data[position]);
return convertView;
}
}
Step 2:
In your activity, recognize your listview:
yourListViewReference = (ListView) findViewById(R.id.your_list_view_id);
And initialize String array:
String[] data = {"item 1", "item2", "item3"}; //how many items you want
And then create instance of custom adapter you created, and set it to listview:
CustomAdapter ad = new CustomAdapter(this, data);
yourListViewReference.setAdapter(ad);
And sorry for my bad english. I am actually working on it.
This article from Vogella is really useful for what you want to do.
Basically, you'll create an Adapter that extends the BaseAdapter class as follows:
public class Adapter extends BaseAdapter {
private List<Item> mItems;
private Context mContext;
public EventAdapter(Context context, List<Event> items) {
mContext = context;
mItems = items;
}
public View getView(int position, View convertView, ViewGroup parent) {
// This recycles your view and prevents constant inflation, which can really hit your performance.
View rowView = convertView;
if (rowView == null) {
ViewHolder viewHolder = new ViewHolder();
rowView = inflater.inflate(R.layout.yourLayout, parent, false);
viewHolder.text = (TextView) rowView.findViewById(R.id.yourTextViewId);
viewHolder.button = (Button) rowView.findViewById(R.id.yourButtonId);
rowView.setTag(viewHolder);
}
ViewHolder holder = (ViewHolder) rowView.getTag();
// Get the correct item by position
Item item = item.get(position);
// Update the row layout with your item data
holder.text.setText(item.text);
holder.button.setButton(item.button);
// Return your row view
return rowView;
}
#Override
public int getCount() {
return mItems.size();
}
#Override
public Object getItem(int position) {
}
#Override
public long getItemId(int position) {
}
static class ViewHolder {
public TextView text;
public Button button;
}
Afterwards you just need to set this adapter to your ListView or RecyclerView by doing
listView.setAdapter(new Adapter(this, items));
I would write a simple example:
You dont need a button in listview row, just implement onItemClick();
main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<ListView
android:id="#+id/custom_list"
android:longClickable="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
list_row.xml
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/textView"
android:id="#+id/rl01">
<TextView
android:layout_width= "wrap_content"
android:layout_height="50dp"
android:id="#+id/text01"
android:text="hello"
android:textSize="24dp"
android:textColor="#color/abc_search_url_text_normal"
android:paddingRight="#dimen/activity_horizontal_margin"
/>
MainActivity.java
oncreate()
{
....
lv1 = (ListView) result.findViewById(R.id.custom_list);
String[] listdata = {"txt1", "txt2", "txt3", "txt4", "txt5"};
ListAdapter listAdapt = new ListAdapter(this, listdata );
lv1.setAdapter(listAdapt);
lv1.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> a, View v, int position, long id) {
//do ur work here when list row selected
}
});
..
}
ListAdapter.java
public class ListAdapter extends BaseAdapter {
String[] listData;
private LayoutInflater layoutInflater;
public CustomListAdapter(Context aContext, String[] listData) {
this.listData = listData;
layoutInflater = LayoutInflater.from(aContext);
}
#Override
public int getCount() {
return listData.size();
}
#Override
public Object getItem(int position) {
return listData.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.list_row, null);
TextView tv1 = (TextView)convertView.findViewById(R.id.text01);
tv1.setText(listData.[position]);
return convertView;
}
I have custom ListView layout with a TextView and CheckBox. Everything works fine.
What I want is, when I click on the CheckBox or TextView (on the single View from ListView) both should behave like one object. (I can click on the CheckBox and it does not effect the TextView and TextView has no effect on CheckBox.) Code has no problem.
I have implemented all possible solutions but problem is still there. (One single click on every object of list should consider ONE COMPLETE CLICK for complete row.) I hope I explained very well.
MAIN ACTIVITY
package com.example.smsplanner;
public class SMSPlanner extends ListActivity {
ListView contactsListView;
private String TAG = "SMSPlanner"; CheckBox check;
int count;
List<ContactInfo> list = new ArrayList<ContactInfo>();
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
ph = new String[3];
phType = new String[3];
LoadContactListFromPhone();
ContactsAdapter contactadAdapter = new ContactsAdapter(this, list);
getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
setListAdapter(contactadAdapter);
}
#Override
public void onListItemClick(ListView parent, View v, int position, long id)
{
TextView tx =(TextView)v.findViewById(R.id.firstname);
TextView ph =(TextView)v.findViewById(R.id.phone);
Toast.makeText(this, tx.getText().toString() + " " + ph.getText().toString() + " " + Integer.toString(count), Toast.LENGTH_SHORT).show();
}
final class ContactHolder{
TextView txtviewfirstname;
CheckBox chkselected;
TextView txtviewphone;
}
void LoadContactListFromPhone()
{
loadlistandreturns();
}
void call()
{
Toast toast = Toast.makeText(this, "Called...",Toast.LENGTH_LONG);
toast.show();
}
}
CUSTOM ADAPTER
public class ContactsAdapter extends ArrayAdapter<ContactInfo>
{
private final Activity context;
int resourceid;
List<ContactInfo> list = null;
public ContactsAdapter(Activity context, List<ContactInfo> list) {
super(context, R.layout.contactrow, list);
this.context = context;
this.list = list;
}
#Override
public View getView(int position, View convertview, ViewGroup viewgroup){
View view = null;
if(convertview == null){
LayoutInflater inflater = context.getLayoutInflater();
view = inflater.inflate(R.layout.contactrow, null);
ContactHolder holder = new ContactHolder();
holder.txtviewfirstname = (TextView)view.findViewById(R.id.firstname);
holder.txtviewphone = (TextView)view.findViewById(R.id.phone);
holder.chkselected = (CheckBox)view.findViewById(R.id.check);
view.setTag(holder);
}
else{
view = convertview;
}
ContactHolder holder2 = (ContactHolder) view.getTag();
holder2.txtviewfirstname.setText(list.get(position).firstname);
holder2.txtviewphone.setText(list.get(position).phonenumber);
holder2.chkselected.setChecked(list.get(position).selected);
return view;
}
final class ContactHolder{
TextView txtviewfirstname;
CheckBox chkselected;
TextView txtviewphone;
}
}
LAYOUT
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="100" >
<RadioGroup
android:id="#+id/rgStyle"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="15"
android:orientation="vertical" >
<TextView
android:id="#+id/firstname"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="#+id/phone"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:textAppearance="?android:attr/textAppearanceSmall" />
</RadioGroup>
<RadioGroup
android:id="#+id/rgStyle2"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:layout_weight="85"
android:orientation="vertical" >
<CheckBox
android:id="#+id/check"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:checked="false"
android:focusable="false"
android:focusableInTouchMode="false" >
</CheckBox>
</RadioGroup>
</LinearLayout>
1. Bydefault all the Rows of the ListView are enabled to listen to click....
You must implement onItemClickListener() for the ListView....
See this example:
http://www.mkyong.com/android/android-listview-example/
you can use a CheckedTextView, or you can create a Checkable Layout, like this one :
http://tokudu.com/2010/android-checkable-linear-layout/
i think you should make adapter as
public class ContactsAdapter extends BaseAdapter {
ArrayList<ContactInfo> mlist;
Context mcontext;
public BluetoothChatadpter(Context context,ArrayList<ChatInfo> mchtlist) {
mlist = mchtlist;
mcontext = context;
}
#Override
public int getCount() {
return mlist.size();
}
#Override
public Object getItem(int postion) {
return mlist.get(postion);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertview, ViewGroup viewgroup){
View view = null;
if(convertview == null){
LayoutInflater inflater = context.getLayoutInflater();
view = inflater.inflate(R.layout.contactrow, null);
ContactHolder holder = new ContactHolder();
holder.txtviewfirstname = (TextView)view.findViewById(R.id.firstname);
holder.txtviewphone = (TextView)view.findViewById(R.id.phone);
holder.chkselected = (CheckBox)view.findViewById(R.id.check);
setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// to open the selected file in resp
// do your work here
}});
chkselected .setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// Toast.makeText(context,// "checked is clicke="+pos, 12).show();
if (chkselected.isChecked())
{
// do your work here
} else {
// do your work here
}
}
});
view.setTag(holder);
}
else{
view = convertview;
}
ContactHolder holder2 = (ContactHolder) view.getTag();
holder2.txtviewfirstname.setText(list.get(position).firstname);
holder2.txtviewphone.setText(list.get(position).phonenumber);
holder2.chkselected.setChecked(list.get(position).selected);
return view;
}
}
I've got a custom BaseAdapter and an add button in the main activity. The button opens a dialog with a textbox and you can add new elements to the list that way. The problem is that the list is not refreshing. In the onActivityResult() function I print the number of elements in the list and each time I hit OK in the dialog box the number increases, so I know it's just the refreshing that doesn't work. My BaseAdapter and my activity:
class ListaOrase extends BaseAdapter{
private Activity context;
ArrayList<String> orase;
public ListaOrase(Activity context){
this.context=context;
orase=new ArrayList<String>();
}
public void add(String string){
orase.add(string);
this.notifyDataSetChanged();
}
public View getView (int position, View convertView, ViewGroup list) {
View element;
if (convertView == null)
{
LayoutInflater inflater = context.getLayoutInflater();
element = inflater.inflate(R.layout.lista, null);
}
else element = convertView;
TextView elementLista=(TextView)element.findViewById(R.id.elementLista);
elementLista.setText(orase.get(position));
return element;
}
}
public class WeatherAppActivity extends ListActivity {
Button buton;
ListaOrase lista;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
lista=new ListaOrase(this);
buton=(Button)findViewById(R.id.buton);
lista.add("Bucuresti");
lista.add("Sibiu");
setListAdapter(lista);
}
public void add(View view){
Intent intent=new Intent();
intent.setClass(this, Adauga.class);
startActivityForResult(intent, 0);
}
public void onActivityResult (int requestCode, int responseCode, Intent data){
System.out.println("Apelata");
if(responseCode==1){
lista.add(data.getStringExtra("oras")); // e chiar getText()
System.out.println(lista.getCount());
lista.notifyDataSetChanged();
}
}
}
As you can see, I'm trying to refresh (notifyDataSetChanged();) both when adding a new element (in the BaseAdapter extending class) and in method onActivityResult, after the dialog passes the new element to the main Activity. I repeat, the element IS added to the list because the count increases, it just doesn't refresh.
Thanks for your answers!
It's normal that it doesn't refresh, you are adding an item to "lista" but the adapter keeps its own copy of that list, so or you set again the list in the adapter and then you call notifyDataChanged or you add the new item to the adapter.
Anyway I see couple of weird things, I thing you could semplify everything using an array adapter, you don't need to implement add,etc. I wrote some code simplyfing yours:
public class WeatherAppActivity extends ListActivity {
Button buton;
ItemsAdapter lista;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
List<String> initialList = new ArrayList<String>();
initialList.add("Bucuresti");
initialList.add("Sibiu");
lista=new ItemsAdapter(this, initialList);
buton=(Button)findViewById(R.id.button1);
buton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
lista.add(""+System.currentTimeMillis()); // e chiar getText()
lista.notifyDataSetChanged();
}
});
setListAdapter(lista);
}
class ItemsAdapter extends ArrayAdapter<String> {
public ItemsAdapter(Context context, List<String> list) {
super(context, R.layout.lista, list);
}
#Override
public View getView(final int position, View row, final ViewGroup parent) {
final String item = getItem(position);
ItemWrapper wrapper = null;
if (row == null) {
row = getLayoutInflater().inflate(R.layout.lista, parent, false);
wrapper = new ItemWrapper(row);
row.setTag(wrapper);
} else {
wrapper = (ItemWrapper) row.getTag();
}
wrapper.refreshData(item);
return row;
}
class ItemWrapper {
TextView text;
public ItemWrapper(View row) {
text = (TextView) row.findViewById(R.id.elementLista);
}
public void refreshData(String item) {
text.setText(item);
}
}
}
}
These are the xml that I have used:
main.xml
<?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" >
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="63dp"
android:text="Button" />
<ListView
android:id="#id/android:list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true" >
</ListView>
</RelativeLayout>
lista.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/elementLista"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Medium Text"
android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout>
This is the version of the adapter using a baseadapter:
class ItemsBaseAdapter extends BaseAdapter {
private List<String> items;
private Context mContext;
public ItemsBaseAdapter(Context context, List<String> list) {
items = list;
mContext = context;
}
public void addItem(String str) {
items.add(str);
}
#Override
public View getView(final int position, View row, final ViewGroup parent) {
final String item = (String) getItem(position);
ItemWrapper wrapper = null;
if (row == null) {
row = getLayoutInflater().inflate(R.layout.lista, parent, false);
wrapper = new ItemWrapper(row);
row.setTag(wrapper);
} else {
wrapper = (ItemWrapper) row.getTag();
}
wrapper.refreshData(item);
return row;
}
class ItemWrapper {
TextView text;
public ItemWrapper(View row) {
text = (TextView) row.findViewById(R.id.elementLista);
}
public void refreshData(String item) {
text.setText(item);
}
}
#Override
public int getCount() {
return items.size();
}
#Override
public Object getItem(int position) {
return items.get(position);
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
}
And this is the version of the list item wich also include an imageview on the left:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<ImageView
android:layout_height="wrap_content"
android:src="#android:drawable/btn_star_big_on"
android:scaleType="fitCenter"
android:layout_width="wrap_content"
/>
<TextView
android:id="#+id/elementLista"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Medium Text"
android:textAppearance="?android:attr/textAppearanceMedium"
/>
</LinearLayout>