Autore Topic: [facile] AlertDialog personalizzata con risorse di testo  (Letto 4217 volte)

Offline amldc

  • Nuovo arrivato
  • *
  • Post: 7
  • Respect: +5
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy Nexus
  • Play Store ID:
    Inforisorse
  • Sistema operativo:
    GNU/Linux (Ubuntu)
[facile] AlertDialog personalizzata con risorse di testo
« il: 13 Marzo 2012, 17:15:12 CET »
0
Livello di difficoltà: facile
Target SDK: 1.5
Min SDK: 1.5
Link al file compresso del progetto eclipse: ResourceDataDialog

Breve descrizione.

Creiamo una classe per AlertDialog personalizzati specializzati nella visualizzazione di file di testo memorizzati tra le risorse del progetto. L'idea è nata dalla fusione di idee e codice che ho trovato nella libreria AboutActivity ed un tutorial trovato su: Styling Android.

Iniziamo con la creazione di un Dialog Builder specializzato che provvederà alle operazioni di caricamento nel proprio corpo del file interessato. Il nostro AlertDialog utilizzerà dei template XML per permettere una facile personalizzazione dell'aspetto; in tale modo potrà essere utilizzato in contesti ed applicazioni diverse, adattandosi all'aspetto generale con poche operazioni che non richiedano la modifica del codice Java.

Iniziamo quindi a preparare un paio di file XML per il layout del nostro AlertDialog.

file layout/alert_dialog_title.xml
Codice (XML): [Seleziona]
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:orientation="vertical" >

    <LinearLayout
       android:id="@+id/title_template"
       android:layout_width="fill_parent"
       android:layout_height="wrap_content"
       android:layout_marginBottom="9dip"
       android:layout_marginLeft="10dip"
       android:layout_marginRight="10dip"
       android:layout_marginTop="6dip"
       android:gravity="center_vertical"
       android:orientation="horizontal" >

        <ImageView
           android:id="@+id/icon"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:layout_gravity="top"
           android:paddingRight="10dip"
           android:paddingTop="6dip"
           android:src="@android:drawable/ic_dialog_alert" />

        <TextView
           android:id="@+id/alertTitle"
           style="?android:attr/textAppearanceLarge"
           android:layout_width="fill_parent"
           android:layout_height="wrap_content"
           android:ellipsize="end"
           android:singleLine="true" />
    </LinearLayout>

    <ImageView
       android:id="@+id/titleDivider"
       android:layout_width="fill_parent"
       android:layout_height="1dip"
       android:gravity="fill_horizontal"
       android:scaleType="fitXY"
       android:src="@android:drawable/divider_horizontal_bright" />

</LinearLayout>

file layout/alert_dialog_message.xml
Codice (XML): [Seleziona]
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
   android:id="@+id/scrollView"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:paddingBottom="12dip"
   android:paddingLeft="14dip"
   android:paddingRight="10dip"
   android:paddingTop="2dip" >

    <WebView
       android:id="@+id/message"
       android:layout_width="fill_parent"
       android:layout_height="wrap_content"
       android:padding="5dip" />

</ScrollView>

Per questi due file non ci sono particolari commenti da aggiungere; in realtà sono copiati quasi pari pari dal tutorial da cui ho preso lo spunto, con la modifica in WebView della view message (era una TextView); possono essere modificati per personalizzare l'aspetto finale del dialogo (cosa che esula dallo scopo di questo tutorial).

Ora inizia la parte interessante, costituita dal codice Java per la definizione del nostro Builder.

nel file ResourceDataDialogBuilder.java
Codice (Java): [Seleziona]
        /**
         * constructor
         *
         * @param context
         *            current context
         * @param filename
         *            filename of raw data stored in application's resources
         *            Defaults mime type to HTML and charcode to UTF-8
         */

        public ResourceDataDialogBuilder(Context context, String filename) {
                super(context);
                builderSetup(context, filename, MIME_HTML, CODE_UTF8);
        }

        /**
         *
         * @param context
         *            current context
         * @param filename
         *            filename of raw data stored in application's resources
         * @param mime
         *            mime type
         * @param charcode
         *            char encoding
         */

        public ResourceDataDialogBuilder(Context context, String filename, String mime, String charcode) {
                super(context);
                builderSetup(context, filename, mime, charcode);
        }

        /**
         * Common setup code
         *
         * @param context
         *            current context
         * @param filename
         *            filename of raw data stored in application's resources
         * @param mime
         *            mime type
         * @param charcode
         *            char encoding
         */

        private void builderSetup(Context context, String filename, String mime, String charcode) {
                View customTitle = View.inflate(context, R.layout.alert_dialog_title, null);
                title = (TextView) customTitle.findViewById(R.id.alertTitle);
                icon = (ImageView) customTitle.findViewById(R.id.icon);
                setCustomTitle(customTitle);

                View customMessage = View.inflate(context, R.layout.alert_dialog_message, null);
                message = (WebView) customMessage.findViewById(R.id.message);
                setView(customMessage);
                message.loadData(getRawData(context, filename), mime, charcode);
        }


