ListView with text and checkbox - android

I used RelativeLayout for my ListView.
<?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:padding="6dip" >
<CheckBox
android:id="#+id/checkBox1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:focusable="false"
android:focusableInTouchMode="false"
android:text="CheckBox" />
<TextView
android:id="#+id/test"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="#+id/checkBox1"
android:layout_alignBottom="#+id/checkBox1"
android:layout_toRightOf="#+id/checkBox1"
android:text="TextView" />
</RelativeLayout>
Here is my ListView code,
private void displayList(){
ArrayList<String> diyListArray = new ArrayList<String>();
diyListArray.add("1");
diyListArray.add("2");
diyListArray.add("3");
diyListArray.add("4");
diyListArray.add("5");
diyListArray.add("6");
diyListArray.add("7");
listAdapter = new ArrayAdapter<String>(this, R.layout.selectrow, R.id.test, diyListArray);
diyList.setAdapter( listAdapter );
}
We can see here that I used ArrayAdapter with resource id of TextView.
I am able to display the checkboxes and their corresponding texts.
How can I get user selected texts from checkboxes?

Try the following:
Demo10.class:----
public class Demo10 extends AppCompatActivity implements Listener {
private ListView lv;
private boolean[] state_ = new boolean[4];
private String[] text_ = new String[4];
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.demo11);
for(int i = 0 ; i<4 ; i++) {
state_[i] = false;
text_[i] = "text"+i;
}
lv = (ListView) findViewById(R.id.lv);
lv.setAdapter(new ItemAdapter(Demo10.this , this));// This includes a Listener that listens to onCheckBoxStateChanges.
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() { // used to handle ListView onItemClicks and how they should affect the corresponding checkBox
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
CheckBox cb = view.findViewById(R.id.cb);
cb.setChecked(!cb.isChecked());
displayCheckBoxStateText();
}
});
}
private void displayCheckBoxStateText(){
for(int i = 0 ; i<4 ; i++){
Log.e("CheckBox", text_[i]+" : " + state_[i]);
}
}
#Override
public void checkBox1(boolean state) {
state_[0] = state;
displayCheckBoxStateText();
}
#Override
public void checkBox2(boolean state) {
state_[1] = state;
displayCheckBoxStateText();
}
#Override
public void checkBox3(boolean state) {
state_[2] = state;
displayCheckBoxStateText();
}
#Override
public void checkBox4(boolean state) {
state_[3] = state;
displayCheckBoxStateText();
}
}
ItemAdapter.class:-----
public class ItemAdapter extends BaseAdapter {
private Context mContext;
private LayoutInflater layoutInflater;
private Listener callback;
public ItemAdapter(Context c , Listener l) {
mContext = c;
callback = l;
layoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public int getCount() {
return s.length;
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return position;
}
public View getView(final int position, View convertView, ViewGroup parent) {
CheckBox cb;
View view = convertView;
if (convertView == null) {
if (layoutInflater != null) {
view = layoutInflater.inflate(R.layout.demo10, null);
}
}
cb = view.findViewById(R.id.cb);
cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
switch (position) {
case 0:
callback.checkBox1(isChecked);
break;
case 1:
callback.checkBox2(isChecked);
break;
case 2:
callback.checkBox3(isChecked);
break;
case 3:
callback.checkBox4(isChecked);
break;
default:
break;
}
}
});
cb.setText(s[position]);
return view;
}
private String[] s = {
"test1",
"test2",
"test3",
"test4"
};
}
Listener interface:----
public interface Listener {
public void checkBox1(boolean state);
public void checkBox2(boolean state);
public void checkBox3(boolean state);
public void checkBox4(boolean state);
}
demo10.xml:----
<?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:padding="6dip" >
<CheckBox
android:id="#+id/cb"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:focusable="false"
android:focusableInTouchMode="false"
android:text="" />
</RelativeLayout>
demo11.xml:-----
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/lv">
</ListView>
</android.support.constraint.ConstraintLayout>

