Clickable text link in Alert Dialog to open Activity - java

I want one word of the text in my Alert Dialog to be clickable and open an activity on click.
I tried to use a ClickableSpan in a SpannableString, but the click is not recognized at all...
public class TestDialog extends AppCompatDialogFragment {
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
String text = "This is a test message.";
SpannableString ss = new SpannableString(text);
ClickableSpan cs = new ClickableSpan() {
#Override
public void onClick(#NonNull View view) {
System.out.println("Test");
}
};
ss.setSpan(cs, 10, 14, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(ss)
.setTitle("Test Title")
.setPositiveButton("Ok!", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
// do something
}
})
.setNegativeButton("No!", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
// do something
}
});
return builder.create();
}
}
Thanks for your help!

Ok, I did it with the help of several other posts here and youtube videos.
I use a Custom Layout showing text combined with clickable spans which I then show in the Alert Dialog:
public class TestDialog extends AppCompatDialogFragment {
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
String text = "This is a test message.";
SpannableString ss = new SpannableString(text);
ClickableSpan cs = new ClickableSpan() {
#Override
public void onClick(#NonNull View view) {
Intent testIntent = new Intent(getContext(), Test.class);
getContext().startActivity(testIntent);
}
};
ss.setSpan(cs, 10, 14, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.test_view, null);
TextView message = (TextView) view.findViewById(R.id.textView);
message.setMovementMethod(LinkMovementMethod.getInstance());
message.setText(ss);
builder.setView(view)
.setTitle("Test Title")
.setPositiveButton("Ok!", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
// do something
}
})
.setNegativeButton("No!", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
// do something
}
});
return builder.create();
}
}
I hope I could also help you.

First, Make your text HTML links clickable by using Html.fromHtml:
.setMessage(Html.fromHtml(text))
and, Add this line to your Activity in Manifest:
<data android:host="my.app" android:scheme="http"></data>
Then, http://my.app should launch your activity.

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

Android: What is the best practice to organize methods to show alert dialog

I am beginner in Android development. Suppose I have some methods to show AlertDialog within an Activity. But each AlertDialog behavior is slightly different. What is the best practice to organize the methods to show AlertDiaolog?
code is like this.
private void showNumberPickerDialog() {
LayoutInflater inflater = this.getLayoutInflater();
View numberPickerDialogView = inflater.inflate(R.layout.number_picker, null);
AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);
alertDialog.setTitle("Title for number picker here");
alertDialog.setCancelable(false);
alertDialog.setView(numberPickerDialogView);
final NumberPicker numberPicker = roomSizeNumberDialogView.findViewById(R.id.number_picker);
numberPicker.setMaxValue(10);
numberPicker.setMinValue(0);
numberPicker.setWrapSelectorWheel(false);
alertDialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// Something here
}
});
alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
});
alertDialog.show();
}
private void showMessageDialog(final boolean isA) {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);
alertDialog.setTitle("Title here");
alertDialog.setCancelable(false);
alertDialog.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if (isA) {
doA();
} else {
doB();
}
}
});
alertDialog.show();
}
private void showAlertDialogC() {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);
final EditText inputEditText = new EditText(this);
inputEditText.setInputType(InputType.TYPE_CLASS_TEXT);
innputEditText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(10)});
alertDialog.setTitle("Title here");
alertDialog.setCancelable(false);
alertDialog.setView(nameEditText);
alertDialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// Do something here
});
alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
});
alertDialog.show();
}
Is there a good way to organize the parts like this?
You can also use a customizable dialog if that's what you are looking for.
final Dialog dialog = new Dialog(context);
dialog.setContentView(R.layout.dialog_options);
dialog.show();
TextView tvDelete = dialog.findViewById(R.id.tvDelete);
tvDelete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialog.dismiss();
Dialog deleteDialog = new Dialog(context);
deleteDialog.setContentView(R.layout.dialog_delete);
deleteDialog.show();
}
});
Treat it just like you would treat an activity. Set onClickListeners on the views for which you want some particular actions. I believe this custom dialog is much more flexible than the AlertDialog
I like to handle my dialog in a separate class, that way you have more control over everything - clickListners, layout design, etc... and you don't have tons of code lines in your activity.
For example, create dialogClass:
public class ProgressDialog extends Dialog {
public ProgressDialog(#NonNull Context context) {
super(context);
setContentView(R.layout.progress_dialog); //this is your layout for the dialog
}
}
And all you need to do is to create dialog instant and call it like this:
ProgressDialog progressDialog = new ProgressDialog(getContext());
progressDialog.show(); // this line shows your dialog

Unable to create RecyclerView inside AlertDialog, content inside Alert Dialog is blank

