2014-10-17 2 views
1

У меня есть listview в layout, и каждый элемент имеет две части: один - аватар пользователя (ImageView), а другой - содержание чата (TextView). Похоже:Связь между адаптером и активностью?

enter image description here

И у меня есть обычай adapter.

Я хотел бы реализовать: когда я нажимаю аватар, я могу пойти в галерею системы и выбрать фотографию в качестве аватара.

Так что мой код о onClickListener в adapter классе:

Intent itent = new Intent(Intent.ACTION_PICK, 
           MediaStore.Images.Media.EXTERNAL_CONTENT_URI); 


((Activity)(context)).startActivityForResult(itent, LOAD_IMAGE_RESULT); 

И я также переопределить метод onActivityResult активности.

Однако решение, упомянутое выше, не может изменить аватар в методе onActivityResult, потому что я не знаю, как общаться между adapter и activity.

Надежды на решение.

ответ

-1

В адаптере (не уверен, какой адаптер вы используете) вы устанавливаете onClickListener для ImageView. Следовательно,

mImageView.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View view) { 
       <INSERT CODE HERE> 
       mContext.startActivity(intent); 
     } 
    }); 

Где mImageView является ImageView для этого элемента. Также хорошей идеей может быть использование ImageButton, поскольку он позволяет Images и является кнопкой, которая вам нравится. Затем добавьте код, который вы хотите выбрать. Вам может потребоваться передать контекст и адаптеру (но вы, как правило, это все равно). Затем вы можете обработать метод onActivityResult в действии, в котором находится адаптер, т. Е. Установить изображение на выбранное изображение. Есть несколько способов сделать это.

+0

Какие проблемы возникают после того, как я нажму аватар, и выберите фотографию, как я обновляю аватар в методе onActivityResult? – chenzhongpu

-1

Добавить публичный метод в пользовательском адаптере, чтобы установить изображение (например, public void setAvatar(Bitmap image))