Make choice mode first
listview.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
I am making a button by clicking on it you can retrieve all the items you checked
button.setOnClickListener(this);
#Override
public void onClick(View v) {
SparseBooleanArray checked = listview.getCheckedItemPositions();
ArrayList<String> selectedItems = new ArrayList<String>();
for (int i = 0; i < checked.size(); i++) {
int position = checked.keyAt(i);
if (checked.valueAt(i))
selectedItems.add(listAdapter.getItem(position));
}
}
here you get all the items checked in your selectedItems ArrayList.

You can override getView() of ArrayAdapter and handles views by yourself. Replace:
listAdapter = new ArrayAdapter<String>(this, R.layout.selectrow, R.id.test, diyListArray);
with
listAdapter = new ArrayAdapter<String>(this, R.layout.selectrow, diyListArray){
boolean[] checked = new boolean[diyListArray.size()];
#NonNull
#Override
public View getView(final int position, #Nullable View convertView, #NonNull ViewGroup parent) {
if(convertView == null) convertView = getLayoutInflater().inflate(R.layout.selectrow, null);
TextView textView = convertView.findViewById(R.id.test);
CheckBox checkBox = convertView.findViewById(R.id.checkBox1);
textView.setText(getItem(position));
checkBox.setChecked(checked[position]);
checkBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
checked[position] = !checked[position];
String msg = "Checked Item: ";
if(!checked[position]) msg = "Unchecked Item: ";
Toast.makeText(getContext(), msg + getItem(position), Toast.LENGTH_SHORT).show();
notifyDataSetChanged();
}
});
return convertView;
}
};
I have blog about ListView: http://programandroidlistview.blogspot.com/
Hope that helps!

Related

Custom Spinner setOnItemSelectedListener is not triggered

