I'm trying to place a spinner inside a list view item in android. The problem is this seems to prevent the row from being highlighted during a press and the onItemClickListener is not getting called by the ListView. Basically I am trying to mimic the functionality in the Google Music app. Does anyone know how to do this? This is the code I have been trying (I know it may not be the best... just throwing together a quick sample which shows the problem):
Activity:
public class ListViewTestActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ListView listView = (ListView) findViewById(R.id.listView1);
DataHolder data = new DataHolder(this);
DataHolder data1 = new DataHolder(this);
DataHolder data2 = new DataHolder(this);
DataHolder data3 = new DataHolder(this);
DataHolder data4 = new DataHolder(this);
DataAdapter d = new DataAdapter(this, R.layout.rowview, new DataHolder[] { data, data1, data2, data3, data4 });
listView.setAdapter(d);
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
Log.e("ERROR", "look at me!");
}
});
}
}
public class DataHolder {
private int selected;
private ArrayAdapter<CharSequence> adapter;
public DataHolder(Context parent) {
adapter = ArrayAdapter.createFromResource(parent, R.array.choices, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
}
public ArrayAdapter<CharSequence> getAdapter() {
return adapter;
}
public String getText() {
return (String) adapter.getItem(selected);
}
public int getSelected() {
return selected;
}
public void setSelected(int selected) {
this.selected = selected;
}
}
This is the list adapter:
public class DataAdapter extends ArrayAdapter<DataHolder> {
private Activity myContext;
public DataAdapter(Activity context, int textViewResourceId, DataHolder[] objects) {
super(context, textViewResourceId, objects);
myContext = context;
}
// We keep this ViewHolder object to save time. It's quicker than findViewById() when repainting.
static class ViewHolder {
protected DataHolder data;
protected TextView text;
protected Spinner spin;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = null;
// Check to see if this row has already been painted once.
if (convertView == null) {
// If it hasn't, set up everything:
LayoutInflater inflator = myContext.getLayoutInflater();
view = inflator.inflate(R.layout.rowview, null);
// Make a new ViewHolder for this row, and modify its data and spinner:
final ViewHolder viewHolder = new ViewHolder();
viewHolder.text = (TextView) view.findViewById(R.id.text);
viewHolder.data = new DataHolder(myContext);
viewHolder.spin = (Spinner) view.findViewById(R.id.spin);
viewHolder.spin.setAdapter(viewHolder.data.getAdapter());
// Used to handle events when the user changes the Spinner selection:
viewHolder.spin.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
viewHolder.data.setSelected(arg2);
viewHolder.text.setText(viewHolder.data.getText());
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
Log.d("DBGINF", "asdf");
}
});
// Update the TextView to reflect what's in the Spinner
viewHolder.text.setText(viewHolder.data.getText());
view.setTag(viewHolder);
Log.d("DBGINF", viewHolder.text.getText() + "");
} else {
view = convertView;
}
// This is what gets called every time the ListView refreshes
ViewHolder holder = (ViewHolder) view.getTag();
holder.text.setText(getItem(position).getText());
holder.spin.setSelection(getItem(position).getSelected());
return view;
}
}
Main layout for activity
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical"
android:layout_width="fill_parent" android:layout_height="fill_parent">
<ListView android:id="#+id/listView1" android:layout_height="match_parent" android:layout_width="match_parent" />
</LinearLayout>
Layout for a row:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="wrap_content" android:weightSum="1" >
<TextView android:layout_width="wrap_content"
android:layout_height="match_parent" android:id="#+id/text"
android:layout_weight="0.5" android:textSize="25sp" />
<Spinner android:layout_width="0dp" android:layout_height="wrap_content"
android:id="#+id/spin" android:prompt="#string/choice_prompt"
android:layout_weight="0.5" />
</LinearLayout>
Thanks for any help!
I had the same problem with ImageButton, and what was needed was to do
mImageButton.setFocusable(false);
I can't garantee it's the same for Spinner, but my money is on it.
Best regards.
Related
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 sample sensors (That's make the ListView busy) with custom user rate and I show the values in my listview, therefore I have a custom listview with 3 textview (for x, y and z values) and one spinner.
my layout is:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="fill_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:minWidth="140dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="X:"
android:id="#+id/tvX"
android:focusable="false"
android:focusableInTouchMode="false"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Y:"
android:focusable="false"
android:focusableInTouchMode="false"
android:id="#+id/tvY" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Z:"
android:focusable="false"
android:focusableInTouchMode="false"
android:id="#+id/tvZ" />
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:layout_marginLeft="30dp">
<Spinner
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:focusableInTouchMode="true"
android:id="#+id/spinner"/>
</LinearLayout>
</LinearLayout>
and I using this code as adapter:
public class customListView extends BaseAdapter
{
public Activity context;
ArrayList<MyActivity.SensorProperties> sensorPropertieses;
public String[] spinnerValues;
public LayoutInflater inflater;
public customListView(Activity context, ArrayList<MyActivity.SensorProperties> sensorPropertieses, String[] spinnerArray)
{
super();
this.context = context;
this.sensorPropertieses = sensorPropertieses;
spinnerValues = spinnerArray;
this.inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return sensorPropertieses.size();
}
#Override
public Object getItem(int i) {
return null;
}
#Override
public long getItemId(int i) {
return 0;
}
class ViewHolder
{
TextView Xvalue, Yvalue, Zvalue;
Spinner spinner;
}
#Override
public View getView(int i, View view, ViewGroup viewGroup)
{
ViewHolder holder;
if (view == null)
{
holder = new ViewHolder();
view = inflater.inflate(R.layout.custom_layout, null);
holder.Xvalue = (TextView) view.findViewById(R.id.tvX);
holder.Yvalue = (TextView) view.findViewById(R.id.tvY);
holder.Zvalue = (TextView) view.findViewById(R.id.tvZ);
holder.spinner = (Spinner) view.findViewById(R.id.spinner);
// populate spinner
ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>
(view.getContext(), android.R.layout.simple_spinner_item, spinnerValues);
holder.spinner.setAdapter(dataAdapter);
view.setTag(holder);
}
else
holder = (ViewHolder) view.getTag();
// update sensor values
holder.Xvalue.setText(String.valueOf("X: " + sensorPropertieses.get(i).x));
holder.Yvalue.setText(String.valueOf("Y: " + sensorPropertieses.get(i).y));
holder.Zvalue.setText(String.valueOf("Z: " + sensorPropertieses.get(i).z));
return view;
}
}
my main activity code is (the layout contain only a button and listview):
public class MyActivity extends Activity implements SensorEventListener
{
public class SensorProperties
{
public float x = 0, y = 0, z = 0;
}
ListView listView;
ArrayList<SensorProperties> sensorPropertieses = new ArrayList<SensorProperties>();
customListView adapter;
SensorManager sensorManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
// let's work only on two nodes
sensorPropertieses.add(new SensorProperties());
sensorPropertieses.add(new SensorProperties());
listView = (ListView) findViewById(R.id.listView);
String[] spinnerValues = new String[] {"A", "B", "C"};
adapter = new customListView(MyActivity.this, sensorPropertieses, spinnerValues);
listView.setAdapter(adapter);
Button btnRegister = (Button) findViewById(R.id.buRegister);
btnRegister.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view)
{
RegisterToSensors();
}
});
}
void RegisterToSensors()
{
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_FASTEST);
sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE), SensorManager.SENSOR_DELAY_GAME);
}
#Override
public void onSensorChanged(SensorEvent sensorEvent)
{
SensorProperties tmp = new SensorProperties();
tmp.x = sensorEvent.values[0];
tmp.y = sensorEvent.values[1];
tmp.z = sensorEvent.values[2];
if (sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
sensorPropertieses.set(0, tmp);
else
sensorPropertieses.set(1, tmp);
adapter.notifyDataSetChanged();
}
///...
}
The question: How should I work with ListView contains TextView and Spinner witout lost spinner focus although I update the TextView frequency?
EDIT:
I change question title and body thanks to mmlooloo comments.
To be clear:
I success to drop-down the spinner if the ListView isn't busy
I success to drop-down spinner when I updating TextView frequency not in ListView
The issue occur only with ListView and only when the listview is busy
EDIT2:
Currently, I'm not sure if the issue is the losing spinner focus or not. for debugging I add sleep of 30ms before I updating sensors value in the textviews (before // update sensor values) in my custom list view:
try {
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
And I success to drop-down the spinner and choose another item while the textview updating (everything is very slow, but works!).
NEW: I have find, right now, probably the issue is with adapter.notifyDataSetChanged() because I cannot drop down the spinner also when I gray-out the textview prints
Bottom line, I'm not really know what is the root cause but I cannot drop-down the spinner when I update text views frequency in listview, and the question is why?
I'll be glad for any help, Thank you!
Issue here is you are frequently calling adapter.notifyDataSetChanged(); in your onSensorChanged method, so it binds listview every time so does
your getView is called every time and which sets spinner value every time.
What I did is, accessed your listview first and second child in onSensorChanged method and from that I have accessed texviews and update them as frequently as you want
and you can access your spinner too.
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
// SensorProperties tmp = new SensorProperties();
// tmp.x = sensorEvent.values[0];
// tmp.y = sensorEvent.values[1];
// tmp.z = sensorEvent.values[2];
// if (sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
// sensorPropertieses.set(0, tmp);
// else
// sensorPropertieses.set(1, tmp);
// adapter.notifyDataSetChanged();
Log.i("tag", "ensorEvent.values[0] = " + sensorEvent.values[0]);
if (sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
View childView = (View) listView.getChildAt(0);
TextView xTextView = (TextView) childView.findViewById(R.id.tvX);
xTextView.setText(String.valueOf(sensorEvent.values[0]));
TextView yTextView = (TextView) childView.findViewById(R.id.tvY);
yTextView.setText(String.valueOf(sensorEvent.values[1]));
TextView zTextView = (TextView) childView.findViewById(R.id.tvZ);
zTextView.setText(String.valueOf(sensorEvent.values[2]));
} else {
View childView = (View) listView.getChildAt(1);
TextView xTextView = (TextView) childView.findViewById(R.id.tvX);
xTextView.setText(String.valueOf(sensorEvent.values[0]));
TextView yTextView = (TextView) childView.findViewById(R.id.tvY);
yTextView.setText(String.valueOf(sensorEvent.values[1]));
TextView zTextView = (TextView) childView.findViewById(R.id.tvZ);
zTextView.setText(String.valueOf(sensorEvent.values[2]));
}
}
Run this code it gives you some idea!!
public class MainActivity extends ActionBarActivity {
List<myItem> myItemList;
ListView list;
boolean isTouchEvent = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myItemList = new ArrayList<myItem>();
for (int i = 0; i < 9; i++) {
myItem m = new myItem();
m.setMyText("This is item number "+i);
myItemList.add(m);
}
list = (ListView)findViewById(R.id.list);
list.setAdapter(new MyAdapter(this, R.layout.list_item, myItemList));
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
Toast.makeText(MainActivity.this, "You have clicked item number "+arg2, Toast.LENGTH_SHORT).show();
}
});
list.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
isTouchEvent = true;
return false;
}
});
}
class MyAdapter extends ArrayAdapter<myItem> {
Context ctx;
public MyAdapter(Context context, int resource, List<myItem> objects) {
super(context, resource, objects);
ctx = context;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if(convertView == null){
holder = new ViewHolder();
LayoutInflater inflater = (LayoutInflater)ctx.getSystemService (Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.list_item, parent, false);
holder.txt = (TextView)convertView.findViewById(R.id.TextView_txt);
holder.sp = (Spinner)convertView.findViewById(R.id.Spinner_sp);
List<String> spinnerValues = new ArrayList<String>();
for (int i = 0; i < 5; i++) {
String temp = "Val #" + i;
spinnerValues.add(temp);
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(ctx,android.R.layout.simple_spinner_item,spinnerValues);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
holder.sp.setAdapter(adapter);
convertView.setTag(holder);
}else {
holder = (ViewHolder)convertView.getTag();
}
holder.sp.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
isTouchEvent = true;
return false;
}
});
holder.sp.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> arg0, View arg1,
int arg2, long arg3) {
if(!isTouchEvent){
return;
}
String spinnerStringValue = (String)holder.sp.getAdapter().getItem(arg2);
holder.txt.setText("You have selected "+ spinnerStringValue );
holder.txt.invalidate();
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
}
});
holder.txt.setText(myItemList.get(position).getMyText());
return convertView;
}
}
static class ViewHolder {
public TextView txt;
public Button bt;
public Spinner sp;
}
public class myItem {
private String myText="";
public String getMyText() {
return myText;
}
public void setMyText(String myText) {
this.myText = myText;
}
}
}
activity_main.xml:
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:descendantFocusability="blocksDescendants"
/>
list_item.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="wrap_content"
android:descendantFocusability="blocksDescendants"
android:orientation="horizontal" >
<TextView
android:id="#+id/TextView_txt"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginLeft="16dip" />
<Spinner
android:id="#+id/Spinner_sp"
android:layout_marginLeft="50dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
I made a listview in a fragment. Now I need to add a simple icon to the listview items. The icon must be the same on every item. This will be a simple arrow (imageview).
Is this possible with the listview I made? And if yes, how do I do it?
So like this format:
My text here --space--space-- >
The code for the fragment:
public class BiblioFragment extends Fragment {
final String[] items = new String[] { "Astma en alcohol", "Astma en huisdieren", "Astma en lichaamsgewicht",
"Astma en ouder worden", "Astmamedicatie", "Bekende mensen met astma", "Longfunctieonderzoek", "Reizen en vakantie",
"Sociaal leven", "Weetjes over astma", "Enzovoort", "Enzovoort", "Enzovoort" };
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_biblio, container, false);
ListView list = (ListView)view.findViewById(R.id.listView1);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, items);
list.setAdapter(adapter);
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
// TODO Auto-generated method stub
Log.v("TAG", "CLICKED row number: " + arg2);
Intent myIntent = new Intent(getActivity(), BiblioDetail.class);
myIntent.putExtra("welkerij", arg2);
startActivity(myIntent);
}
});
return view;
}
}
My XML for that fragment:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#ffffff">
<ListView
android:id="#+id/listView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true" >
</ListView>
</LinearLayout>
In onCreateView
ListView list = (ListView)view.findViewById(R.id.listView1);
CustomAdapter cus = new CustomAdapter(getActivity(),items);
list.setAdapter(cus);
Use a custom adapter
public class CustomAdapter extends BaseAdapter {
String items[];
LayoutInflater mInflater;
public CustomAdapter(Context context, String[] items) {
mInflater = LayoutInflater.from(context);
this.items = items;
}
#Override
public int getCount() {
return items.length;
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView ==null)
{
convertView = mInflater.inflate(R.layout.list_item,parent,false);
holder = new ViewHolder();
holder.tv = (TextView) convertView.findViewById(R.id.textView1);
holder.iv = (ImageView) convertView.findViewById(R.id.imageView1);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
holder.tv.setText(items[position])
// use holder.iv to set whatever image you want according to the position
return convertView;
}
static class ViewHolder
{
ImageView iv;
TextView tv;
}
}
list_item.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" >
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="42dp"
android:layout_marginTop="32dp"
android:src="#drawable/ic_launcher" />
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="#+id/imageView1"
android:layout_marginLeft="64dp"
android:layout_marginTop="14dp"
android:layout_toRightOf="#+id/imageView1"
android:text="TextView" />
</RelativeLayout>
Snap
Edit:
If you feel this is over kill you can use a compound textview with image on the left and text on the right.
In the above I have used list_item.xml which is a custom layout. I inflate that layout in getView of custom adapter. I set the text to textview. I have set the default launcher icon to imageview. You can change it though.
I have also used a ViewHolder
http://developer.android.com/training/improving-layouts/smooth-scrolling.html
Also check
How ListView's recycling mechanism works
Create ListAdapter
public class ListAdapter extends ArrayAdapter<Item> {
public ListAdapter(Context context, int textViewResourceId) {
super(context, textViewResourceId);
// TODO Auto-generated constructor stub
}
private List<Item> items;
public ListAdapter(Context context, int resource, List<Item> items) {
super(context, resource, items);
this.items = items;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi;
vi = LayoutInflater.from(getContext());
v = vi.inflate(R.layout.itemlistrow, null);
}
Item p = items.get(position);
if (p != null) {
ImageView ICon = ( ImageView) v.findViewById(R.id.description);
}
}
return v;
}
In your Activity
ListView yourListView = (ListView) findViewById(R.id.itemListView);
// get data from the table by the ListAdapter
ListAdapter customAdapter = new ListAdapter(this, R.layout.itemlistrow, List<yourItem>);
yourListView .setAdapter(customAdapter);
I have created a listview using following tutorial link http://www.ezzylearning.com/tutorial.aspx?tid=1763429
Outcome of this is, List of Activity as below image
Now, I want to navigate to different activity screen by clicking on individual row. I do have idea of navigating to next screen, However I'm not able to find the correct position of each row. I don't have much knowledge of android so please bare with my question if it is too silly.
although the code is available on the above link I'm attaching the .xml files and .java. here as well.
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#FFFFFF">
<ListView
android:id="#+id/listView1"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
listview_item_row.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dp">
<ImageView android:id="#+id/imgIcon"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:gravity="center_vertical"
android:layout_alignParentTop="true"
android:layout_alignParentBottom="true"
android:layout_marginRight="15dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp" />
<TextView android:id="#+id/txtTitle"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_vertical"
android:layout_alignParentTop="true"
android:layout_alignParentBottom="true"
android:textStyle="bold"
android:textSize="22dp"
android:textColor="#000000"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp" />
</LinearLayout>
Weather.java
public class Weather {
public int icon;
public String title;
public Weather(){
super();
}
public Weather(int icon, String title) {
super();
this.icon = icon;
this.title = title;
}
}
WeatherAdapter.java
public class WeatherAdapter extends ArrayAdapter<Weather>{
Context context;
int layoutResourceId;
Weather data[] = null;
public WeatherAdapter(Context context, int layoutResourceId, Weather[] data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
WeatherHolder holder = null;
if(row == null)
{
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new WeatherHolder();
holder.imgIcon = (ImageView)row.findViewById(R.id.imgIcon);
holder.txtTitle = (TextView)row.findViewById(R.id.txtTitle);
row.setTag(holder);
}
else
{
holder = (WeatherHolder)row.getTag();
}
Weather weather = data[position];
holder.txtTitle.setText(weather.title);
holder.imgIcon.setImageResource(weather.icon);
return row;
}
static class WeatherHolder
{
ImageView imgIcon;
TextView txtTitle;
}
}
MainActivity.java
public class MainActivity extends Activity {
private ListView listView1;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Weather weather_data[] = new Weather[]
{
new Weather(R.drawable.weather_cloudy, "Cloudy"),
new Weather(R.drawable.weather_showers, "Showers"),
new Weather(R.drawable.weather_snow, "Snow"),
new Weather(R.drawable.weather_storm, "Storm"),
new Weather(R.drawable.weather_sunny, "Sunny")
};
WeatherAdapter adapter = new WeatherAdapter(this,
R.layout.listview_item_row, weather_data);
listView1 = (ListView)findViewById(R.id.listView1);
View header = (View)getLayoutInflater().inflate(R.layout.listview_header_row, null);
listView1.addHeaderView(header);
listView1.setAdapter(adapter);
}
any help will be appreciated
Thanks
You need to attach OnItemClickListener
listView1.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView <?> adapterView, View view, int position, long id) {
// position is index of the row that was clicked
}
});
where is listView1.setOnItemClickListener ? have you set setOnItemClickListener to listView1?.and in below code onItemClick have position.
listView1.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,long id) {
}
});
You should do something like this
listView1.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) { //do something
}
});
use setOnItemSelectedListener with list http://developer.android.com/reference/android/widget/AdapterView.OnItemSelectedListener.html
listView1.addHeaderView(header);
listView1.setAdapter(adapter);
listView1.setOnItemSelectedListener(
new OnItemSelectedListener() {
#Override
public void onItemSelected(
AdapterView<?> parent, View view, int pos, long id
) {
//where pos is your index
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {}
}
);
Try this way...
listView1.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1,
int position, long arg3) {
Toast.makeText(context, position+"", Toast.LENGTH_LONG).show();
Intent go_detail_Activity_Intent= new Intent(context,Target_Activity.class);
go_detail_Activity_Intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(go_detail_Activity_Intent);
}
});
I think it help you.
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>