Затем в методе onActivityResult, получить выбранное изображение и использовать вновь созданный метод, чтобы установить новый образ в адаптере. (См здесь для получения дополнительной информации: Getting a Result from an Activity

Не забудьте поставить notifyDataSetChanged(); в конце вашего Ваш новый метод в адаптере, чтобы обновить все список

public void setAvatar(Bitmap image) 
{ 
    ... 

    imageView.setImageBitmap(image); 
    ... 

    notifyDataSetChanged(); 
} 

Кроме того, если вам нужно. знать, какие изображения была нажата, вы можете указать Integer в качестве параметра и проверить его в onActivityResult.
Я вижу, вы используете постоянный LOAD_IMAGE_RESULT для этого параметра. Вместо постоянной, положить целое число, которые идентифицировать щелкнул элемент.

+0

Я должен знать, какой элемент щелкнуть по методу onActivityResult. Но как я могу его получить? Должен ли я иметь глобальную переменную для представления этого? – chenzhongpu

+0

Выдержка из сайта android dev: _ Нет ничего особенного в объекте Intent, который вы используете при запуске действия для результата, но вам нужно передать дополнительный целочисленный аргумент методу startActivityForResult(). Целый аргумент - это «код запроса», который идентифицирует ваш запрос. Когда вы получаете результат Intent, обратный вызов предоставляет один и тот же код запроса, чтобы ваше приложение могло правильно идентифицировать результат и определить, как его обрабатывать ._ Я отредактирую свой ответ. В ожидании см. Это: [dev page] (http://developer.android.com/training/basics/intents/result.html#StartActivity) –

0

Вы должны сохранить ссылку на щелчок в методе onClickListener и иметь общедоступный метод в своем адаптере.Когда вы получите ответ в методе onActivityResult вызывается метод адаптера и использовать

2

EDIT - Сначала я только что показал один из метода обновления ребенка рассматривает только оставив это адаптер в неустойчивом состоянии (, потому что исходный вопрос не дает много информации о базовой структуре данных).

Адаптер: адаптер объект действует в качестве моста между AdapterView и исходными данными для этой точки зрения. Адаптер обеспечивает доступ к элементам данных . Адаптер также несет ответственность за создание представления для каждого элемента в наборе данных.

Примечание:Поскольку определение сам описывает, что очень важно для поддержания состояния средств (данные + вид). Поэтому вы всегда должны иметь постоянный пользовательский интерфейс.

Чтобы правильно привести пример, я также определил класс модели данных ItemData на основе предположения о заданном изображении в исходном вопросе.

/** 
* Model Class 
*/ 
public class ItemData { 

    private Uri imageUri; 
    private String msg; 
    private Date timeStamp; 

    public void setImageUri(Uri uri) { 
     this.imageUri = uri; 
    } 

    public Uri getImageUri() { 
     return this.imageUri; 
    } 

    ... 
} 

CustomAdapter

Создайте специальный адаптер для ListView, который будет поддерживать мнения ребенка с его набором данных соответственно. Вы должны сохранить ссылку на последний выбранный индекс строки lastSelectedIndexRow, который может быть использован позже для обновления вида.

Примечание:Чтобы получить представление для любого индекса в listView, мы не должны вызывать getView() метод адаптера. Поскольку вызов getView() с нулевым значением для convertView заставляет адаптер раздуть новый вид из ресурса макета адаптера (не получает представление, которое уже отображается).

AdapterView всегда должна быть обновлена ​​с notifyDataSetChanged() на основе текущего удержания набора данных адаптером.

public class CustomAdapter extends BaseAdapter { 

    private Context context; 
    private LayoutInflater inflater; 

    private List<ItemData> dataList; 

    private int lastSelectedRowIndex = -1; 
    public static int LOAD_IMAGE_RESULT = 201; 

    public CustomAdapter(Context context, ArrayList<ItemData> dataList) { 

     // hold the items 
     this.context = context; 
     this.dataList = dataList; 

     this.inflater = LayoutInflater.from(this.context); 
    } 

    @Override 
    public int getCount() { 
     return (dataList != null && !dataList.isEmpty()) ? dataList.size() : 0; 
    } 

    @Override 
    public ItemData getItem(int position) { 
     return (dataList != null && !dataList.isEmpty()) ? dataList.get(position) : null; 
    } 

    @Override 
    public long getItemId(int position) { 
     return 0; 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 

     ViewHolderItem viewHolder; 
     if (converView == null) { 

      // inflate the layout 
      convertView = inflater.inflate(R.layout.row_item, parent, false); 

      // well set up the ViewHolder 
      viewHolder = new ViewHolderItem(); 
      viewHolder.avatar = (ImageButton)view.findById(R.id.avatar); 

      // store the holder with the view. 
      convertView.setTag(viewHolder);  
     } 
     else { 
      // we've just avoided calling findViewById() on resource every time 
      // just use the viewHolder 
      viewHolder = (ViewHolderItem) convertView.getTag(); 
     } 

     // Set row data 
     ItemData data = (ItemData)getItem(position); 
     if (data != null) { 

      // set message 
      viewHolder.message.setText(data.getMessage()); 

      // set formatted timestamp 
      String formattedTimeStamp = ...; // convert data.getTimeStamp() into formatted version 
      viewHolder.timeStamp.setTextView(formattedTimeStamp); 

      // set Image and also it's action. 
      viewHolder.avatar.setImageUri(data.getImageUri()); 
      viewHolder.avatar.setOnClickListener(new View.OnClickListener() { 

       @Override 
       public void onClick(View view) { 
        try { 

         Intent intent = new Intent(Intent.ACTION_PICK, 
          MediaStore.Images.Media.EXTERNAL_CONTENT_URI); 

         ((Activity)context).startActivityForResult(intent, LOAD_IMAGE_RESULT); 
        } catch (Exception e) { 
        Log.e("Demo application", "Failed to invoke call", e); 
        } 
       } 
      } 
     } 
    } 

    /** 
    * Get the last selected item index 
    * 
    */ 
    public int getLastSelectedItemIndex() { 
     return lastSelectedRowIndex; 
    } 

    /** 
    * Update the adapater with new data 
    * 
    */ 
    public void updateItems(List<ItemData> dataList) { 

     if (this.dataList != dataList) 
      this.dataList = dataList; 

     // update the view. 
     notifyDataSetChanged(); 

     // reset the last selection 
     lastSelectedRowIndex = -1; 
    } 

    /** 
    * Hold View items 
    */ 
    static class ViewHolderItem { 

     private ImageView avatar; 
     private TextView message; 
     private TextView timeStamp; 
    } 
} 

ExampleActivity

В деятельности, вы, к определенной ссылке заказного адаптера и обработке результатов выбора изображения в onActivityResult() методе. После того, как вы получите выбранное изображение из галереи, обновите базовые данные, содержащиеся внутри dataList, а также обновите адаптер, вызвав метод updateItems().

Способ адаптера updateItems() принимает новый список данных в качестве аргумента и аннулирует адаптерView, вызывая notifyDataSetChanged().

public class ExampleActivity extend FragmentActivity { 

    private ListView listView; 
    private CustomAdapter adapter; 

    private List<ItemData> dataList; 

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

     dataList = ...; // Load the list from database 

     // Create the custom adapter with filled list items. 
     adapter = new CustomAdapter(this, dataList); 

     // List View and set the data adapter 
     listView = (ListView)findViewById(R.id.listView); 
     listView.setAdapter(adapter); 
    } 

    @Override 
    protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
     super.onActivityResult(requestCode, resultCode, data); 

     // Check if it's coming from MediaStore Selection. 
     if (resultCode == Activity.RESULT_OK && 
        requestCode == CustomAdapter.LOAD_IMAGE_RESULT) { 

      // Get the selected rowIndex 
      if (adapter != null && dataList != null) { 

        // check the row index is valid 
        int rowIndex = adapter.getLastSelectedItemIndex(); 
        if (rowIndex > -1 && rowIndex < dataList.size()) { 

         // Get the item 
         ItemData item = dataList.get(rowIndex); 

         // Update the item with imageUri 
         item.setImageUri(Uri.parse(data.getData())); 

         /** 
         * If you may want to update the information in database, 
         * then it's the best place, but please do in background thread. 
         */ 

         //Now notify the adapter with new changes 
         adapter.updateItems(dataList); 
        } 
      } 
     } 
    } 

    ... 
} 
+0

Это все неправильно. Адаптер должен всегда отображать текущее состояние, и его нужно обновлять только при вызове 'notifyDataSetChanged'. –

+1

@PaulBurke - Я согласен, очевидно, адаптер должен поддерживать текущее состояние данных w.r.t. И для этого структура данных, в которой хранится информация для отображения списка, должна обновляться с новой информацией, а затем аннулировать адаптер, вызывая 'notifyDataSetChanged'. Однако исходный вопрос не показывает фрагмент фрагмента кода, который содержит информацию об «выбранном изображении», поэтому я просто показал один из способов просто обновить только просмотр. – Deminem

+0

Вместо того, чтобы показывать OP, как сделать его плохой код работать, было бы более полезно объяснить, как правильно это сделать. Ваш ответ неполный и неправильный с точки зрения Android. Что происходит при изменении конфигурации, или если система во время паузы убивает приложение? –

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