I have a spinner and an adapter.
Spinner spinner = findViewById(R.id.spinner);
SpinnerAdapter adapter = new SpinnerAdapter(this, R.layout.spinner_item, getList());
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()
{
#Override
public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id)
{
Log.e("PROGRAM", "Selected |" + position + "|");
}
#Override
public void onNothingSelected(AdapterView<?> parentView)
{
}
});
This is my SpinnerAdapter dropdown creation
#Override
public View getDropDownView(final int position, final View convertView, final ViewGroup parent)
{
MyObject object = getItem(position);
View layout = LayoutInflater.from(parent.getContext()).inflate(R.layout.my_object_item, parent, false);
((TextView) layout.findViewById(R.id.name)).setText(object.getName());
return layout;
}
And my_object_item xml is
<?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:id="#+id/item"
android:clickable="true"
android:focusable="true">
<ImageView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:id="#+id/icon"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/name"/>
</LinearLayout>
For some reason I can not get setOnItemSelectedListener to trigger. Should I be adding listener to every component of my_object_item and from there triggering setOnItemSelectedListener?
As you have suggested above, you can try to do things manually, by adding a listener that listens to clicks on either the TextView or ImageView (the components of each item in the spinner dropdown view), and then update the spinner view according to what was selected.
1) MainActivity.class:------------
public class MainActivity extends AppCompatActivity implements Listener {
private Spinner sp;
private SpinnerAdapter spinnerAdapter;
private String[] name = {
"N1",
"N2",
"N3",
"N4"
};
private int[] icon = {
R.drawable.icon,
R.drawable.icon,
R.drawable.icon,
R.drawable.icon
};
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
sp = (Spinner) findViewById(R.id.sp);
spinnerAdapter = new SpinnerAdapter(getApplicationContext() , name , icon , name[0] , icon[0] , MainActivity.this); // TODO: Every time the activity (spinner) is created, the item selected is changed
//TODO to the initial name[0] and icon[0]. In order to solve this issue you can save the selected item (name and icon) value in sharedPreferences and use the saved value every time the spinner is opened.
sp.setAdapter(spinnerAdapter);
}
#Override
public void clicked(int position) {
if(spinnerAdapter != null){
spinnerAdapter.setCurrentNameIcon(name[position] , icon[position]);
}
}
2) SpinnerAdapter.class:---------------
public class SpinnerAdapter extends BaseAdapter {
private Context mContext;
private LayoutInflater layoutInflater;
private Listener callback;
private String current_name;
private int current_icon;
private String[] name;
private int[] icon;
public SpinnerAdapter(#NonNull Context context , String[] name_ , int[] icon_ , String inital_name_ , int initial_icon_ , Listener l) {
mContext = context;
layoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if(l != null){
callback = l;
}
name = name_;
icon = icon_;
current_name = inital_name_;
current_icon = initial_icon_;
}
public int getCount() {
return name.length;
}
public Object getItem(int position) {
return name[position];
}
public long getItemId(int position) {
return position;
}
#NonNull
public View getView(final int position, View convertView, ViewGroup parent) {
View view = convertView;
final TextView tv;
ImageView iv;
if (convertView == null) {
if (layoutInflater != null) {
view = layoutInflater.inflate(R.layout.my_object_item, parent , false);
}
}
tv = (TextView) view.findViewById(R.id.name);
tv.setText(current_name);
iv = (ImageView) view.findViewById(R.id.icon);
iv.setBackground(mContext.getResources().getDrawable(current_icon));
return view;
}
#Override
public View getDropDownView(final int position, #Nullable View convertView, #NonNull final ViewGroup parent) {
View view = convertView;
final TextView tv;
ImageView iv;
if (convertView == null) {
if (layoutInflater != null) {
view = layoutInflater.inflate(R.layout.my_object_item, parent , false);
}
}
tv = (TextView) view.findViewById(R.id.name);
tv.setText(name[position]);
tv.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(callback != null){
//https://stackoverflow.com/questions/7287195/android-spinner-close?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa
View root = parent.getRootView();
root.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK));
root.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK));
callback.clicked(position);
}
}
});
iv = (ImageView) view.findViewById(R.id.icon);
iv.setBackground(mContext.getResources().getDrawable(icon[position]));
iv.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(callback != null){
//https://stackoverflow.com/questions/7287195/android-spinner-close?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa
View root = parent.getRootView();
root.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK));
root.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK));
callback.clicked(position);
}
}
});
return view;
}
public void setCurrentNameIcon(String name , int icon){
current_name = name;
current_icon = icon;
this.notifyDataSetChanged();
}
}
3) Listener interface:------------
public interface Listener {
public void clicked(int position);
}
4) main_activity.xml:---------
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent">
<Spinner
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/sp">
</Spinner>
</android.support.constraint.ConstraintLayout>
5) my_object_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="60dp"
android:id="#+id/item"
android:clickable="true"
android:focusable="true">
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#drawable/icon"
android:layout_gravity="center_vertical"
android:id="#+id/icon"/>
<TextView
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_gravity="center_vertical"
android:gravity="center"
android:text="HI"
android:id="#+id/name"/>
</LinearLayout>

use Custome ListView with TextView And CheckBox With Single Selection of CheckBox

