requestFeature() must be called before adding content - RecyclerView - java

Im trying to bulid a clickable RecyclerView that will open a dialog.
I cant figure out what wrong with my code, after I click the RV item the app carsh and this Eror is in the logcat:
android.util.AndroidRuntimeException: requestFeature() must be called before adding content
at com.android.internal.policy.PhoneWindow.requestFeature(PhoneWindow.java:317)
at com.android.internal.app.AlertController.installContent(AlertController.java:231)
at android.app.AlertDialog.onCreate(AlertDialog.java:423)
The Adapter is suppose to create the CustomDialog when the user clicks an item from the RV.
This is my Adapter relevant method:
#Override
public void onBindViewHolder(PartyViewHolder holder, final int position) {
SingleParty party=partyList.get(position);
String partyItemTitle= party.getPartyTitle()+ " at "+ party.getFourDigitTime()+ " in "+ party.getPlace();
holder.partyDescription.setText(partyItemTitle);
holder.linearLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
((PartiesActivity)context).showCustomDialog(partyList.get(position),position,partyList);
}
});
}
CustomDialog relevant code:
public class CustomDialog extends AppCompatDialogFragment {
private SingleParty editedParty;
private CustomDialogListener listener;
private RadioGroup eventPosted;
private RadioButton published,notPublished;
private EditText minAge, fourDigitTime, customerCost, originalCustomerCost, ticketsLeft, maxTickets, partyTitle, place, partyId, accountId, description;
private boolean selectedB,deleteB;
private String minAgeS, fourDigitTimeS, customerCostS, originalCustomerCostS, ticketsLeftS, maxTicketsS, partyTitleS, placeS, partyIdS, accountIdS, descriptionS;
ToggleButton deleteTB;
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// Get the layout inflater
LayoutInflater inflater = getActivity().getLayoutInflater();
// Inflate and set the layout for the dialog
// Pass null as the parent view because its going in the dialog layout
final View view = inflater.inflate(R.layout.custom_dialog, null);
initializeVariables(view);
builder.setView(view)
.setTitle(R.string.dialog_title)
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
selectedB=published.isChecked();
getStringDataFromDialog();
listener.applyTexts(selectedB,
deleteB,
minAgeS,
fourDigitTimeS,
customerCostS,
originalCustomerCostS,
ticketsLeftS,
maxTicketsS,
partyTitleS,
placeS,
partyIdS,
accountIdS,
descriptionS);
}
})
// Add action buttons
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
//dont save changes
}
});
AlertDialog alertDialog = builder.create();
//gets the dialog to be rtl
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
alertDialog.getWindow().getDecorView().setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
}
return alertDialog;
}
showCustomDialog:
public void showCustomDialog(SingleParty editedParty, int position, ArrayList<SingleParty> listEdited){
CustomDialog customDialog=new CustomDialog();
customDialog.setEditedParty(editedParty);
//check if he is super admin
//super admin- delete waiting for published and edit/delete published one
this.editedParty=editedParty;
this.editedPosition=position;
this.listEdited=listEdited;
customDialog.show(getSupportFragmentManager(),"");
// customDialog.setDialogValues();
}
Thanks !

Related

IllegalStateException: Fragment FiltroOpcao not attached to a context.- Android Error

