2013-11-28 3 views
0

Я пытаюсь построить диалог, как этот (слой карты Google выбрать диалог):CustomDialog из DialogFragment в андроида

enter image description here

И это мои основные коды:

public class MapLayerSourceChooseDialog extends DialogFragment { 
    private MapLayerSelectedListener mListener; 
    private LayerAdapter mLayerAdapter; 

    public void setLayerSelectListener(MapLayerSelectedListener listener) { 
     mListener = listener; 
    } 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     mLayerAdapter = new LayerAdapter(getActivity(), R.layout.common_dialog_maplayer, new ArrayList<MapLayer>()); 
    } 

    @Override 
    public Dialog onCreateDialog(Bundle savedInstanceState) { 
     AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); 
     builder.setTitle("Layers").setAdapter(mLayerAdapter, new DialogInterface.OnClickListener() { 
      public void onClick(DialogInterface dialog, int which) { 

       if (mListener != null) { 
        MapLayer layer = mLayerAdapter.getItem(which); 
        mListener.OnMapLayerSelected(which, layer); 
       } 
      } 
     }); 
     Log.d("map", "dialog on create"); 
     return builder.create(); 
    } 

    public void updateData(List<MapLayer> layers) { 
     mLayerAdapter.updateItems(layers); 
    } 

    private class LayerAdapter extends ArrayAdapter<MapLayer> { 
     private List<MapLayer> mItems; 

     public LayerAdapter(Context context, int resource, List<MapLayer> items) { 
      super(context, resource, items); 
      mItems = items; 
     } 

     @Override 
     public View getView(int position, View convertView, ViewGroup parent) { 
      ViewHolder holder = null; 
      if (convertView == null || convertView.getTag() == null) { 
       convertView = getActivity().getLayoutInflater().inflate(R.layout.common_dialog_maplayer, parent, false); 

       holder = new ViewHolder(); 
       holder.iconView = (ImageView) convertView.findViewById(R.id.map_layer_icon); 
       holder.nameView = (TextView) convertView.findViewById(R.id.map_layer_name); 
       holder.checkView = (ImageView) convertView.findViewById(R.id.map_layer_check); 

       convertView.setTag(holder); 
      } else 
       holder = (ViewHolder) convertView.getTag(); 

      MapLayer layer = getItem(position); 
      holder.iconView.setImageDrawable(getResources().getDrawable(layer.drawable)); 
      holder.nameView.setText(layer.name); 
      holder.checkView.setVisibility(layer.isActive ? View.VISIBLE : View.GONE); 

      return convertView; 
     } 

     public void updateItems(List<MapLayer> layers) { 
      mItems.clear(); 
      mItems.addAll(layers); 
      // notifyDataSetChanged(); 
     } 
    } 

    private static class ViewHolder { 
     ImageView iconView; 
     TextView nameView; 
     ImageView checkView; 
    } 

    interface MapLayerSelectedListener { 
     void OnMapLayerSelected(int index, String name); 
    } 
} 

вызывающего абонента (при другом видах деятельности):

mapLayerSourceChooseDialog.updateData(layers); 
mapLayerSourceChooseDialog.show(getSupportFragmentManager(), null); 

Но я всегда получаю NPE, мне интересно если я использую диалог неправильно?

Может ли кто-нибудь проверить его для меня?

+0

Пожалуйста, разместите свой логарифм! –

ответ

1

Проблема в том, что вы предполагаете, что mLayerAdapter будет инициализирован к моменту звонка mapLayerSourceChooseDialog.updateData(layers). Это неправильно. После того, как вы создадите экземпляр MapLayerSourceChooseDialog, onCreate() не будет вызываться сразу.

два очевидных варианта:

  1. Подайте List<MapLayer> в качестве аргумента к фрагменту. Используйте методы setArguments() и на MapLayerSourceChooseDialog. Ваши объекты MapLayar должны быть не менее Serializable, но предпочтительно реализовать Parcelable. Обратите внимание, что вы, вероятно, не хотите идти по этому пути, если ваши объекты довольно сложны и/или размер списка достаточно велик.
  2. Определите интерфейс прослушивателя с геттером, который возвращает List<MapLayer>, который должен реализовывать Activity, содержащий фрагмент. В MapLayerSourceChooseDialog вы можете затем выполнить действие и вызвать getter для извлечения данных. Этот подход может быть быстрее реализован, но может нарушиться, если ваша деятельность не сохранит List<MapLayer> при изменении конфигурации.

Пример обоих подходов можно найти в documentation for DialogFragment.

Смежные вопросы