選択ダイアログ:カスタムコントロール+カスタムダイアログ

13175 ワード

プロジェクトの必要性のため、選択ダイアログを使用する必要があります.システムを使用してコントロールを持参すれば実現できますが、長期的な観点から見ると、本プロジェクトの発展に不利です.そこで、自分でカスタムコントロールを作って、組み合わせコントロールを使って、ついでに組み合わせコントロールの作成を学びました.
カスタムコントロールにはいろいろな方法がありますが、具体的には言及しません.今回は組み合わせコントロールだけを使って、まず図を見て、今回実現した効果について直感的に認識させます.
上の図に示すように、「ブラウズモード」をクリックすると、選択ダイアログボックスがポップアップされます(注意:このボタンにはタイトルと現在の選択項目があり、右側にはユーザーにヒントを与えるアイコンがあります).このダイアログボックスはカスタムダイアログボックスを使用できます.このような実現に対して、私が考えている可能性のあるいくつかの方法は:
  • ListPreferenceを使用
  • 難点1:PreferenceActivityの背景色を使って選択できますか?個人的には
  • を変更できると思います.
  • 難点2:Preferenceはデータを保存するのではないでしょうか.データを保存しない場合はどうすればいいですか?検証の結果、persistenceプロパティを設定して、データ
  • を保存しないようにすることができます.
  • 難点3:ダイアログのレイアウトを変更できますか?できるはずです.私は確信していません.証明書
  • を待っています.
  • Spinnerを使用
  • 難点1:ホームページ(タイトル、現在のオプション、右にアイコンを1つ追加)にコンビネーションダイアログを表示すれば解決できるはずですが、面倒そうな
  • 難点2:ダイアログのレイアウトを変更できますか?できるはずです.私は確信していません.証明書
  • を待っています.
  • 完全カスタム
  • 難点1:コントロールの美しさ?画像で解決できるはずです.
  • 難点2:ダイアログボックスをポップアップしてオプションを選択すると、対応する内容が変更されます.
  • 難点3:カスタムダイアログレイアウト

  • 最初にやったとき、検証する情報が足りなかったかもしれないので、最初の2つの方法は実現を求めず、その時最後の方法を選んだ.
    カスタムコントロールを選択し、次の変数を持つクラスListSelectView extends LinearLayoutを定義しました.
    	private TextView tvHeader;    //Item    
    	private TextView tvContent;   //Item   
    	
    	private CharSequence[] mEntries;   //      
            private CharSequence[] mEntryValues;  //        
    	private int mClickedDialogEntryIndex; //      index

    1、itemプロジェクトの実現
    まずホームページのitem項目です.
    次のレイアウトが定義されています.
    
    
        
        
        	
        	
        
        
    
    

    このようなレイアウトをほぼ実現し、attrs.xmlには2つのプロパティが定義されています(状況に応じて追加できます)
        
            
            
        

    その後ListSelectViewコンストラクタでコントロールおよびステータスを初期化
    	public ListSelectView(Context context, AttributeSet attrs) {
    		super(context, attrs);
    		LayoutInflater.from(context).inflate(R.layout.list_select_layout, this, true);
    		TypedArray a = context.obtainStyledAttributes(attrs, org.lansir.R.styleable.ListSelectView, 0, 0);
    		mEntries = a.getTextArray(org.lansir.R.styleable.ListSelectView_entries);  //        
    		mEntryValues = a.getTextArray(org.lansir.R.styleable.ListSelectView_entryValues);
    		a.recycle();
    
    		tvHeader = (TextView) findViewById(R.id.tvListSelectLayoutTitle);  //     
    		tvContent = (TextView) findViewById(R.id.tvListSelectLayoutContent);
    		tvHeader.setTextColor(Color.BLACK);  //      
    		tvContent.setGravity(Gravity.TOP);
    		this.setOnClickListener(this); //      
    	}

    得られた効果は以上のように,具体的な美工は後期にマッピングによって実現できる.
    これでItemエントリの初期化が完了しました
    2、ダイアログの実現
    次に、ダイアログの表示を行います.
    前節では、クリックイベントを設定しました.イベントの内容は次のとおりです.
    	@Override
    	public final void onClick(View v) {
    
    		SingleSelectionDialog dialog = new SingleSelectionDialog.Builder(this.getContext()).setTitle(tvHeader.getText()).setSingleChoiceItems(mEntries,
    				mClickedDialogEntryIndex, new DialogInterface.OnClickListener() {
    
    					@Override
    					public void onClick(DialogInterface dialog, int which) {
    						mClickedDialogEntryIndex = which;
    						tvContent.setText(mEntryValues[mClickedDialogEntryIndex]);
    						dialog.dismiss();
    					}
    
    				}).create();
    
    		dialog.show();
    
    
    	}

    ここでダイアログをカスタマイズします.SingleSelectionDialogはDialogから継承されたクラスです.AlertDialogから継承されないのは、AlertDialogがコンテンツをカスタマイズし、DialogクラスよりもStyleが面倒で、複雑な方法で実現しなければならないからです.また、ここでsetSingleChoiceItemsはSingleSelectionDialogクラスがカスタマイズしたカプセル化方法であり、ここではダイアログリストオプションの値とイベントを設定し、このイベントではオプションのIndexを設定し、次回ダイアログを再度クリックするときに設定された値に設定するとともに、ホームページItemオプション値tの内容を変更し、ダイアログを閉じる.
    SingleSelectionDialogのコードは以下のように実現される.
    public class SingleSelectionDialog extends Dialog {
    
    	public SingleSelectionDialog(Context context, boolean cancelable,
    			OnCancelListener cancelListener) {
    		super(context, cancelable, cancelListener);
    
    	}
    
    	public SingleSelectionDialog(Context context, int theme) {
    		super(context, theme);
    	}
    
    	public SingleSelectionDialog(Context context) {
    		super(context);
    	}
    
    	public static class Builder {
    
    		private Context context;
    		private CharSequence title;  //     
    		private CharSequence[] mListItem; //      
    		private int mClickedDialogEntryIndex;  //     Index
    		private DialogInterface.OnClickListener mOnClickListener;  //       
    
    		public Builder(Context context) {
    			this.context = context;
    		}
    
    		public Builder setTitle(int title) {
    			this.title = (String) context.getText(title);
    			return this;
    		}
    
    		public Builder setTitle(CharSequence title) {
    			this.title = title;
    			return this;
    		}
    
    		public CharSequence[] getItems() {
    			return mListItem;
    		}
    
    		public Builder setItems(CharSequence[] mListItem) {
    			this.mListItem = mListItem;
    			return this;
    		}
    		
    		//    List     ,        create   ,    Android    dialog   
    		public Builder setSingleChoiceItems(CharSequence[] items, int checkedItem, final OnClickListener listener) {
    			this.mListItem = items;
                            this.mOnClickListener = listener;
                            this.mClickedDialogEntryIndex = checkedItem;
                            return this;
                    } 
    
    	
    		public SingleSelectionDialog create() {
    			LayoutInflater inflater = (LayoutInflater) context
    					.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    			final SingleSelectionDialog dialog = new SingleSelectionDialog(
    					context, R.style.Theme_Dialog_ListSelect);
    			View layout = inflater.inflate(R.layout.single_selection_dialog,
    					null);
    			dialog.addContentView(layout, new LayoutParams(
    					LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
    			
    			if(mListItem == null){
    				throw new RuntimeException("Entries should not be empty");
    			}
    			ListView lvListItem = (ListView) layout.findViewById(R.id.lvListItem);
    //			android.R.layout.simple_list_item_single_choice
    			//lvListItem.setAdapter(new ArrayAdapter(context, android.R.layout.simple_list_item_single_choice, android.R.id.text1, mListItem));
    //			SingleSelectionAdapter mSingleSelectionAdapter = new SingleSelectionAdapter(context, R.layout.single_list_item, R.id.ctvListItem, mListItem);
    //			lvListItem.setAdapter(mSingleSelectionAdapter);
    			lvListItem.setAdapter(new ArrayAdapter(context,  R.layout.single_selection_list_item, R.id.ctvListItem, mListItem));
    			lvListItem.setOnItemClickListener(new OnItemClickListener(){
    
    				@Override
    				public void onItemClick(AdapterView> parent, View view,
    						int position, long id) {
    					mOnClickListener.onClick(dialog, position);
    
    				}
    				
    			});
    			lvListItem.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
    			lvListItem.setItemChecked(mClickedDialogEntryIndex, true);
    			lvListItem.setSelection(mClickedDialogEntryIndex);
    		
    
    			TextView tvHeader = (TextView)layout.findViewById(R.id.title);
    			tvHeader.setText(title);
    					
    			
    			return dialog;
    		}		
    		
    	}
    
    }
    

    setSingleSelectItemsは、createで使用されるラジオリストのItemおよびイベントを設定します.
    最も重要なのはcreate()メソッドで、ここでdialogのトピックを初期化します.
  • キャンセルタイトル
  • 縁取りをキャンセル
  • 透明
  • を使用
    スタイルスタイルは次のとおりです.
    	

    次にsetContentを使用してコンテンツを初期化します.ここでは、カスタムレイアウトを使用して作成します.xmlレイアウトファイルは次のとおりです.
    
    
             //  
    	
    
    		
    	
            //  
    	
    		
    
    	//  
    	
    
    

    レイアウト全体は、ヘッダ、コンテンツ、下部に分かれています.ヘッダはタイトルを表示し、コンテンツはラジオリストを表示し、下部はダイアログボックスを美化するために使用されます.
    次に、adapterのlayoutがlistオプションのスタイルを設定するようにAdapterを設定します.

    このlayoutをする時、当初は確かにどのようにするか分からなかったが、自分でTextViewとRadioButtonを定義して解決しようとしたが、その後、このような解決方法はずっと理想的ではないことに気づいた.主な問題はラジオボタンをどのように設定し、ラジオ機能を実現するかだった.カスタマイズしたAdapterでは、どのitemが選択されているかを検出する必要がありますが、ListViewのキャッシュメカニズムがこの方法の複雑さを増しているため、バッファを作成し、ラジオの状態を保存しなければなりません.また、システムDialogのソースコードを見てみると、キャッシュオプションの状態を使用して実現されていることがわかりました.では、私たちはどうして自分で定義し、自分で実現しなければならないのですか.そんなに複雑なのに、なぜそれを使用しないのですか.そこでandroidを参照しました.R.layout.simple_list_item_single_choiceはファイルの内容をレイアウトし、CheckedTextViewのコントロールを使用していることを発見しましたが、システムのデフォルトのラジオスタイルは望んでいません.そこで、自分でCheckedTextViewをカスタマイズし、ラジオスタイル(android:checkMark)を変更しました.
    レイアウトを作成し、最後の統合を開始します.つまり、ラジオ・リストを設定し、問題が発生しやすい場所です.
    			ListView lvListItem = (ListView) layout.findViewById(R.id.lvListItem);
    			lvListItem.setAdapter(new ArrayAdapter(context,  R.layout.single_selection_list_item, R.id.ctvListItem, mListItem));
    			lvListItem.setOnItemClickListener(new OnItemClickListener(){
    
    				@Override
    				public void onItemClick(AdapterView> parent, View view,
    						int position, long id) {
    					mOnClickListener.onClick(dialog, position);
    
    				}
    				
    			});
    			lvListItem.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
    			lvListItem.setItemChecked(mClickedDialogEntryIndex, true);
    			lvListItem.setSelection(mClickedDialogEntryIndex);
    システムカスタムAdapterを使用すると、上記のキャッシュオプションのステータスのような多くの問題を解決できることがわかりました.ここでは、あまり凝っていないように見えますが、実は凝っています.setChoiceModeはsetItemCheckedの前に呼び出さなければなりません.そうしないとsetChoiceModeは失効します.これもAndroidのListViewのソースコードを見てから発見しました.
    このように、ダイアログボックスを選択します:カスタムコンビネーションコントロール+カスタムダイアログボックスが完了し、使用が非常に簡単で、自分で多くの設定をする必要はありません.私のActivity全体は次のようになります.
    public class SharePrefersActivity extends Activity {
        
    	private ListSelectView mListSelectView;
    	
    	
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            mListSelectView = (ListSelectView)findViewById(R.id.lsvTest);
            mListSelectView.setHeader("Hello");
            mListSelectView.setContent("world");
    
        }
    

    次のような効果を実現し、スクリーンショットを記念することができます.
    これで大功を成し遂げた.
    3、注意オプション
    このDEMOを作るとき、ホームページItemのselectを設定したいので、コンストラクション関数でthisを使います.setBackground()を設定すると、xmlでListSelectViewにpaddingLeft,layout_を設定します.marginなどの属性は無効になりますが、ここではこの間違いを覚えて、後の人に注意してください.
    ソースのダウンロード
    著作権はすべて、転載して出典を明らかにしてください!