I'm trying get item selected from user to fragment formulary on my Android app, following the google documentation this is possible using this methods from the library, i tried implement this methods and your Interface in my DialogFragment and get it on my fragment formulary, but, the error is returned when i click on the button necessary to open Dialog Fragment.
This is my Dialog Fragment class:
public class FiltroOpcao extends DialogFragment {
OnFiltroEscolhido listener;
private final String[] filtroAnuncio = getResources().getStringArray(R.array.filtro_array);
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
try {
listener = (OnFiltroEscolhido) getTargetFragment();
}catch(ClassCastException e){
throw new ClassCastException(context.toString()+"Deve ser implementado");
}
}
#NonNull
#Override
public Dialog onCreateDialog(#Nullable Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("Filtrar por:")
.setItems(R.array.filtro_array, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
listener.pegarFiltro(filtroAnuncio[which]);
}
});
return builder.create();
}
public interface OnFiltroEscolhido{
void pegarFiltro (String escolha);
}
}
And it is where i called the DialogFragment and the crash happens on my VendaFragment fragment class
public void onClick(View v) {
FiltroOpcao filtroOpcao = new FiltroOpcao();
filtroOpcao.setTargetFragment(VendaFragment.this, 1);
filtroOpcao.show(VendaFragment.this.getChildFragmentManager(), "FiltroOpcao");
}
private final String[] filtroAnuncio = getResources().getStringArray(R.array.filtro_array);
Probably, getResources() is the problem because you are using it before the fragment was attached.
Try to move the initialization of filtroAnuncio to onCreateDialog()
private String[] filtroAnuncio;
#NonNull
#Override
public Dialog onCreateDialog(#Nullable Bundle savedInstanceState) {
filtroAnuncio = getResources().getStringArray(R.array.filtro_array);
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("Filtrar por:")
.setItems(R.array.filtro_array, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
listener.pegarFiltro(filtroAnuncio[which]);
}
});
return builder.create();
}

Dynamically add Views in Dialog

I am trying to make Dialog that will consist 2x EditText and 1x Buttons. By clicking additional button you can add another 2x EditText and 1x Buttons. This 1x Button provide deleting this added pair. When i try to use button that should add another Views it's working properly. But button for deleting the View is working only for the first pairs. How can i do this with android:onClick, because i was trying buy it crashed.
Here is my code of Dialog class:
public class ExampleDialog extends AppCompatDialogFragment {
private EditText editTextUsername;
private EditText editTextPassword;
private ExampleDialogListener listener;
private LinearLayout parentLinearLayout;
private Context mContext;
Button dodaj,usun;
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.dialog_template, null);
builder.setView(view)
.setTitle("Login")
.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
}
})
.setPositiveButton("ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
String username = editTextUsername.getText().toString();
String password = editTextPassword.getText().toString();
listener.applyTexts(username, password);
}
});
editTextUsername = view.findViewById(R.id.edit_username);
editTextPassword = view.findViewById(R.id.edit_password);
parentLinearLayout = (LinearLayout) view.findViewById(R.id.parent_linear_layout);
dodaj = view.findViewById(R.id.add_field_button);
usun = view.findViewById(R.id.delete_button);
dodaj.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View rowView = inflater.inflate(R.layout.field, null);
// Add the new row before the add field button.
parentLinearLayout.addView(rowView, parentLinearLayout.getChildCount() - 1);
}
});
usun.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
parentLinearLayout.removeView((View) v.getParent());
usun = v.findViewById(R.id.delete_button);
}
});
return builder.create();
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
try {
listener = (ExampleDialogListener) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString() +
"must implement ExampleDialogListener");
}
}
public void contexta(Context context)
{
this.mContext = context;
}
public interface ExampleDialogListener {
void applyTexts(String username, String password);
}
}
And there is the conception of Dialog box on the picture below:
Picture
This issue may be due to view reference. Check whether v.getParent() is the view you want to delete or not.
For testing you can use "removeViewAt(int index)" method. Pass an index and check whether view is deleted at index or not.

How to delete an Item from a Spinner Using an AlertDialog