I am trying to display two RecyclerViews inside alert dialog contents. Please Help what am I doing wrong?
The onCreateViewHolder function is not being called
Please note that the RecyclerViews are inside the ConstraintLayout in the xml. If that is causing them not to display what should be the correct procedure?
public class MainActivity extends AppCompatActivity {
private View inflatedView;
private RecyclerView fontList,sizeList;
private String[] fonts = {"normal","sans","serif","monospace"};
private String[] sizes = {"14","16","18","20","22","24"};
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
inflatedView = getLayoutInflater().inflate(R.layout.design_style,null);
builder.setView(inflatedView).setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity.this,"OK Pressed",Toast.LENGTH_SHORT).show();
}
}).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity.this,"Cancel",Toast.LENGTH_SHORT).show();
}
});
AlertDialog dialog = builder.create();
dialog.show();
fontList = inflatedView.findViewById(R.id.fontlist);
sizeList = inflatedView.findViewById(R.id.sizelist);
fontList.setLayoutManager(new LinearLayoutManager(this));
fontList.setAdapter(new MyAdapter(Arrays.asList(fonts)));
sizeList.setLayoutManager(new LinearLayoutManager(this));
sizeList.setAdapter(new MyAdapter(Arrays.asList(sizes)));
}
private class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder>{
private List<String> itemList;
public MyAdapter(List<String> itemList) {
this.itemList = itemList;
Log.d("lol","MyAdapter");
}
#NonNull
#Override
public MyAdapter.MyViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.design_fontcell,viewGroup);
Log.d("lol","onCreateViewHolder");
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull MyAdapter.MyViewHolder myViewHolder, int i) {
myViewHolder.mtextView.setText(itemList.get(i));
Log.d("lol",itemList.get(i));
}
#Override
public int getItemCount() {
Log.d("lol","getItemCount: "+itemList.size());
return itemList.size();
}
class MyViewHolder extends RecyclerView.ViewHolder{
TextView mtextView;
MyViewHolder(View cellView){
super(cellView);
mtextView = cellView.findViewById(R.id.textView_font);
}
}
}
}
Change your code like this
AlertDialog.Builder builder = new AlertDialog.Builder(this);
inflatedView = getLayoutInflater().inflate(R.layout.design_style,null);
//No need of setView() for buttons
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity.this,"OK Pressed",Toast.LENGTH_SHORT).show();
}
}).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity.this,"Cancel",Toast.LENGTH_SHORT).show();
}
});
fontList = inflatedView.findViewById(R.id.fontlist);
sizeList = inflatedView.findViewById(R.id.sizelist);
fontList.setLayoutManager(new LinearLayoutManager(this));
fontList.setAdapter(new MyAdapter(Arrays.asList(fonts)));
sizeList.setLayoutManager(new LinearLayoutManager(this));
sizeList.setAdapter(new MyAdapter(Arrays.asList(sizes)));
builder.setView(inflatedView); //Set the view at the end
AlertDialog dialog = builder.create();
dialog.show();

Creating ids to implement select listener in dialog

Iam creating a dialog with following code, who creates multiple choice check box.. But I don't know how to create their id's to add click event , I m new to android please help me..:
private void showDailog() {
final String[] items = {" Blue", " Red", " Black", " White", " Pink"};
final ArrayList itemsSelected = new ArrayList();
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Select any theme you want : ");
builder.setMultiChoiceItems(items, null,
new DialogInterface.OnMultiChoiceClickListener() {
#Override
public void onClick(DialogInterface dialog, int selectedItemId,
boolean isSelected) {
if (isSelected) {
itemsSelected.add(selectedItemId);
} else if (itemsSelected.contains(selectedItemId)) {
itemsSelected.remove(Integer.valueOf(selectedItemId));
}
}
})
.setPositiveButton("Done!", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
//Your logic when OK button is clicked
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id)
}
});
dialog = builder.create();
dialog.show();
}
Instead of Alert Dialog create a simple dialog with your custom layout like this
Dialog dialog = new Dialog(MainActivity.this);
dialog.setContentView(R.layout.dialog_lauout);
dialog.show();
Button button = (CheckBox) dialog.findViewById(R.id.button);
checkBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});

How to pass values from DIalog class to it's host

So this is my Dialog class:
public class SecondActivity extends DialogFragment {
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
builder.setView(inflater.inflate(R.layout.second, null))
.setPositiveButton("Save", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dismiss();
}
});
return builder.create();
}
}
In my dialog there are 2 edit texts which get 2 strings. I want to use those 2 strings in my MainActivity if the user presses on the save button. How do I do that?
The inflate method returns a view where you can execute a findViewById, like the following:
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View v = inflater.inflate(R.layout.second, null);
EditView editView = (EditView)v.findById(R.id.your_edit_view);
builder.setView(v)
.setPositiveButton("Save", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dismiss();
}
});
return builder.create();
}

Categories