任意のProgressDialog を作る場合の注意

ProgressDialog の表示を標準のレイアウトではなく、別に用意するレイアウトで表示
AsyncTask で表示する場合、
WindowManager.LayoutParams を用意して、
  ProgressDialog の setContentView(View v,LayoutParams params)
の実行では、
以下のエラーが発生する。 

  04-09 19:35:48.540: E/AndroidRuntime(3082): android.util.AndroidRuntimeException: requestFeature() must be called before adding content


画面 Activity の方で setContentView 実行後でこれを実行してはいけないのである。

回避する方法は、ProgressDialog onCreate メソッドをOverrideして、
その中で、任意レイアウトをコンテンツとしてセットすること。


AsyncTask 実装の中で書いたサンプルは、以下のとおり。。。
private メソッド showDialog の中に書いてある。
以下、進捗の途中でメッセージを変更する例である。

import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.PixelFormat;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;
/**
 * CustomiseProgressTask
 */

public abstract class CustomiseProgressTask extends AsyncTask<String,Integer,Long>{
   private Context context;
   private boolean cancelFlag;
   private ProgressDialog dialog;
   TextView progressmessage;

   protected abstract void onResulted(Long result);

   public CustomiseProgressTask(Context context){
      cancelFlag = false;
      this.context = context;
   }
   @Override
   protected void onPreExecute(){
      showDialog();
   }
   @Override
   protected Long doInBackground(String...params){
      int count=1;
      try{
      for(;count < 10;count++){
         if (isCancelled()){
            break;
         }
         Thread.sleep(1000);
         if (cancelFlag) break;
         // 進捗 Update
         publishProgress(count * 10);
      }
      }catch(InterruptedException e){
      }
      return (long)count;
   }
   @Override
   protected void onProgressUpdate(Integer...values){
      if (values[0]==50){
         // 中間でメッセージを変更
         progressmessage.setText("Step 2");
      }
   }
   @Override
   protected void onPostExecute(Long result){
      onResulted(result);
      dismissDialog();
   }
   @Override
   protected void onCancelled(){
      cancelFlag = true;
      dismissDialog();
      new AlertDialog.Builder(context)
      .setMessage("キャンセルされました")
      .setPositiveButton("OK",new DialogInterface.OnClickListener(){
         @Override
         public void onClick(DialogInterface _dialog,int which){
         }
      }).create().show();
   }

   private void showDialog(){
      LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
      final View view = inflater.inflate(R.layout.custom2progress,null);

      final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
      layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
      layoutParams.format = PixelFormat.TRANSLUCENT;


      progressmessage = (TextView)view.findViewById(R.id.progressmessage);
      progressmessage.setText("Loading data...");

      dialog = new ProgressDialog(context){
         @Override
         protected void onCreate(Bundle savedInstanceState){
            super.onCreate(savedInstanceState);
            setContentView(
view,layoutParams);
         }

      };
      dialog.setIndeterminate(false);
      dialog.setCancelable(true);   // キャンセル可
      dialog.setMax(100);           // publishProgress に合わせて最大値をセット
      dialog.setProgress(0);
      dialog.setOnCancelListener(new DialogInterface.OnCancelListener(){
         @Override
         public void onCancel(DialogInterface _dialog){
            cancel(true);
         }
      });
      dialog.show();
   }

   protected void dismissDialog() {
      if (dialog != null){
         dialog.dismiss();
         dialog = null;
      }
   }
}