I'm trying to make an Activity that deletes the item pressed on the Spinner using an AlertDialog. I'm not deleting anything yet, I just added a Toast to make sure it will work.
This is my code:
public class SpinnerActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_spinner);
final Spinner spinner = (Spinner) findViewById(R.id.spinner);
final Context context = getApplicationContext();
// Create an ArrayAdapter using the string array and a default spinner layout
final ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
R.array.planets_array, android.R.layout.simple_spinner_item);
// Specify the layout to use when the list of choices appears
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
// Apply the adapter to the spinner
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
int selectionCurrent = spinner.getSelectedItemPosition();
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (selectionCurrent != position) {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);
// set title
alertDialogBuilder.setTitle(R.string.dialogtitle);
//set dialog message
alertDialogBuilder.setMessage(R.string.dialogtext).setCancelable(false)
.setPositiveButton(R.string.si,new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
// if this button is clicked,
Toast.makeText(context, "Eliminar", Toast.LENGTH_SHORT).show();
}
}) .setNegativeButton(R.string.no
, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// if this button is clicked, do nothing
dialog.cancel();
}
});
alertDialogBuilder.setView(spinner);
AlertDialog alertDialog = alertDialogBuilder.create();
// show it
alertDialog.show();
}
selectionCurrent = position;
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
When I run the code, the following error is displayed: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
I tried to use ((ViewGroup)spinner.getParent()).removeView(spinner); before the alertDialog.show(); but it still not working.
It says: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
Anyone knows how to solve the problem?
First create a variable to inflate the ArrayAdapter:
String[] mTestArray;
Get the data from resources:
mTestArray = getResources().getStringArray(R.array.planets_array);
Inflate the ArrayAdapter with this array:
final ArrayList<String> list =new ArrayList<String>(Arrays.asList(mTestArray));
final ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_spinner_item, list);
And finally remove it in your dialog:
final ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
mTestArray , android.R.layout.simple_spinner_item);
String item = list.get(position);
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (selectionCurrent != position) {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);
// set title
alertDialogBuilder.setTitle(R.string.dialogtitle);
//set dialog message
alertDialogBuilder.setMessage(R.string.dialogtext).setCancelable(false)
.setPositiveButton(R.string.si,new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
list.remove(position);
adapter.notifyDataSetChanged();
// if this button is clicked,
Toast.makeText(context, "Eliminar", Toast.LENGTH_SHORT).show();
}
}) .setNegativeButton(R.string.no
, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// if this button is clicked, do nothing
dialog.cancel();
}
});
alertDialogBuilder.setView(spinner);
AlertDialog alertDialog = alertDialogBuilder.create();
// show it
alertDialog.show();
}
selectionCurrent = position;
}

Returning information from an AlertDialog in Android

I have created the following AlertDialog. In it, the user selects an item from a range of options stored in an XML file and handled using an Adapter, and then clicks either the positive button or the negative button. Here is the code:
public void OpenDialog() {
AlertDialog.Builder dialog = new AlertDialog.Builder(activity);
dialog.setTitle("Promotion Options");
LayoutInflater inflater = (LayoutInflater) activity.getSystemService(activity.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(com.zlaporta.chessgame.R.layout.promotion, null);
dialog.setView(v);
dialog.setPositiveButton("Choose", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if (which == 1) {
System.out.println("ok");
}
}
});
dialog.setNegativeButton("Undo Move", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
});
dialog.show();
Spinner spinner = (Spinner) v.findViewById(com.zlaporta.chessgame.R.id.promotionSpin);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(activity, com.zlaporta.chessgame.R.array.option,
android.R.layout.simple_spinner_item);
//could be other options here instead of simple_spinner_dropdown_item. Just type simple and see what comes up next time
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
Now, I'd like information about the user's selection in the spinner to be passed back to the enclosing Activity after the positive button is clicked. What's the best way to do this?
As you seem to have defined the AlertDialog in a separate class, you cannot directly access methods defined inside the Activity from where it is invoked.
One possible way is to define a public method inside the Activity as follows:
public void doSomething(Object spinnerDataObject){
....
}
and access it this way:
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
// call the Activity's method here and send the selected item.
((MainActivity)activity).doSomething(parent.getItemAtPosition(position));
dialog.dismiss();
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
This will send the selected Spinner data object to the Activity. Whatever you want to do with that object can be done inside doSomething().

