I have a ListView with each row consisting of a textview and a checkbox.
The user is allowed to click on each TextView, and once he does a DialogBox is presented to him where he is expected to either choose Yes or No.
When he chooses No, the CheckBox next to the TextView the user clicked needs to be ticked automatically.
The problem that I am facing is that no matter which TextBox the user chooses, the last CheckBox of the list gets ticked all the time, and not the one next to the chosen TextView.
After debugging I noticed that this is happening because the getView() method of the adapter class stops on the last row, thus the last row always gets selected. I tried setting up tags for each row so that I can than tick the checkbox accordingly but then neither Checkboxes get ticked.
I would appreciate any help on this matter.
....
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
.....
holder.text.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(final View v)
{
final AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
builder.setTitle("Materials");
builder.setMessage("Did you require any materials to fix this error?");
builder.setPositiveButton("Yes", new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which)
{
String clickedError;
clickedError = holder.text.getText().toString();
Intent intent = new Intent(mContext, Material.class);
intent.putStringArrayListExtra("materialList", materialList);
intent.putExtra("clickedError", clickedError);
intent.putExtra("repairID", repairID);
((Activity)mContext).startActivityForResult(intent, 1);
}
});
builder.setNegativeButton("No", new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which)
{
//holder.chk.setChecked(true); // This ticks the last checkbox of the list.
if(holder.chk.getTag() == v.getTag())
{
holder.chk.setChecked(true);
}
}
});
builder.show();
}
});
Try passing the checkbox for the row into your on click listener:
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
.....
holder.text.setOnClickListener(new MyClickListener(holder.chk);
}
private class MyClickListener implements OnClickListener
{
Checkbox checkbox = null;
public MyClickListener(final Checkbox checkbox)
{
this.checkbox = checkbox;
}
#Override
public void onClick(final View v)
{
final AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
builder.setTitle("Materials");
builder.setMessage("Did you require any materials to fix this error?");
builder.setPositiveButton("Yes", new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which)
{
String clickedError;
clickedError = holder.text.getText().toString();
Intent intent = new Intent(mContext, Material.class);
intent.putStringArrayListExtra("materialList", materialList);
intent.putExtra("clickedError", clickedError);
intent.putExtra("repairID", repairID);
((Activity)mContext).startActivityForResult(intent, 1);
}
});
builder.setNegativeButton("No", new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which)
{
//checkbox.setChecked(true); // This ticks the last checkbox of the list.
if(checkbox.getTag() == v.getTag())
{
checkbox.setChecked(true);
}
}
});
builder.show();
}
});
CheckBox extends TextView. Use CheckBox.setText(CharSequence | int) to set text into CheckBox and remove the TextView (that will not solve your check problem, of course). Regarding your problem - it's because most AdapterView's re-use Views. Store the checked item information somewhere and in getView call setChecked(checkedItems.get(pos)).
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
.....
holder.chk.setChecked(checkedItems.get(position))
.....
builder.setNegativeButton("No", new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which)
{
//holder.chk.setChecked(true); // This ticks the last checkbox of the list.
if(holder.chk.getTag() == v.getTag())
{
holder.chk.setChecked(true);
checkedItems.put(position, true);
}
}
});
}
Where checkedItems is a SparseBooleanArray
Related
I have a listview in which when you select a row, it's checkbox becomes checked / unchecked. However, I have a onItemLongClick that displays a dialog.
Problem is when I long-click a row in the listview, it becomes checked and I don't want that to happen, I just need it to display a dialog. This is confusing me because the onItemClick is also called when I use onItemLongClick.
Here's the code for onItemClick:
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#RequiresApi(api = Build.VERSION_CODES.N)
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
CheckBox checkBox = (CheckBox)view.findViewById(R.id.checkmark);
TextView tv3 = (TextView)view.findViewById(R.id.tx_amount);
String shitts = listView.getItemAtPosition(position).toString();
HashMap<String, String> data = new HashMap<>();
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
try {
checkBox.setChecked(!checkBox.isChecked());
String[] a = shitts.split(", ");
String[] sep = a[0].split("=");
String betamount = sep[1];
String[] sepx = a[2].split("=");
String betnumber = sepx[1];
String showbetnumber = betnumber.replaceAll("[;/:*?\"<>|&{}']","");
if(checkBox.isChecked()){
hash.put(showbetnumber,tv3.getText().toString());
}else {
tv3.setText(betamount);
checked.removeAll(Collections.singletonList(position));
hash.remove(showbetnumber,tv3.getText().toString());
}
}catch (Exception e){
}
}
});
and here's the code for onItemLongClick
listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
TextView txAmt = view.findViewById(R.id.tx_amount);
AlertDialog.Builder alert = new AlertDialog.Builder(MainActivity.this);
alert.setTitle("Enter Amount:");
final EditText input = new EditText(MainActivity.this);
input.setInputType(InputType.TYPE_CLASS_NUMBER);
input.setRawInputType(Configuration.KEYBOARD_12KEY);
alert.setView(input);
alert.setPositiveButton("enter", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
String x = input.getText().toString();
txAmt.setText(x);
}
});
alert.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
//Put actions for CANCEL button here, or leave in blank
}
});
alert.show();
return false;
}
});
Any help is appreciated!
Create a boolean isLongClick and set it to false.
onItemLongClick(), set isLongClick to true.
On your dialog, set isLongClick to false again when any button is clicked or if the dialog was dismissed.
Finally, wrap all your code inside onItemClick() in:
if (!isLongClick) {
// onItemClick() code
}
The source of this solution
Can someone please explain where do put the removeView() in this case?
private void regListClickCallback() {
ListView myList = (ListView) findViewById(R.id.gamePlayList);
LayoutInflater li = LayoutInflater.from(this);
scorCh = li.inflate(R.layout.score_change_layout, null);
myList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View viewClicked, int position, long idInDB) {
AlertDialog.Builder aDB = new AlertDialog.Builder(context);
aDB.setView(scorCh);
aDB.setCancelable(false).setMessage(i).setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
}).setNegativeButton("NO", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
});
AlertDialog aD = aDB.create();
aD.show();
}
});
}
When I run the app I can click on one of the list items and get the dialog, but when I click the same item again or any other item, I get
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
I have tried to put the following code both in onCreate and in this regListClickCallback.
if(scorCh!=null)
{
ViewGroup parent = (ViewGroup) scorCh.getParent();
if(parent!=null)
parent.removeView(scorCh);
};
i was searching and trying alot today but it all does not help.
I want to use a Dialog with my own layout. In this layout there is a spinner with some subitems. My Problem is i can't get those selecteditems.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
LayoutInflater inflater = getLayoutInflater();
builder.setView(inflater.inflate(R.layout.decision, null));
LayoutInflater inflater2= getLayoutInflater();
View viewInflater=inflater2.inflate(R.layout.decision, null);
Spinner spinner=(Spinner) viewInflater.findViewById(R.id.spinner1);
spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
Log.v("click", "returnValue");
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
Log.v("click", "nothing");
}
});
builder.setPositiveButton("Start", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Log.v("click", "positive");
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Log.v("click", "negative");
}
});
builder.show();
}
I think that the problem can be that you inflate a layout, which returns a new view. This new view has different reference than this original and when you set the listener, it affects only at this new, not this you want. Maybe you should set this new view to newly created Alert Dialog?
Have you tried something like this (instead of builder.show())?
AlertDialog alertDialog = builder.create();
alertDialog.setView(viewInflater);
alertDialog.show();
It helped me so much when I wanted do set my custom view to alertdialog.
I have implemented Custom Spinner using Button following wildnove's answer. Everything works fine, but I am not able to display the highlighted radio button for the selected button.
Below is the code.
((Button) findViewById(R.id.btnSpinnerPlanets)).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// How to highlight Radio button of a selected Item???
final String[] items = view.getResources().getStringArray(R.array.planets__entries);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(MyFormActivity.this, android.R.layout.simple_spinner_dropdown_item, items);
new AlertDialog.Builder(MyFormActivity.this).setTitle("the prompt").setAdapter(adapter, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
((Button) findViewById(R.id.btnSpinnerPlanets)).setText(items[which]);
dialog.dismiss();
}
}).create().show();
}
});
Can somebody help me how to highlight selected Item's Radio button ...
Unfortunately this behavior is not natively implemented in Spinner component, however, you can always create your own BaseAdapter to show whatever you need weather is in the spinner it self or in the dropdown like this:
private class ExampleAdapter extends BaseAdapter{
#Override
public int getCount() {
return 0;
}
#Override
public Object getItem(int arg0) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
//Here is where you actually get the chance to return whatever you want in the spinner component (the single bar with the arrow)
return yourCommonView;
}
#Override
public View getDropDownView(int position, View convertView,
ViewGroup parent) {
//Here is where you get the chance to return whatever you want in the dropdown menu so here you should validate what's the currently selected element and return an image accordingly...
return yourSelectedView;
}
}
The important method here is, getDropDownView that is the one that gives you the chance to return an element with a checked CheckBox, or any mark you want to use, of course you have to create your own layout and validate if the element currently created need to be marked or not...
Regards!
The problem with this code is that you are creating the Spinner each time the Button is clicked. Try the following code:
#Override
protected Dialog onCreateDialog(int id) {
Dialog dialog;
AlertDialog.Builder builder;
switch(id) {
case 1:
Button b=((Button) findViewById(R.id.btnSpinnerPlanets));
builder = new AlertDialog.Builder(MyFormActivity.this).setTitle("the prompt").setAdapter(get_the_adapter(b), new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
b.setText(b.getResources().getStringArray(R.array.planets__entries)[which]);
dismissDialog(1);
}
})
dialog = builder.create();
break;
default:
dialog = null;
}
return dialog;
}
}
public ArrayAdapter<String> get_the_Adapter(Button view){
String[] items = view.getResources().getStringArray(R.array.planets__entries);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(MyFormActivity.this, android.R.layout.simple_spinner_dropdown_item, items);
return adapter;
}
And for the Button's onClick():
((Button) findViewById(R.id.btnSpinnerPlanets)).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
showDialog(1);
}
});
I have my ListActivity that when you tap on an item, it pops up a Dialog that ask the user for user and password. How can I get the selected position from the dialog?
Here's how I initialize the ListActivity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ListView listView = getListView();
listView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
showDialog(DIALOG_USER_PASSWORD);
}
});
}
The Dialog I pop up is a simple AlertDialog with 2 EditText which I inflate from an xml file
protected Dialog onCreateDialog(int id) {
switch (id) {
...
case DIALOG_USER_PASSWORD:
LayoutInflater factory = LayoutInflater.from(this);
final View dialogView = factory.inflate(R.layout.alert_dialog_text_entry, null);
return new AlertDialog.Builder(MyListActivity.this)
.setIcon(R.drawable.alert_dialog_icon)
.setTitle(R.string.ask_user_password)
.setView(dialogView)
.setPositiveButton(R.string.ok_text, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
String userName = ((EditText) findViewById(R.id.username_edit_alert_dialog))
.getText().toString();
String password = ((EditText) findViewById(R.id.password_edit_alert_dialog))
.getText().toString();
Credentials cred = new CredentialsL1(userName, password);
/* HERE IS WHERE i NEED THE SELECTED ITEM
mId IS THE OBJECT ASSOCIATED TO THE SELECTED POSITION */
mService.connect(mId, cred);
}
})
// Cancel button
.setNegativeButton(R.string.cancel_text,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.cancel();
}
})
.create();
}
return null;
}
The only I've come up with is creating a new field "mId" and setting it when the user taps and using it when the user taps OK in the Dialog. Any more elegant idea?
Thanks
private int selectedPosition;
...
protected void onCreate(Bundle savedInstanceState) {
....
// inside the item listener...
selectedPosition = position;
showDialog(DIALOG_USER_PASSWORD);
/* HERE IS WHERE i NEED THE SELECTED ITEM
mId IS THE OBJECT ASSOCIATED TO THE SELECTED POSITION */
// just use selectedPosition var
Any more elegant idea?
It seems that you use a normal ListView (not a checkbox one)... so, it's fine to do it this way.