Abbiamo due costruttori per permettere la creazione del dialogo omettendo il tipo mime e la codifica dei caratteri; allo stato attuale della classe è ridondante ma la divisione è fatta in previsione di un'estensione per adattarla all'utilizzo di testo semplice oltre ad HTML.
Il metodo builderSetup() provvede alle operazioni basilari per la creazione del dialogo: aggancia le view dei nostri template e richiama la funzione di caricamento del file.

nel file ResourceDataDialogBuilder.java
Codice (Java): [Seleziona]
        /**
         *
         * @param context
         *            current context
         * @param fileName
         *            filename of raw data resource
         * @return String containing file data
         */

        private static String getRawData(Context context, String fileName) {
                try {
                        String packageName = context.getApplicationContext().getPackageName();
                        Resources resources = context.getApplicationContext().getResources();
                        int resourceIdentifier = resources.getIdentifier(fileName, "raw", packageName);
                        if (resourceIdentifier != 0) {
                                InputStream inputStream = resources.openRawResource(resourceIdentifier);
                                BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
                                String line;
                                StringBuffer data = new StringBuffer();
                                while ((line = reader.readLine()) != null) {
                                        data.append(line);
                                }
                                reader.close();
                                return data.toString();
                        } else
                                return null;
                } catch (IOException e) {
                        return null;
                }
        }

questa funzione è facilmente riconoscibile da chi abbia già visto la libreria AboutActivity; Provvede a caricare il file indicato, permettendoci
di utilizzare diverse lingue semplicemente duplicandolo nelle varie cartelle raw,raw-it ecc.

Infine non ci resta che utilizzare la nostra classe per visualizzare il contenuto del file  nell'AlertDialog personalizzato:
Codice (Java): [Seleziona]
        @Override
        protected Dialog onCreateDialog(int id) {
                switch (id) {
                        case DLG_ID_DIALOG1:
                                return testDialog("datafile");
                        default:
                                return null;
                }
        }

        /**
         *
         * @return
         *              AlertDialog contenente il file specificato
         */

        private AlertDialog testDialog(String filename) {
                ResourceDataDialogBuilder builder = new ResourceDataDialogBuilder(this, filename);
                builder.setNegativeButton("no", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                                dialog.dismiss();
                        }
                });
                builder.setPositiveButton("yes", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                                dialog.dismiss();
                        }
                });
                return builder.create();
        }

Nell'esempio vediamo come venga fatto il richiamo per utilizzare il file datafile, che conterrà il nostro testo HTML. Si può notare come il metodo per la creazione del dialogo sia parametrizzato, rendendo molto semplice la gestione di più file di contenuti semplicemente aggiungendo i richiami opportuni nel metodo onCreateDialog().




Sorgenti:
ResourceDataDialogBuilder.java
Codice (Java): [Seleziona]
/**
 * Tutorial from Amedeo Lanza - Consulanza Informatica.
 *
 * ResourceDataDialogBuilder class was created by merging from:
 *
 *  [url=http://blog.stylingandroid.com/archives/280]Styling Android  &raquo; Blog Archive   &raquo; Alert Dialog &#8211; Part 2[/url]
 *  [url=http://android.marcoduff.com/aboutactivity.php]AndroidDuff - Utility - AboutActivity[/url]
 *  
 */

package it.inforisorse.tutorial.resdatadialog;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.view.View;
import android.webkit.WebView;
import android.widget.ImageView;
import android.widget.TextView;

public class ResourceDataDialogBuilder extends Builder {

        private static final String MIME_HTML = "text/html";
        private static final String CODE_UTF8 = "UTF-8";

        private TextView title = null;
        private WebView message = null;
        private ImageView icon = null;

        /**
         * constructor
         *
         * @param context
         *            current context
         * @param filename
         *            filename of raw data stored in application's resources
         *            Defaults mime type to HTML and charcode to UTF-8
         */

        public ResourceDataDialogBuilder(Context context, String filename) {
                super(context);
                builderSetup(context, filename, MIME_HTML, CODE_UTF8);
        }

        /**
         *
         * @param context
         *            current context
         * @param filename
         *            filename of raw data stored in application's resources
         * @param mime
         *            mime type
         * @param charcode
         *            char encoding
         */

        public ResourceDataDialogBuilder(Context context, String filename, String mime, String charcode) {
                super(context);
                builderSetup(context, filename, mime, charcode);
        }

        /**
         * Common setup code
         *
         * @param context
         *            current context
         * @param filename
         *            filename of raw data stored in application's resources
         * @param mime
         *            mime type
         * @param charcode
         *            char encoding
         */

