I'm trying to show HTML code in a dialog but the HTML needs to be stored in a string which is first put into a textview.
I have found many other questions about something similar but most are setting the text in code rather than in strings.xml. None I found seem to use a 'dialog to textview to string with html' process.
I've done so far what I think should work but I'm getting an error now (below). I've tried other ways but cannot get the HTML effects to show.
I'm still new to Android so any help to see what I'm doing wrong would be great. Thanks.
preferencesActivity.java - OnCreate
Preference myPref = (Preference) findPreference("pref_showHelp");
myPref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference preference) {
Dialog dialog = new dialog(preferencesActivity.this);
helpFile_textView = (TextView) findViewById(R.id.helpFile_textView);
helpFile_textView.setText(Html.fromHtml(getString(R.string.helpFile_text))); // Line 44
dialog.setContentView(R.layout.helpfile);
dialog.setTitle("Help");
dialog.show();
return false;
}
});
}
helpfile .xml
<TextView
android:id="#+id/helpFile_textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="#string/helpFile_text" />
</LinearLayout>
Strings .xml
<string name="helpFile_text">Test of <b>bold and <u>underline</u> and bullet •</string>
Logcat
E/AndroidRuntime(1516): java.lang.NullPointerException
E/AndroidRuntime(1516): at com.example.newcalc.preferencesActivity$1.onPreferenceClick(preferencesActivity.java:44)
Change
helpFile_textView = (TextView) findViewById(R.id.helpFile_textView);
helpFile_textView.setText(Html.fromHtml(getString(R.string.helpFile_text)));
dialog.setContentView(R.layout.helpfile);
to
dialog.setContentView(R.layout.helpfile);
helpFile_textView = (TextView) dialog.findViewById(R.id.helpFile_textView);
helpFile_textView.setText(Html.fromHtml(getString(R.string.helpFile_text)));
You have to inflate the layout that you want to use in the Dialog before you can find it using findViewById
Also since the id you want to find (i.e. helpFile_textView) is in the layout that you inflated in dialog you have to use dialog.findViewById instead of findViewById to get the TextView
Also
Dialog dialog = new dialog(preferencesActivity.this);
should be
Dialog dialog = new Dialog(preferencesActivity.this);
but i think that is a typo.
try this
dialog.setContentView(R.layout.helpfile);
helpFile_textView = (TextView) dialog.findViewById(R.id.helpFile_textView);
helpFile_textView.setText(Html.fromHtml(preferencesActivity.this.getResources().getString(R.string.helpFile_text)));
for more correction refer #Aproov's answer.
Related
When I run my code on some devices (Like MI note 4) it gives me an exception:
android.view.WindowManager$BadTokenException: Unable to add window -- token android.view.ViewRootImpl$W#7989790 is not valid; is your activity running?
But when I run this on a high speed and latest mobile (MI note 5 pro) it works fine. I can't understand the error here, please guide me thanks.
Here is XML for the spinner :-
<Spinner
android:id="#+id/type_spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="#dimen/dp_10"
android:entries="#array/type" />
and my string array:
<string-array name="type">
<item>Every Month</item>
<item>Every Year</item>
<item>Once</item>
</string-array>
add_reminder.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
View view1 = LayoutInflater.from(getActivity()).inflate(R.layout.add_reminder, null);
final PopupWindow pw = new PopupWindow(view1, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
pw.setFocusable(true);
pw.setTouchable(true);
pw.showAtLocation(view, Gravity.CENTER, 0, 0);
final Spinner type = view1.findViewById(R.id.type_spinner);
});
My fragment is still running in behind a pop-up, so this error must not be appearing since it shows that activity is not running.
And remember it's running OK on latest device.
Try as follows
View view1 = LayoutInflater.from(getActivity()).inflate(R.layout.add_reminder, null);
To
View view1 = LayoutInflater.from(view.getContext()).inflate(R.layout.add_reminder, null);
I solved that error by putting my popup's XML code in fragment and make it visible on click. By that way spinner's code runs nicely on every device that way error must be somewhere in using spinner in custom popup.
I am using revision 26.0.1 of the Android Support Library to set custom fonts in my app. In my app's theme, I added:
<item name="android:fontFamily">#font/my_font</item>
It worked like a charm, converting the text in my whole app to my custom font. EXCEPT for my dialogs - specifically their titles, messages, and also their NumberPickers. In those places, fonts were not updated. (Radio buttons and checkboxes worked; so did the yes/no buttons)
Is there something I'm forgetting to add to my themes or styles? Or is this simply not supported yet by the support library?
A little more detail: I am using AppCompatDialogFragment to implement all my dialogs. In their onCreateDialog() methods, I create a dialog using AlertDialog.Builder then return it.
Thanks for the help!
Thank you everybody who answered, but unfortunately none of those solutions worked for me. I hope they will work for someone else.
I've concluded that this is a bug in the support library, and hopefully Google will fix. In the meantime, I developed this hacky workaround:
public static void applyCustomFontToDialog(Context context, Dialog dialog) {
Typeface font = ResourcesCompat.getFont(context, R.font.my_font);
if (font != null) {
TextView titleView = dialog.findViewById(android.support.v7.appcompat.R.id.alertTitle);
TextView messageView = dialog.findViewById(android.R.id.message);
if (titleView != null) titleView.setTypeface(font, Typeface.BOLD);
if (messageView != null) messageView.setTypeface(font);
}
}
This works by scanning the dialog's view tree for the title and message views by the IDs that the support library gives them. If the support library were to change these IDs, this would no longer work (which is why it's hacky). Hopefully Google fixes this issue and I won't need to do this anymore.
I've found a way that only requires a one-line change to Java code every time you create an AlertDialog.
Step 1
Create a custom, reusable layout containing a TextView with the correct font set. Call it alert_dialog.xml:
<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
style="#style/SomeStyleWithDesiredFont"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="#dimen/spacing_2x" />
Step 2
Create a reusable helper function somewhere that will inflate this layout and set the text to your desired string
public static TextView createMessageView(String message, Context context) {
TextView messageView = (TextView) LayoutInflater.from(context).inflate(R.layout.alert_dialog, null, false);
messageView.setText(message);
return messageView;
}
Step 3
In every AlertDialog.Builder chain in your code, replace this line:
.setMessage(messageString)
with this line:
.setView(createMessageView(messageString, context))
(Note that the same approach should work for the title TextView. You can apply a custom view for the title by calling setCustomTitle() in your builder)
You should use a ContextThemeWrapper when creating the dialog builder. Like this
ContextThemeWrapper wrappedContext = new ContextThemeWrapper(context, R.style.mystyle);
AlertDialog.Builder builder = new AlertDialog.Builder(wrappedContext);
If you are supporting only SDK 11 and above, you may want to use
ContextThemeWrapper wrappedContext = new ContextThemeWrapper(context, R.style.mystyle);
AlertDialog.Builder builder = new AlertDialog.Builder(wrappedContext, R.style.mystyle);
Perhaps not the case here, I had a similar issue and found that fontFamily would not be impimented using the AsyncLayoutInflater. This is also the case if the AlertDialog is nested inside the AsyncLayoutInflater. I had to convert to the conventional layout inflator in order for the custom font to show. For example,
This did not show fontFamily called from TextView XML.
AsyncLayoutInflater inflater =new AsyncLayoutInflater(activity);
inflater.inflate(R.layout.dialog, null, new AsyncLayoutInflater.OnInflateFinishedListener() {
#Override
public void onInflateFinished(#NonNull View view, int resid, ViewGroup parent) {
final TextView tv = view.findViewById(R.id.textview);
tv.setText("Text with custom fontFamily called in XML, but won't work");
}
});
This did show fontFamily called from TextView XML.
final ViewGroup nullParent = null;
final View view = activity.getLayoutInflater().inflate(R.layout.dialog, nullParent);
final TextView tv= view.findViewById(R.id.textview);
tv.setText("Text with custom fontFamily called in XML, and will work");
you can inflate a custom layout in your dialog like this:
final android.support.v7.app.AlertDialog.Builder alertDialogBuilder = new android.support.v7.app.AlertDialog.Builder(context,
R.style.LimitAlertDialogStyle);
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View alertLayout = layoutInflater.inflate(R.layout.date_layout, null);
TextView tv= (TextView) alertLayout.findViewById(R.id.tv);
Typeface fc=Typeface.createFromAsset(getAssets(),"fonts/FONT");
tv.setTypeface(fc);
You can use custom Alert Dialog and set the font using Typeface. Have a look at below code snippet.
AlertDialog dg = new AlertDialog.Builder(this).setMessage("Your Message").show();
TextView tv = (TextView) dg.findViewById(android.R.id.message); // Your TextView of custom Alert Dialog
Typeface fc=Typeface.createFromAsset(getAssets(),"fonts/FONT"); // This is your font file name.
tv.setTypeface(fc);
Once I click the button, I want text of different sizes to be displayed. I tried using the built-in html support for it but I found out that font size tag is not supporI'm using a TextView to do this but I keep getting an error saying "could not execute method of the activity".
Here is my activity main part:
<TextView
android:id="#+id/header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="32px" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/rams"
android:onClick="ramsShow" />
I have the header string resource in string.xml:
<string name="header">Header</string>
This is the method in my MainActivity that is called when the button is clicked:
public void ramsShow(View view)
{
TextView test= new TextView(this);
test = (TextView) findViewById(R.id.header);
String tmp = "hi";
test.setText(tmp);
}
As Ketan suggested you should have:
public void ramsShow(View view)
{
TextView test = (TextView) findViewById(R.id.header);
String tmp = "hi";
test.setText(tmp);
}
To adjust sizes have a look here: How to set text size of textview dynamically for different screens
In Activity class, above the onCreate Method, add this line.
TextView test = null;
Within onCreate method, add this code
test = (TextView) findViewById(R.id.header);
Idea is to move the line from ramsShow method to onCreate method.
Within onCreate() write this code...
RelativeLayout lView = new RelativeLayout(this);
myText = new TextView(this);
myText.setText(Html.fromHtml("<b><center><font size='3'><font color=\"#145A14\">Welcome standard\n"</font></font></center></b>"));
lView.addView(myText);
setContentView(lView);
}
What I am trying to do is to create a custom dialog that overrides an AlertDialog.
What it is supposed to do is get some text (at least 2 strings) and then for each of those strings it is supposed to be able to get more information, but I want to do this in custom dialogs.
So what is supposed to happen is a user can enter 2 people in an activity screen, and then for the first person, you get a custom dialog and that person can enter three words, and then it jumps to the next custom dialog (exact same layout I am inflating) and the second person can enter some words.
This is my xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/LinLay_Enter_Words"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="#+id/TextView_AddPlayerWord_Instruction"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="#dimen/help_text_size"
android:textStyle="bold"></TextView>
<EditText
android:id="#+id/EditText_Word1"
android:layout_height="wrap_content"
android:maxLength="20"
android:layout_width="match_parent"
android:maxLines="1"></EditText>
<EditText
android:id="#+id/EditText_Word2"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:maxLines="1"></EditText>
<EditText
android:id="#+id/EditText_Word3"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:maxLines="1"></EditText>
</LinearLayout>
And this is part of the code:
protected Dialog onCreateDialog(int id) {
switch (id) {
case NOUN_INPUT_DIALOG_ID:
Dialog returnedDialog = initWordDialog();
return(returnedDialog);
}
return null;
}
It calls initWordDialog():
private Dialog initWordDialog() {
LayoutInflater inflater = LayoutInflater.from(this); //(LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View dialogLayout = inflater.inflate(R.layout.word_entry_dialog, null);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
...
TextView v1 = (TextView) dialogLayout.findViewById(R.id.TextView_AddPlayerWord_Instruction);
...
v1.setText("SomeText");
builder.setView(dialogLayout);
builder.setTitle(R.string.enter_word_title);
builder.setPositiveButton("Next", onNextSubmit);
AlertDialog wordBuilderDialog = builder.create();
return wordBuilderDialog;
}
I think what I am trying to find has been discussed to some degree here:
Value of EditText in Custom Dialog
Android - Custom Dialog - Can't get text from EditText
How to add two edit text fields in an alert dialog
The problem, I believe, lies here, where all of the examples everyone has their onClick in the same function as their onCreate. My stuff was a bit more complicated and I wanted to separate out the functions; however, as a result, I am now unable to access any of the EditText variables.
Here is my onClick implementation:
private DialogInterface.OnClickListener onNextSubmit = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
if (setPlayerWords()) {
...
}
};
The part that matters is I don't even get to the part where I'm accessing the edittexts until setPlayerWords is called, and this is where it is failing:
public boolean setPlayerWords() {
PMGamePlay pmObj = (PMGamePlay) getApplicationContext();
String[] playerWords = new String[pmObj.numberOfWordsPlayersGetToInput()];
//LayoutInflater inflater = LayoutInflater.from(this);
//View dialogLayout2 = inflater.inflate(R.layout.word_entry_dialog, null);
//setContentView(R.layout.word_entry_dialog);
final LinearLayout myLayout = (LinearLayout) findViewById(R.id.LinLay_Enter_Words);
final EditText w0 = (EditText) myLayout.findViewById(R.id.EditText_Word1);
final EditText w1 = (EditText) myLayout.findViewById(R.id.EditText_Word2);
final EditText w2 = (EditText) myLayout.findViewById(R.id.EditText_Word3);
String test = w0.getText().toString();
playerWords[0] = w0.getText().toString();
playerWords[1] = w1.getText().toString();
playerWords[2] = w2.getText().toString();
...
return true;
}
I initially tried re-inflating, but that seemed to reset and while the edittexts would not be null, they were reset to have "" in their values.
Then I tried to setContentView on my xml file, but that still gave me a null value.
Now, I just try and simply access the linearlayout, and that also returns a null value. If I just try to access the edittexts by their id directly without first going through its parent linearlayout, it also returns a null value.
At this point, I'm not sure what to do other than to cram everything that I have in these separate functions into the same single onclick, but I really don't want to do that. Is there nothing else I can do to access these edittexts?
Any help would be greatly appreciated!
Have you tried using the long version of inflate inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) ? I know that if you don't use this method there can be some issues with it grabbing layout characteristics, so might be causing the issue. For the viewgroup you should pick the parrent view for the alert and usually want attachToRoof = false;
public class MessageDisplayDialog extends Dialog implements OnClickListener
{
public MessageDisplayDialog(Context context, String title, String message)
{
super(context);
setTitle(title);
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.color.default_text_color);
Log.v(getClass().getSimpleName(), "MessageDisplayDialog");
LinearLayout objLinearLayout = new LinearLayout(context);
LinearLayout objButtonLayout = new LinearLayout(context);
TextView objMesaageView = new TextView(context);
objMesaageView.setText(message);
objMesaageView.setTextColor(Color.WHITE);
objMesaageView.setGravity(Gravity.CENTER_HORIZONTAL);
objMesaageView.setPadding(0, 0, 0, 10);
Button okButton = new Button(context);
okButton.setText(" OK ");
okButton.setOnClickListener(this);
okButton.setWidth(100);
objButtonLayout.addView(okButton);
objButtonLayout.setGravity(Gravity.CENTER_HORIZONTAL);
objButtonLayout.setPadding(0, 5, 0, 0);
objButtonLayout.setBackgroundColor(Color.LTGRAY);
objLinearLayout.setOrientation(LinearLayout.VERTICAL);
objLinearLayout.addView(objMesaageView);
objLinearLayout.addView(objButtonLayout);
setContentView(objLinearLayout);
//LayoutParams param = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
//this.addContentView(objLinearLayout, param);
}
public void onClick(View v)
{
this.dismiss();
}
}
But the Dialog is not showing bar below the Title, how to crack it.
I think your question has already been answered in this thread
Android - change custom title view at run time
please do some searching and accept answers before asking questions.
I think the horizontal border between the title and the message in the built in dialogs is part of AlertDialog, not the base Dialog class, although I could be totally wrong about that. Regardless, whenever I attempt to do something similar to what you are doing, that horizontal line disappears and I've never been able to get it back.
I ended up just writing my own dialog layout XML file and creating my own horizontal line using a <shape> drawable. It's actually fairly painless to create your own completely custom Dialog layouts like this, and gives you more control over the look of your dialogs.
This is old I know, but FYI the solution of drawing your own line on a custom dialog is not compatible with ICS.
It will display both your line and the line that ICS is now including by default. So you'd get two lines on the screen.
use two lines of code to remove dialoge title
Dialog dialog = new Dialog(this);
dialog.requestWindowFeature(dialog.getWindow().FEATURE_NO_TITLE);