How to call main activity's function from custom ArrayAdapter?

I've looked at a lot of similar questions and can't seem to get anything to work. I have a main class with a function like this that edits shows a dialog box then edits a List when a button is pressed.
public class EditPlayers extends SherlockFragmentActivity {
listPlayerNames.setAdapter(new EditPlayerAdapter(ctx,
R.layout.score_row_edit_player, listScoreEdit));
public void deletePlayer(final int position) {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(
EditPlayers.this);
// Setting Dialog Title
alertDialog.setTitle("Delete Player");
// Setting Dialog Message
alertDialog.setMessage("Are you sure?");
// Setting Delete Button
alertDialog.setPositiveButton("Delete",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
listScoreEdit.remove(position);
updateListView();
}
});
// Setting Cancel Button
alertDialog.setNeutralButton("Cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
// Showing Alert Message
alertDialog.show();
}
}
How do I access that function from the getView() in the adapter? Here's the XML for the row
<TextView
android:id="#+id/nameEdit"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:paddingBottom="10dp"
android:paddingTop="10dp"
android:paddingLeft="10dp"
android:layout_weight="70"
android:text="Name"
android:textColor="#666666"
android:textSize="22sp"
android:textStyle="bold" >
</TextView>
<Button
android:id="#+id/deletePlayer"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="30"
android:text="Delete"
android:focusable="false" />
Here's the getView()
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
convertView = (LinearLayout) inflater.inflate(resource, null);
Score score = getItem(position);
TextView txtName = (TextView) convertView.findViewById(R.id.nameEdit);
txtName.setText(score.getName());
Button b = (Button)convertView.findViewById(R.id.deletePlayer);
b.setTag(position);
b.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//call function here
}
});
return convertView;
}
I'm totally lost at this point so any help would be appreciated. Thanks!
I would recommend providing an interface back to your activity that lets it know when that button is pressed. I would not recommend calling an activity's method from an ArrayAdapter. It is too tightly coupled.
Try something like this:
Your Activity
public class EditPlayers extends SherlockFragmentActivity implements EditPlayerAdapterCallback {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EditPlayerAdapter adapter = new EditPlayerAdapter(this,
R.layout.score_row_edit_player, listScoreEdit);
adapter.setCallback(this);
listPlayerNames.setAdapter(adapter);
}
private void deletePlayer(final int position) {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(
EditPlayers.this);
// Setting Dialog Title
alertDialog.setTitle("Delete Player");
// Setting Dialog Message
alertDialog.setMessage("Are you sure?");
// Setting Delete Button
alertDialog.setPositiveButton("Delete",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
listScoreEdit.remove(position);
updateListView();
}
});
// Setting Cancel Button
alertDialog.setNeutralButton("Cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
// Showing Alert Message
alertDialog.show();
}
#Override
public void deletePressed(int position) {
deletePlayer(position);
}
}
Adapter:
public class EditPlayerAdapter extends ArrayAdapter {
private EditPlayerAdapterCallback callback;
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
convertView = (LinearLayout) inflater.inflate(resource, null);
Score score = getItem(position);
TextView txtName = (TextView) convertView.findViewById(R.id.nameEdit);
txtName.setText(score.getName());
Button b = (Button)convertView.findViewById(R.id.deletePlayer);
b.setTag(position);
b.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if(callback != null) {
callback.deletePressed(position);
}
}
});
return convertView;
}
public void setCallback(EditPlayerAdapterCallback callback){
this.callback = callback;
}
public interface EditPlayerAdapterCallback {
public void deletePressed(int position);
}
}
Your EditPlayerAdapter gets a Context passed to it. Activity extends Context
If the Context passed is your EditPlayers and you store a class-scoped reference to that Context in your Adapter, you can then do:
((EditPlayers) yourContextVar).function();
Better yet, make an interface of some sort. It will help clarify and organise your code and it applies the same principle.

Categories