Hear i use Custom ListView with TextView and CheckBox.
But i want that Single Selection in CheckBox At a time
One CheckBox Selected then other one is Deselect
using BaseAdapter
but This code not Work Properly ..
Please Give me Suggestion ..thnks
#Override
public View getView(final int position, View view, ViewGroup parent) {
Integer selected_position = -1;
holder = new ViewHolder();
final Items itm = rowItem.get(position);
LayoutInflater layoutInflater = (LayoutInflater) context
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (view == null) {
view = layoutInflater.inflate(R.layout.activity_custom_list,
parent, false);
holder.tvItemName = (TextView) view.findViewById(R.id.textView1);
holder.check = (CheckBox) view.findViewById(R.id.checkBox1);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
holder.tvItemName.setText(itm.getItems());
if (position == selected_position)
holder.check.setChecked(true);
else
holder.check.setChecked(false);
holder.check.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (holder.check.isChecked()) {
selected_position = position;
} else {
selected_position = -1;
}
notifyDataSetChanged();
}
});
return view;
}}
use Custom List-View with Text-View And Check-Box With Single Selection of Check Box
So many try then finally i got the Solution I hope it is Useful Code to you All...
This code Help you to create custom List-view with Text-view and Check-box then you select one check-box and if you select another one the first should automatically be Deselected.....Thank You...
activity_main.xml
<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="com.example.listviewdemo2.MainActivity" >
<ListView
android:id="#+id/listView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true" />
</RelativeLayout>
activity_custom_list.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.listviewdemo2.CustomListActivity" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/darker_gray" >
<TextView
android:id="#+id/textView1"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginTop="4dp"
android:layout_weight="0.39"
android:textAppearance="?android:attr/textAppearanceMedium" />
<CheckBox
android:id="#+id/checkBox1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="150dp"
android:layout_marginTop="4dp"/>
</LinearLayout> </LinearLayout>
String.xml
<string-array name="name">
<item>Laptop</item>
<item>Mobile</item>
<item>Desktop</item>
<item>TV</item>
<item>Pendrive</item>
<item>Router</item>
<item>Notebook</item>
<item>Tablet</item>
<item>I-pad</item>
<item>Bluetooth</item>
<item>HomeTheator</item>
</string-array>
MainActivity.java
String[] ItemName;
List<Items> rowItem;
ListView list;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
rowItem = new ArrayList<Items>();
ItemName = getResources().getStringArray(R.array.name);
for(int i = 0 ; i < ItemName.length ; i++)
{
Items itm = new Items(ItemName[i]);
rowItem.add(itm);
}
list = (ListView) findViewById(R.id.listView1);
CustomListActivity adapter = new CustomListActivity(this, rowItem);
list.setAdapter(adapter);
}
Items.java
public class Items {
private String items;
private boolean selected;
public Items(String items) {
this.items = items;
}
public String getItems() {
return items;
}
public void setItemName(String name) {
this.items = name;
}
public boolean getSelected() {
return selected;
}
public boolean setSelected(Boolean selected) {
return this.selected = selected;
}}
CustomListActivity.java
public class CustomListActivity extends BaseAdapter {
Context context;
List<Items> rowItem;
View listView;
boolean checkState[];
ViewHolder holder;
public CustomListActivity(Context context, List<Items> rowItem) {
this.context = context;
this.rowItem = rowItem;
checkState = new boolean[rowItem.size()];
}
#Override
public int getCount() {
return rowItem.size();
}
#Override
public Object getItem(int position) {
return rowItem.get(position);
}
#Override
public long getItemId(int position) {
return rowItem.indexOf(getItem(position));
}
public class ViewHolder {
TextView tvItemName;
CheckBox check;
}
#Override
public View getView(final int position, View view, ViewGroup parent) {
holder = new ViewHolder();
final Items itm = rowItem.get(position);
LayoutInflater layoutInflater = (LayoutInflater) context
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (view == null) {
listView = new View(context);
listView = layoutInflater.inflate(R.layout.activity_custom_list,
parent, false);
holder.tvItemName = (TextView) listView
.findViewById(R.id.textView1);
holder.check = (CheckBox) listView.findViewById(R.id.checkBox1);
listView.setTag(holder);
} else {
listView = (View) view;
holder = (ViewHolder) listView.getTag();
}
holder.tvItemName.setText(itm.getItems());
holder.check.setChecked(checkState[position]);
holder.check.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
for(int i=0;i<checkState.length;i++)
{
if(i==position)
{
checkState[i]=true;
}
else
{
checkState[i]=false;
}
}
notifyDataSetChanged();
}
});
return listView;
}}
Show The Output :-
If you want a custom ListView with single choice CheckBox you can use something like this:
https://stackoverflow.com/a/12003125/5778152

Updating TextView without losing Spinner focus in busy ListView

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>

Custom List View with OnClickListener

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;
}
}

Android: ListView not refreshing on notifyDataSetChanged();

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>

Categories

Resources