I have created a "InterestLine" class with a "lineContent" layout that has a TextView and a RatingBar.
Then I have created an adapter to make a listView of InterestLines on the main layout, so the user can see a list of text views + rating bar besides it, and rate every one of the elements.
public class MainActivity extends ActionBarActivity implements RatingBar.OnRatingBarChangeListener{
private String gender,age,output;
private List<InterestLine> lines;
private Button doneBtn;
private ListView lv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String[] interest_list = {"//the list of text views//"};
lv=(ListView)findViewById(R.id.list_view);
lines=new ArrayList<InterestLine>();
for(String il:interest_list)
lines.add(new InterestLine(il));
ArrayAdapter<InterestLine> adapter=new ArrayAdapter<InterestLine>(this, R.layout.linecontent, R.id.tv1, lines);
lv.setAdapter(adapter);
doneBtn=(Button)findViewById(R.id.button1);
doneBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// collect stars (interests)
for(InterestLine il : lines)
output = output + il.getInterestName() + ":" + il.getNumberOfStars() + ",";
Log.i("OUTPUT", output);
}
});
}
#Override
public void onRatingChanged(RatingBar ratingBar, float rating,
boolean fromUser) {
// TODO Auto-generated method stub
}
I want to onClick of the button to collect all the ratings that were introduced by the user on the RatingBars, tried several methods without success.
Hope you can help me with this.
Thanks
The layout of the main activity:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ListView
android:id="#+id/list_view"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="0.86" >
</ListView>
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/done_btn"
android:layout_gravity="right" />
</LinearLayout>
And the layout of the line:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="match_parent">
<TextView
android:text="#string/line_text"
android:id="#+id/tv1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textSize="18sp"
android:width="120sp" />
<RatingBar
android:id="#+id/ratingBar1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:stepSize="1.0"
android:layout_gravity="center_vertical" />
</LinearLayout>
It took me a while to figure it out. For this kind of complex layout, you should not use ArrayAdapter. You should make a custom adapter extend from BaseAdapter.
Here's the working Custom Adapter and Activity codes.
RatingAdapter
public class RatingAdapter extends BaseAdapter{
List<InterestLine> mInterestLineArrayList;
private RatingListener ratingListener;
public RatingAdapter(List<InterestLine> interestLines) {
mInterestLineArrayList = interestLines;
}
#Override public int getCount() {
return mInterestLineArrayList.size();
}
#Override public InterestLine getItem(int i) {
return mInterestLineArrayList.get(i);
}
#Override public long getItemId(int i) {
return i;
}
#Override public View getView(int i, View view, ViewGroup viewGroup) {
RatingViewHolder ratingViewHolder;
if(view==null){
view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.linecontent,viewGroup,false);
ratingViewHolder = new RatingViewHolder(view);
view.setTag(ratingViewHolder);
}else{
ratingViewHolder = (RatingViewHolder) view.getTag();
}
ratingViewHolder.titleView.setText(getItem(i).getInterestName());
ratingViewHolder.ratingBar.setNumStars(getItem(i).getNumberOfStars());
ratingViewHolder.currentPosition = i;
return view;
}
public void setOnItemRatingChangeListener(RatingListener ratingListener){
this.ratingListener = ratingListener;
}
public interface RatingListener{
void onRatingBarClicked(RatingBar ratingBar, float v, boolean b,int position);
}
class RatingViewHolder implements RatingBar.OnRatingBarChangeListener{
private TextView titleView;
private RatingBar ratingBar;
private int currentPosition;
public RatingViewHolder(View view){
titleView = (TextView) view.findViewById(R.id.tv1);
ratingBar = (RatingBar) view.findViewById(R.id.ratingBar1);
ratingBar.setOnRatingBarChangeListener(this);
}
#Override public void onRatingChanged(RatingBar ratingBar, float v, boolean b) {
if(ratingListener!=null){
ratingListener.onRatingBarClicked(ratingBar,v,b,currentPosition);
}
}
}
}
MainActivity
public class MainActivity extends AppCompatActivity{
private String gender, age, output;
private List<InterestLine> lines;
private Button doneBtn;
private ListView lv;
#Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String[] interest_list = { "Hope","it's","ok" };
lv = (ListView) findViewById(R.id.list_view);
lines = new ArrayList<>();
for (String il : interest_list) {
InterestLine interestLine = new InterestLine();
interestLine.setInterestName(il);
lines.add(interestLine);
}
RatingAdapter adapter = new RatingAdapter(lines);
lv.setAdapter(adapter);
adapter.setOnItemRatingChangeListener(new RatingAdapter.RatingListener() {
#Override public void onRatingBarClicked(RatingBar ratingBar, float v, boolean b,int position) {
lines.get(position).setNumberOfStars((int)v);
}
});
doneBtn = (Button) findViewById(R.id.button1);
doneBtn.setOnClickListener(new View.OnClickListener() {
#Override public void onClick(View v) {
// collect stars (interests)
output = "";
for (InterestLine il : lines) {
output = il.getInterestName() + " " + il.getNumberOfStars();
Log.i("OUTPUT", output);
}
}
});
}
}
Basically, you create a custom adapter where you can get the instance of each rating bar. Then you set the OnRatingChangeListener on that rating bars. Then you get the desired rating value from the activity with the help of a callback. The tricky part here is getting the item position from the adapter. I solved this by storing the current item position in viewholder. Anyway, I would also like to point out that it will be a lot easier to use recycler view for this kind of thing.
Related
I have two button inside mylist.xml which is inserted over listview in main.xml using arrayadapter.It is showing me the data in application but only click functionality is not working.
Not be able to click list and both buttons.
activity_main.xml
( In this file I have just made listview using xml in which my custom list "mylist.xml" is going to inserted. )
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ListView
android:id="#+id/lv"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</ListView>
</LinearLayout>
mylist.xml
( In this file all the content of listview lv which is there on mainactivity.These file need to be inserted in that listview. )
<?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:layout_width="match_parent"
android:layout_height="30dp"
android:layout_marginTop="10dp"
android:id="#+id/s"
android:gravity="center_horizontal"
android:textSize="20dp"
android:textStyle="bold"/>
<TextView
android:layout_width="match_parent"
android:layout_height="25dp"
android:id="#+id/c"
android:textSize="15dp"
android:textStyle="bold"/>
<TextView
android:layout_width="match_parent"
android:layout_height="55dp"
android:id="#+id/d"
android:textSize="15dp"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="left">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/b1"
android:text="UPDATE"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/b2"
android:text="DELETE"/>
</LinearLayout>
</LinearLayout>
MainActivity Class
public class MainActivity extends AppCompatActivity
{
String S1[]={"hello","1","2"},C1[]={"ello2","1","2"},D1[]={"hello3","3","4"};
Button b1,b2;
ListView lv;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv=findViewById(R.id.lv);
b1=findViewById(R.id.b1);
b2=findViewById(R.id.b2);
// display data
CustomAdapter myAdapter=new CustomAdapter(this,S1,C1,D1);
lv.setAdapter(myAdapter);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(MainActivity.this,"ello"+position,Toast.LENGTH_LONG).show();
b1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(MainActivity.this,"ello",Toast.LENGTH_LONG).show();
}
});
b2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(MainActivity.this,"ello",Toast.LENGTH_LONG).show();
}
});
}
});
}
}
CustomAdapter class
public class CustomAdapter extends ArrayAdapter<String>
{
private final Activity context;
private final String Subject1[],Chapter1[],Details1[];
public CustomAdapter(Activity context,String Subject1[], String Chapter1[], String Details1[])
{
super(context,R.layout.mylist,Subject1);
this.context=context;
this.Subject1=Subject1;
this.Chapter1=Chapter1;
this.Details1=Details1;
}
public View getView(int position, View view, ViewGroup parent)
{
LayoutInflater inflater=context.getLayoutInflater();
view=inflater.inflate(R.layout.mylist, null);
TextView s =view.findViewById(R.id.s);
TextView c= view.findViewById(R.id.c);
TextView d= view.findViewById(R.id.d);
s.setText(Subject1[position]);
c.setText(Chapter1[position]);
d.setText(Details1[position]);
return view;
};
}
update the parent layout in your mylist.xml with
android:descendantFocusability="blocksDescendants"
like the following...
<?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:descendantFocusability="blocksDescendants"
android:orientation="vertical">
If any row item of list contains focusable or clickable view then
OnItemClickListener won't work.
I have found the solution here
Alternatively, you may try setting onClickListeners under getView() method of the list adapter like this (make int position parameter of getView() method final and use it inside your onclick() method). Just copy and paste the getView() method in your adapter ...
public View getView(final int position, View view, ViewGroup parent)
{
LayoutInflater inflater=context.getLayoutInflater();
view=inflater.inflate(R.layout.mylist, null);
TextView s =view.findViewById(R.id.s);
TextView c= view.findViewById(R.id.c);
TextView d= view.findViewById(R.id.d);
s.setText(Subject1[position]);
c.setText(Chapter1[position]);
d.setText(Details1[position]);
//Do like this
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Do whatever you want here with the position
}
});
b1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(context,"BUTTON1 clicked: position=" + position,Toast.LENGTH_LONG).show();
}
});
b2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(context,"BUTTON2 clicked: position=" + position,Toast.LENGTH_LONG).show();
}
});
return view;
};
Try this :
In MainActivity :
public class MainActivity extends AppCompatActivity{
String S1[]={"hello","1","2"},C1[]={"ello2","1","2"},D1[]={"hello3","3","4"};
ListView lv;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv=findViewById(R.id.lv);
// display data
CustomAdapter myAdapter=new CustomAdapter(this,S1,C1,D1);
lv.setAdapter(myAdapter);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// this click work for only on list items not work on list components
// you have to do this functionality in your **CustomAdapter** for list components.
}
});
}
}
Now, in CustomAdapter :
public class CustomAdapter extends ArrayAdapter<String>{
private final Activity context;
private final String Subject1[],Chapter1[],Details1[];
public CustomAdapter(Activity context,String Subject1[], String Chapter1[], String Details1[])
{
super(context,R.layout.mylist,Subject1);
this.context=context;
this.Subject1=Subject1;
this.Chapter1=Chapter1;
this.Details1=Details1;
}
public View getView(int position, View view, ViewGroup parent)
{
LayoutInflater inflater=context.getLayoutInflater();
view=inflater.inflate(R.layout.mylist, null);
TextView s =view.findViewById(R.id.s);
TextView c= view.findViewById(R.id.c);
TextView d= view.findViewById(R.id.d);
Button b1 = view.findViewById(R.id.b1);
Button b2 = view.findViewById(R.id.b2);
s.setText(Subject1[position]);
c.setText(Chapter1[position]);
d.setText(Details1[position]);
// here you have to do click thing :
b1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(MainActivity.this,"HELLO BUTTON 1",Toast.LENGTH_LONG).show();
}
});
b2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(MainActivity.this,"HELLO BUTTON 2",Toast.LENGTH_LONG).show();
}
});
return view;
};
}
There are two places where you can put the butonClick.
1: Inside your adapter:-
public class CustomAdapter extends ArrayAdapter<String>{
private final Activity context;
private final String Subject1[],Chapter1[],Details1[];
public CustomAdapter(Activity context,String Subject1[], String Chapter1[], String Details1[])
{
super(context,R.layout.mylist,Subject1);
this.context=context;
this.Subject1=Subject1;
this.Chapter1=Chapter1;
this.Details1=Details1;
}
public View getView(int position, View view, ViewGroup parent)
{
LayoutInflater inflater=context.getLayoutInflater();
view=inflater.inflate(R.layout.mylist, null);
TextView s =view.findViewById(R.id.s);
TextView c= view.findViewById(R.id.c);
TextView d= view.findViewById(R.id.d);
Button b1 = view.findViewById(R.id.b1);
Button b2 = view.findViewById(R.id.b2);
s.setText(Subject1[position]);
c.setText(Chapter1[position]);
d.setText(Details1[position]);
button1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Button1 click here
Toast.makeText(getApplicationContext(),"BUTTON 1 Position : "+ position,Toast.LENGTH_LONG).show();
}
});
button2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Button2 click here
Toast.makeText(getApplicationContext(),"BUTTON 2 Position : "+ position,Toast.LENGTH_LONG).show();
}
});
return view;
};
}
2:In your Activity:-
to put a buttonClick listener inside your listview first make a listener like:
public interface OnclickListener {
void onButtonClickHere(int position);
}
And then in your Activity:
ListAdapter adapter;
OnclickListener onclickListener;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
private void init() {
onclickListener = this;
filterNames = getResources().getStringArray(R.array.finalfilter_names);
filterMethods = getResources().getStringArray(R.array.filter_method_names);
listView = (ListView)
findViewById(R.id.idListView);
adapter = new ListAdapter(groceryList, getApplicationContext(), onclickListener);
}
you can access the onclick here
#Override
public void onButtonClickHere(int position) {
Filter filter = null;
if(position == 0){
filter = FilterPack.getAweStruckVibeFilter(this);
}else if(position == 1){
filter = FilterPack.getMarsFilter(this);
}else if(position == 2){
filter = FilterPack.getStarLitFilter(this);
}
filtered = bitmap.copy(bitmap.getConfig(), true);
// apply filter
imgImage.setImageBitmap(filter.processFilter(filtered));
// struck mars starlit
}
And then in your adapter :
add this in your constructor
OnclickListener onclickListener;
public ListAdapter(List<ButtonsBean> horizontalGrocderyList, Context context,OnclickListener onclickListener ){
this.buttonsBeanList = horizontalGrocderyList;
this.context = context;
this.onclickListener = onclickListener; // Add this to your constructor
}
and inside getView()
add this line:
onclickListener.onButtonClickHere(position);
I want to create a listview that displays the same clickable icon several times. I tried many ways, including a custom adapter with layout inflater but failed... At this point my ListView displays numbers instead of the icon. Can you help me please? here is my code
public class UserSelectionActivity extends AppCompatActivity implements AdapterView.OnItemClickListener {
static ArrayList<Integer> arrayOfIcons = new ArrayList<Integer>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user_selection);
arrayOfIcons.clear();
for (int i=0; i<3; i++) {arrayOfIcons.add(R.drawable.edit);}
ArrayAdapter<Integer> adapter2 = new ArrayAdapter<Integer>(this, android.R.layout.simple_list_item_1, arrayOfIcons);
ListView listView2 = (ListView) findViewById(R.id.usersListView2);
listView2.setAdapter(adapter2);
listView2.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//TODO
}
});
}
}
I don't do anything in onResume method, that's why I didn't share it
And my xml file :
<?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">
<ListView
android:id="#+id/usersListView2"
android:layout_width="80dp"
android:layout_height="450dp"
android:layout_alignParentEnd="true"
android:paddingTop="4dip"
android:paddingBottom="3dip" />
</RelativeLayout>
Hy, I suggest you to create a custom adapter:
1) create your list_item:
In res -> layout create a new file named list_item.xml. It contains only one imageView inserted into a ConstraintLayout:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/imageViewIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0"
app:srcCompat="#mipmap/ic_launcher" />
2) In your activity_main.xml you have to inser your listView:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ListView
android:id="#+id/listViewIcon"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
3) Now you have to create a new class call, for example, IconAdapter, where you create your custom adapter:
public class IconAdapter extends BaseAdapter {
Context context;
List<Integer> iconIDList;
/**
*
* #param context = activity context
* #param iconIDList = list with icon's id
*/
public IconAdapter(Context context, List<Integer> iconIDList) {
this.context = context;
this.iconIDList = iconIDList;
}
#Override
public int getCount() {
//return the size of my list
return iconIDList.size();
}
#Override
public Object getItem(int i) {
return null;
}
#Override
public long getItemId(int i) {
return 0;
}
#Override
public View getView(int i, View convertView, ViewGroup viewGroup) {
//inflate my view
if (convertView == null) {
LayoutInflater inflater;
inflater = LayoutInflater.from(context);
convertView = inflater.inflate(R.layout.list_item, null);
}
//istantiate my imageView
ImageView imageView = convertView.findViewById(R.id.imageViewIcon);
//set imageView's icon
imageView.setImageResource(iconIDList.get(i));
//return my view
return convertView;
}
}
4) Now in your MainActivity, put all together:D
public class MainActivity extends AppCompatActivity {
List<Integer> iconIDList;
IconAdapter iconAdapter;
ListView listView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//istantiate my components
iconIDList = new ArrayList<>();
listView = findViewById(R.id.listViewIcon);
iconAdapter = new IconAdapter(this, iconIDList);
int myIcon = R.drawable.ic_launcher_background;
//populate the list with icon's id
for (int i = 0; i < 5; i++) {
iconIDList.add(myIcon);
}
//set my custom adapter to the listView
listView.setAdapter(iconAdapter);
//set clickListner to the elements of my listView
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
//i is the index of the clicked element
Toast.makeText(MainActivity.this, "Click on element n. " + i, Toast.LENGTH_SHORT).show();
}
});
}
}
I hope that can help you!!! Good job!! If you have a question, comment my answer!!
In your comment you ask me how to add one listener for the name (textView) clicked and one for the icon clicked.
1) modify your list_item.xml file. Now we can use:
a LinearLayout instead of ConstraintLayout;
a textView;
a ImageButton instead of ImageView.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:descendantFocusability="blocksDescendants" > <!--this is very important to detect click-->
<TextView
android:id="#+id/textViewIcon"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3"
android:gravity="left|center"
android:text="TextView"
android:textSize="24sp" />
<ImageButton
android:id="#+id/imageButtonIcon"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginRight="8dp"
android:layout_weight="1"
app:srcCompat="#mipmap/ic_launcher" />
</LinearLayout>
2) Is better if you create a class that contains your data. We can call this class IconData:
public class IconData {
int iconID;
String text;
//constructor
public IconData(int iconID, String text) {
this.iconID = iconID;
this.text = text;
}
//getter and setter
public int getIconID() {
return iconID;
}
public void setIconID(int iconID) {
this.iconID = iconID;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
3) Now we have to change our IconAdapter.
We'll add an Interface to detect clicks on the ImageButton;
We'll change the list's data type;
We'll instatiate the newest TextView and ImageButton:
//create custom adapter -> I extend my class using BaseAdapter
public class IconAdapter extends BaseAdapter {
//create an interface to comunicate the clicks on the imageButton
public interface MyIconAdapterInterface {
void setOnClickListnerMyImageButton (int position);
}
Context context;
//change the list's name and data type
List<IconData> iconIDTextList;
MyIconAdapterInterface myIconAdapterInterface;
/**
* #param context = activity context
* #param iconIDTextList = list with icon's id and text
* #param myIconAdapterInterface = the interface that mainActivity will implements
*/
public IconAdapter(Context context, List<IconData> iconIDTextList, MyIconAdapterInterface myIconAdapterInterface) {
this.context = context;
this.iconIDTextList = iconIDTextList;
this.myIconAdapterInterface = myIconAdapterInterface;
}
#Override
public int getCount() {
//return the size of my list
return iconIDTextList.size();
}
#Override
public Object getItem(int i) {
return null;
}
#Override
public long getItemId(int i) {
return 0;
}
#Override
public View getView(final int i, View convertView, ViewGroup viewGroup) {
//inflate my view
if (convertView == null) {
LayoutInflater inflater;
inflater = LayoutInflater.from(context);
convertView = inflater.inflate(R.layout.list_item, null);
}
//istantiate my imageView and textView
ImageButton imageButton = convertView.findViewById(R.id.imageButtonIcon);
TextView textView = convertView.findViewById(R.id.textViewIcon);
//set imageView's button
int image = iconIDTextList.get(i).getIconID();
imageButton.setImageResource(image);
//set text
String text = iconIDTextList.get(i).getText();
textView.setText(text);
//setOnclickListner on my imageButton
imageButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//pass the position of my clicks to the myIconAdapterInterface
myIconAdapterInterface.setOnClickListnerMyImageButton(i);
}
});
return convertView;
}
}
4) Finally we have to change the MainActivity.java's code:
implement our class with the new interface that we have create in our IconAdapter;
modify our list data type;
pass the newest list and the interface to the IconAdapter;
implement the interface's methods.
//I implement my MainActivity with IconAdapter.MyIconAdapterInterface. I create this interface
//in the iconAdapter class
public class MainActivity extends AppCompatActivity implements IconAdapter.MyIconAdapterInterface {
//change to iconIDTextList and change List data type
List<IconData> iconIDTextList;
IconAdapter iconAdapter;
ListView listView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//istantiate my components
iconIDTextList = new ArrayList<>();
listView = findViewById(R.id.listViewIcon);
//the second "this" is refer to the IconAdapter.MyIconAdapterInterface
iconAdapter = new IconAdapter(this, iconIDTextList, this);
int myIcon = R.drawable.ic_launcher_background;
String myText = "Hello! ";
//populate the list with icon's id and text
for (int i = 0; i < 5; i++) {
iconIDTextList.add(new IconData(myIcon, myText + i));
}
//set my custom adapter to the listView
listView.setAdapter(iconAdapter);
//set clickListner to the elements of my listView
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
//i is the index of the clicked element
Toast.makeText(MainActivity.this, "Click on element n. " + i, Toast.LENGTH_SHORT).show();
}
});
}
//this is IconAdapter.MyIconAdapterInterface's method that I have to implement
#Override
public void setOnClickListnerMyImageButton(int position) {
//position = click's position
Toast.makeText(this, "Click on image n. "
+ position, Toast.LENGTH_SHORT).show();
}
}
Good Job!!
So I have been trying to display a list of data from my local mysql server using API calls like getAll,getByID,etc. on the spinner in a drop down style. However when I click on the spinner nothing happens. Here's my code for the passing the data to the spinner:-
public class markAbsentee extends AppCompatActivity implements OnItemSelectedListener{
Button fromDate, toDate, save;
TextView displayFDate, displayTDate;
Spinner genieS;
List genieList;
private Spinner getGenieS;
private List<Genie> getGenieList;
private Button getFromDate;
private Button getToDate;
private Button getSave;
private TextView getDisplayFDate;
private TextView getDisplayTDate;
private DatePickerDialog.OnDateSetListener mDateSetListener, mDateSetListener1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mark_absentee);
getGenieS = (Spinner) findViewById(R.id.geniespinner);
getFromDate = (Button) findViewById(R.id.button2);
getToDate = (Button) findViewById(R.id.button3);
getDisplayFDate = (TextView) findViewById(R.id.fromDate);
getDisplayTDate = (TextView) findViewById(R.id.toDate);
new SpinTask().execute();
//I have called the AsyncTask here which contains the get() API
}
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
Genie selected = (Genie)parent.getSelectedItem();
Toast.makeText(markAbsentee.this, selected.id + " " + selected.name, Toast.LENGTH_LONG).show();
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
class SpinTask extends AsyncTask<Void, Void, List<Genie>>{
private Exception exception;
protected void onPreExecute(){}
#Override
protected List<Genie> doInBackground(Void... voids) {
GenieService genieService = new GenieService();
return genieService.getAll();
}
protected void onPostexecute(List<Genie> genies){
if(genies == null){
new ArrayList<Genie>();
}else {
List<String> rows = genies.stream().map(genie -> getRow(genie)).collect(Collectors.toList());
ArrayAdapter<Genie> adapter = new ArrayAdapter<Genie>(markAbsentee.this, android.R.layout.simple_spinner_item, genies);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
Toast.makeText(markAbsentee.this, "Clicked", Toast.LENGTH_LONG).show();
genieS.setAdapter(adapter);
}
}
private String getRow(Genie g){
return String.format("%s %s", g.name, g.salary);
}
}
}
Here's the layout of the spinner:-
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/bcak"
android:orientation="vertical"
tools:context="com.codionics.geniem.markAbsentee">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginStart="76dp"
android:layout_marginTop="59dp"
android:text="Enter Absentee"
android:textSize="30dp"
android:textColor="#ffff" />
<Spinner
android:id="#+id/geniespinner"
android:layout_width="350dp"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_below="#+id/textView4"
android:layout_marginStart="20dp"
android:layout_marginTop="27dp"
android:popupBackground="#color/colorPrimary"
android:spinnerMode="dropdown"
android:autofillHints="Select genie" />
</RelativeLayout>
</android.support.constraint.ConstraintLayout>
P.S:- GenieService is the service class for calling the API's. I want to display the name and salary of the person in the spinner drop down list.Thanks in advance for the help.
when you set spinner value it containg only single value like string,integer etc show. when you getting data then it add data into list like below ...
listArray.addAll("Your Value");
then after define array adapter like below and set spinner ..
ArrayAdapter arrayAdapter=new ArrayAdapter(this,android.R.layout.simple_list_item_1,strings);
spinner.setAdapter(arrayAdapter);
then after you called any function on spinner item selection used like below code ...
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
Toast.makeText(getApplicationContext(),"Hello",0).show();
}
#Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
I have a custom list view with layout contain two layouts, called upper and bottom.
upper layout contain spinner, set and remove buttons.
bottom layout contain text view and back button.
By default bottom layout is in GONE state and when the user clicks on set button upper layout is GONE and bottom is VISIBLE (clicking on back button in bottom layout will return upper bottom back).
my problem is spinner value is disappear after specific flows:
Flow 1:
Add two items
Click on SET button on the first item
Remove the second item
Click on 'Back' button on the first item
Flow 2:
Click on SET
Rotate screen
Click on Back
Just to be clear, spinner values are exist and if drop it down you'll found the names (and I have android:configChanges="keyboardHidden|orientation|screenSize" in my manifest).
So, why spinner value is disappear after those flows ?
Here is my code:
Names.java
public class Names
{
private String name;
private int nameIndex;
private Boolean isNameOnTop;
public Names()
{
name = "";
isNameOnTop = true;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getNameIndex() {
return nameIndex;
}
public void setNameIndex(int nameIndex) {
this.nameIndex = nameIndex;
}
public Boolean getIsNameOnTop() {
return isNameOnTop;
}
public void setIsNameOnTop(Boolean isNameOnTop) {
this.isNameOnTop = isNameOnTop;
}
}
MainActivity.Java
public class MainActivity extends Activity
{
ArrayList<Names> namesArray = new ArrayList<>();
ListView lvNames;
ListviewAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lvNames = (ListView) findViewById(R.id.listView);
adapter = new ListviewAdapter(this, namesArray);
lvNames.setAdapter(adapter);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_add)
{
namesArray.add(new Names());
adapter.notifyDataSetChanged();
return true;
}
return super.onOptionsItemSelected(item);
}
}
ListviewAdapter.java
public class ListviewAdapter extends BaseAdapter
{
public Activity context;
public LayoutInflater inflater;
private ArrayList<Names> namesID;
private boolean isDeleted;
public ArrayList<Names> getNamesID() {
return namesID;
}
public void setNamesID(ArrayList<Names> namesID) {
this.namesID = namesID;
}
// Constructor
public ListviewAdapter(Activity context, ArrayList<Names> names)
{
super();
setNamesID(names);
this.context = context;
this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return getNamesID().size();
}
#Override
public Names getItem(int position) {
return getNamesID().get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
public class ViewHolder
{
RelativeLayout relativeLayout_Upper;
RelativeLayout relativeLayout_Bottom;
Spinner spNames;
Button btn_set, btn_remove, btn_back;
TextView tvChosen;
int index;
}
#Override
public View getView(final int i, View view, final ViewGroup viewGroup) {
final ViewHolder holder;
if (view == null) {
holder = new ViewHolder();
view = inflater.inflate(R.layout.listview_row, null);
holder.relativeLayout_Upper = (RelativeLayout) view.findViewById(R.id.lvRow_upper_layout);
holder.relativeLayout_Bottom = (RelativeLayout) view.findViewById(R.id.lvRow_bottom_layout);
holder.spNames = (Spinner) view.findViewById(R.id.spNames);
holder.btn_set = (Button) view.findViewById(R.id.btn_set);
holder.btn_remove = (Button) view.findViewById(R.id.btn_remove);
holder.btn_back = (Button) view.findViewById(R.id.btn_back);
holder.tvChosen = (TextView) view.findViewById(R.id.tv_chosen);
view.setTag(holder);
}
else
holder = (ViewHolder) view.getTag();
holder.index = i;
if (isDeleted)
{
holder.spNames.setSelection(getItem(holder.index).getNameIndex());
holder.tvChosen.setText("Chosen: " + getItem(holder.index).getName());
if (getItem(holder.index).getIsNameOnTop())
{
holder.relativeLayout_Upper.setVisibility(View.VISIBLE);
holder.relativeLayout_Bottom.setVisibility(View.GONE);
}
else
{
holder.relativeLayout_Upper.setVisibility(View.GONE);
holder.relativeLayout_Bottom.setVisibility(View.VISIBLE);
}
}
// pop spinner names
String[] names = new String[]{"Tom", "Ben", "Gil", "Adam", "Moshe", "Adi", "Michael", "Yasmin", "Jessica", "Caroline", "Avi", "Yael"};
final ArrayAdapter<String> spNamesAdapter = new ArrayAdapter<String>
(view.getContext(), android.R.layout.simple_spinner_dropdown_item, names);
spNamesAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
holder.spNames.setAdapter(spNamesAdapter);
holder.spNames.setSelection(getItem(holder.index).getNameIndex());
holder.spNames.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
//holder.spNames.setTag(position);
getItem(holder.index).setNameIndex(position);
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
holder.btn_set.setTag(i);
holder.btn_set.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getItem(holder.index).setName(holder.spNames.getSelectedItem().toString());
int position = (Integer) v.getTag();
holder.tvChosen.setText("Chosen: " + getItem(position).getName());
holder.relativeLayout_Upper.setVisibility(View.GONE);
holder.relativeLayout_Bottom.setVisibility(View.VISIBLE);
getItem(holder.index).setIsNameOnTop(false);
}
});
// remove
holder.btn_remove.setTag(i);
holder.btn_remove.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int position = (Integer) v.getTag();
namesID.remove(position);
notifyDataSetChanged();
isDeleted = true;
}
});
// back
holder.btn_back.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
holder.relativeLayout_Upper.setVisibility(View.VISIBLE);
holder.relativeLayout_Bottom.setVisibility(View.GONE);
getItem(holder.index).setIsNameOnTop(true);
}
});
return view;
}
}
activity_main.xml: contain ListView only.
upper_view.xml
<?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="match_parent">
<Spinner
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/spNames" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="SET"
android:id="#+id/btn_set" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="REMOVE"
android:id="#+id/btn_remove" />
</LinearLayout>
bottom_view.xml
<?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="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Chosen:"
android:id="#+id/tv_chosen"
android:layout_marginRight="20dp" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="BACK"
android:id="#+id/btn_back" />
</LinearLayout>
listview_row.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/lvRow_upper_layout">
<include
android:layout_width="fill_parent"
android:layout_height="wrap_content"
layout="#layout/upper_view"
android:id="#+id/includeRow_register"
android:layout_alignParentLeft="true"
android:layout_marginLeft="0dp"
android:layout_alignParentTop="true"
android:layout_marginTop="0dp" />
</RelativeLayout>
<RelativeLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/lvRow_bottom_layout"
android:visibility="gone">
<include
android:layout_width="fill_parent"
android:layout_height="wrap_content"
layout="#layout/bottom_view"
android:id="#+id/includeRow_showData"
android:layout_alignParentLeft="true"
android:layout_marginLeft="0dp"
android:layout_alignParentTop="true"
android:layout_marginTop="0dp" />
</RelativeLayout>
</LinearLayout>
In your ListviewAdapter, change:
// back
holder.btn_back.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
holder.relativeLayout_Upper.setVisibility(View.VISIBLE);
holder.relativeLayout_Bottom.setVisibility(View.GONE);
getItem(holder.index).setIsNameOnTop(true);
}
});
to:
// back
holder.btn_back.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
holder.relativeLayout_Upper.setVisibility(View.VISIBLE);
holder.relativeLayout_Bottom.setVisibility(View.GONE);
getItem(holder.index).setIsNameOnTop(true);
notifyDataSetChanged();
// OR you can use this
// holder.spNames.requestLayout();
}
});
Whenever you click on "Add" in the method onOptionsItemSelected() you add an object new names() into the list, and in the Names class, the value of attribute name is set to ""
I guess that's why you getting an empty item in the spinner.
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>