Android Dialog with modifiable single line title

2019-08-14 06:02发布

问题:

In short, I'm working on a "DurationPickerDialog" that works similarly to how the DatePickerDialog works but works based on the xsd:duration type, so the user specifies the number of years, months, days, etc.

I've also implemented a "fuzzy duration" function that gives me durations as a string like "one month ago". I would really like to be able to update the DurationPickerDialog's title in the same manner that the DatePickerDialog's title is updated, but there seems to be a problem. In the DatePickerDialog, they have it set to be a single line all the time, so that it doesn't get "jumpy." Here's how Android's source does the DatePickerDialog's title.

// Note: before the skim-readers look at this bit, realize that this is NOT my
// code but Android's internal code for the DatePickerDialog.
@Override
public void show() {
    super.show();

    /* Sometimes the full month is displayed causing the title
     * to be very long, in those cases ensure it doesn't wrap to
     * 2 lines (as that looks jumpy) and ensure we ellipsize the end.
     */
    TextView title = (TextView) findViewById(R.id.alertTitle);
    title.setSingleLine();
    title.setEllipsize(TruncateAt.END);
}

Unfortunately, I cannot access their R.id.alertTitle, because it is part of com.android.internal.R.

I have seen implementations like this stackoverflow post where it would have me modify the Window.FEATURE_CUSTOM_TITLE attribute, but that doesn't seem to let me modify the title (easily) after that.

There was also another stackoverflow post that mentioned how to change the title at runtime between two different XML layouts, but that also doesn't seem like it would be all too helpful, since the title should be modified every time the duration changes, and creating an XML layout for each duration is obviously not a good idea.

So, since they "cheated" by accessing a value that us mere mortals don't have access to, is there another way that I could go about doing it?


Edit: And through some black magic, it seems that it now does ellipsize the text like I was wanting? Only earlier it wasn't, and now I can't seem to reproduce the problem. So, I suppose while we're at it, can someone explain to me how I might have accomplished this magic?

回答1:

I would implement a custom dialog by extending the Dialog class and creating a custom xml layout for it.
You'd need some custom button backgrounds for the plus / minus and top / bottom combos and some button listeners to manipulate the values.
Since you are going for a duration value, you are probably going to need more space than the existing dialog gives you anyway.
This way you can set the title to whatever you like. Let me know if you need a code example.

Example: The dialog class:

import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class DurationDialog extends Dialog {

    private Button yearButtonPlus;
    private Button yearButtonMinus;
    private TextView dialogBody;
    private TextView dialogTitle;

    private String dialogBodyString;
    private String dialogTitleString;


    public DurationDialog(final Context context, String dialogBody, String dialogTitle) {
        super(context,R.style.CustomDialogTheme);
        this.dialogBodyString = dialogBody;
        this.dialogTitleString = dialogTitle;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        this.setContentView(R.layout.my_dialog);

        yearButtonPlus = (Button) findViewById(R.id.dialog_year_button_plus);
        yearButtonMinus = (Button) findViewById(R.id.dialog_year_button_minus);
        dialogBody = (TextView) findViewById(R.id.dialog_body);
        dialogTitle = (TextView) findViewById(R.id.dialog_title);

        dialogBody.setText(dialogBodyString);
        dialogTitle.setText(dialogTitleString);


        yearButtonPlus.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                //do year increment here
            }
        });

        //etc...
    }

}

In your activity, you call this.showDialog(DURATION_DIALOG); // DURATION_DIALOG is just an integer specified at the top of your Activity to identify the dialog for the next peice of code, which handles actually creating the dialog:

import android.app.Activity;
import android.app.Dialog;

public class MyActivity extends Activity  {

    private Dialog dialog;


    //Lots of other activity stuff...



    protected Dialog onCreateDialog(int id) {

        switch (id) {
            case DURATION_DIALOG:
                dialog = new DurationDialog(Activity.this, "your title", "your body");
                dialog.setOnDismissListener(onDismissListener);
                break;
            default:
                dialog = null;
        }
        return dialog;
    }

}

//put this listener in as an inner class of MyActivity:
    private DialogInterface.OnDismissListener onDismissListener = new DialogInterface.OnDismissListener() {
    @Override
    public void onDismiss(DialogInterface dialog) {

        DurationDialog dialog = (DurationDialog) dialog;
        //grab the duration stuff out of your dialog and do stuff with it....

    }
};

Finally, you can set your dialog theme as is done above in your styles.xml file. For example:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="CustomDialogTheme" parent="@android:style/Theme.Dialog">
        <item name="android:windowBackground">@drawable/bgnd_transparent</item>
        <item name="android:windowIsFloating">true</item>
    </style>
</resources>

Good luck!



回答2:

If you want to modify the dialog title's TextView (change text, style, behaviour...) without using a custom view, just do it that way:

TextView tv = (TextView) dialog.findViewById(android.R.id.title);
tv.setText("New title");
...