        private void builderSetup(Context context, String filename, String mime, String charcode) {
                View customTitle = View.inflate(context, R.layout.alert_dialog_title, null);
                title = (TextView) customTitle.findViewById(R.id.alertTitle);
                icon = (ImageView) customTitle.findViewById(R.id.icon);
                setCustomTitle(customTitle);

                View customMessage = View.inflate(context, R.layout.alert_dialog_message, null);
                message = (WebView) customMessage.findViewById(R.id.message);
                setView(customMessage);
                message.loadData(getRawData(context, filename), mime, charcode);
        }

        @Override
        public ResourceDataDialogBuilder setTitle(int textResId) {
                title.setText(textResId);
                return this;
        }

        @Override
        public ResourceDataDialogBuilder setTitle(CharSequence text) {
                title.setText(text);
                return this;
        }

        @Override
        public ResourceDataDialogBuilder setIcon(int drawableResId) {
                icon.setImageResource(drawableResId);
                return this;
        }

        @Override
        public ResourceDataDialogBuilder setIcon(Drawable icon) {
                this.icon.setImageDrawable(icon);
                return this;
        }

        /**
         *
         * @param context
         *            current context
         * @param fileName
         *            filename of raw data resource
         * @return String containing file data
         */

        private static String getRawData(Context context, String fileName) {
                try {
                        String packageName = context.getApplicationContext().getPackageName();
                        Resources resources = context.getApplicationContext().getResources();
                        int resourceIdentifier = resources.getIdentifier(fileName, "raw", packageName);
                        if (resourceIdentifier != 0) {
                                InputStream inputStream = resources.openRawResource(resourceIdentifier);
                                BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
                                String line;
                                StringBuffer data = new StringBuffer();
                                while ((line = reader.readLine()) != null) {
                                        data.append(line);
                                }
                                reader.close();
                                return data.toString();
                        } else
                                return null;
                } catch (IOException e) {
                        return null;
                }
        }
}

ResourceDataDialogActivity.java
Codice (Java): [Seleziona]
/**
 * Tutorial from Amedeo Lanza - Consulanza Informatica.
 *
 * ResourceDataDialogBuilder class was created by merging from:
 *
 *  [url=http://blog.stylingandroid.com/archives/280]Styling Android  &raquo; Blog Archive   &raquo; Alert Dialog &#8211; Part 2[/url]
 *  [url=http://android.marcoduff.com/aboutactivity.php]AndroidDuff - Utility - AboutActivity[/url]
 *  
 */

package it.inforisorse.tutorial.resdatadialog;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class ResourceDataDialogActivity extends Activity {
        private static final int DLG_ID_DIALOG1 = 1;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Button btnButton1 = (Button) findViewById(R.id.button1);
                btnButton1.setOnClickListener(new OnClickListener() {
                        public void onClick(View v) {
                                showDialog(DLG_ID_DIALOG1);
                        }
                });
    }

        @Override
        protected Dialog onCreateDialog(int id) {
                switch (id) {
                        case DLG_ID_DIALOG1:
                                return testDialog("datafile");
                        default:
                                return null;
                }
        }

        /**
         *
         * @return
         *              AlertDialog contenente il file specificato
         */

        private AlertDialog testDialog(String filename) {
                ResourceDataDialogBuilder builder = new ResourceDataDialogBuilder(this, filename);
                builder.setNegativeButton("no", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                                dialog.dismiss();
                        }
                });
                builder.setPositiveButton("yes", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                                dialog.dismiss();
                        }
                });
                return builder.create();
        }
}

main.xml
Codice (XML): [Seleziona]
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent"
   android:orientation="vertical" >

    <TextView
       android:layout_width="fill_parent"
       android:layout_height="wrap_content"
       android:text="@string/hello" />

    <Button
       android:id="@+id/button1"
       android:layout_width="fill_parent"
       android:layout_height="wrap_content"
       android:text="button1" />

</LinearLayout>

raw/datafile
Codice (html): [Seleziona]
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
        <head>
                <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
                <title>Licenza di uso</title>
                <style type="text/css">
                        h1 {
                                text-align:center;
                        }
                </style>
</head>
<body>
        <h1>File contents</h1>
        <p>Sample of how to create an AlertDialog containing a file stored in application's resources</p>
</body>

raw-it/datafile
Codice (html): [Seleziona]
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
        <head>
                <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
                <title>Licenza di uso</title>
                <style type="text/css">
                        h1 {
                                text-align:center;
                        }
                </style>
</head>
<body>
        <h1>Contenuti file</h1>
        <p>Semplice esempio di come creare un AlertDialog contenente un file memorizzato nelle risorse dell'applicazione</p>
</body>

Bibliografia: