2016-08-12 117 views
2

社區! 我需要幫助更新ListView中的不可見項目。這不是關於項目內容,而是項目的視圖表示。好吧,讓我給你看我的例子。我有一個字符串數組:如何在ListView中更新某些不可見項目的視圖? [Android]

<string-array name="reminder_notifications"> 
    <item>15 minutes before</item> 
    <item>30 minutes before</item> 
    <item>1 hour before</item> 
    <item>1.5 hour before</item> 
    <item>5 hours before</item> 
    <item>8 hours before</item> 
    <item>1 day before</item> 
</string-array> 

在活動我創建適配器:

adapterNotifications = ArrayAdapter.createFromResource(this, R.array.reminder_notifications, R.layout.dialog_list_multiple_choise); 

後,用一些方法我計算whitch項目從字符串數組是avaliable當前提醒。例如。如果用戶在16:00設置提醒爲16:45,那麼他只能選擇項目15 minutes before30 minutes before。其他項目應該禁用。 所以,谷歌後,我發現瞭如何獲得在特定位置獲得無形的ListView孩子:

public View getViewByPosition(int position, ListView listView) { 
    final int firstListItemPosition = listView.getFirstVisiblePosition(); 
    final int lastListItemPosition = firstListItemPosition + listView.getChildCount() - 1; 
    if (position < firstListItemPosition || position > lastListItemPosition) { 
     return listView.getAdapter().getView(position, listView.getChildAt(position), listView); 
    } else { 
     final int childIndex = position - firstListItemPosition; 
     return listView.getChildAt(childIndex); 
    } 
} 

現在,我面臨着最後一個問題(我希望) - 如何更新項目的看法,我從得到上面的方法?我試圖用這樣的:

View v = getViewByPosition(position, lvNotifications); 
v.setEnabled(true); 

但它只有在第一次打開的對話框中查看更新,換句話說,我必須與ListView控件打開對話窗口,關閉並重新打開。只有在這種情況下,我才能看到更新的視圖。 我知道,我的英語很糟糕,所以有以下屏幕截圖:

主對話框。使用ListView打開對話框之前 Main dialog. Before opening the dialog with ListView

列表視圖對話框。首次開放。沒有項目被禁用。錯誤 List view dialog. First opening. No items are disabled. WRONG

列表視圖對話框。第二次開幕。 5項被禁用。 RIGHT List view dialog. Second opening. 5 items are disabled. RIGHT

謝謝。

回答

1

您從錯誤的一面處理了問題。您不應該從適配器外部編輯視圖,這是適配器的用途。相反,編寫你自己的適配器。像這樣做:

import android.content.Context; 
import android.support.annotation.NonNull; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.ArrayAdapter; 
import android.widget.BaseAdapter; 
import android.widget.CheckBox; 
import android.widget.CompoundButton; 
import android.widget.TextView; 

/** 
* A {@link ArrayAdapter} to let the user select multiple notification times. 
*/ 
public class ReminderNotificationsAdapter extends BaseAdapter implements CompoundButton.OnCheckedChangeListener { 

    /** 
    * A array with all currently selected entries 
    */ 
    private boolean[] mSelected; 

    /** 
    * A array with all enabled entries 
    */ 
    private boolean[] mEnabled; 

    /** 
    * The items to be shown 
    */ 
    private String[] mItems; 

    /** 
    * A {@link Context} 
    */ 
    private Context mContext; 

    /** 
    * Creates a new instance 
    * 
    * @param context a {@link Context} 
    * @param items all selectable items 
    * @param checkedItems all selected items. This array will be updated with the users selectiion 
    * @param enabledItems all enabled items 
    */ 
    public ReminderNotificationsAdapter(Context context, String[] items, boolean[] checkedItems, boolean[] enabledItems) { 
     // Check array sizes 
     if(items.length != checkedItems.length || checkedItems.length != enabledItems.length) { 
      throw new RuntimeException("All arrays must be the same size"); 
     } 

     // Add all and store params 
     this.mContext = context; 
     this.mItems = items; 
     this.mSelected = checkedItems; 
     this.mEnabled = enabledItems; 

    } 

    @Override 
    public int getCount() { 
     return this.mItems.length; 

    } 

    @Override 
    public String getItem(int i) { 
     return this.mItems[i]; 

    } 

    @Override 
    public long getItemId(int i) { 
     return this.getItem(i).hashCode(); 

    } 

    @NonNull 
    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     View v = convertView; 

     // Create view if not provided to convert 
     if(v == null) { 
      v = LayoutInflater.from(this.mContext).inflate(R.layout.dialog_list_multiple_choise, parent, false); 
     } 

     // Prepare text view 
     TextView tv = (TextView) v.findViewById(android.R.id.text1); 
     tv.setText(this.getItem(position)); 
     tv.setEnabled(this.isEnabled(position)); 

     // Prepare checkbox 
     CheckBox cb = (CheckBox) v.findViewById(android.R.id.checkbox); 
     cb.setTag(position); 
     cb.setChecked(this.mSelected[position]); 
     cb.setEnabled(this.isEnabled(position)); 
     cb.setOnCheckedChangeListener(this); 

     // Return view 
     return v; 

    } 

    @Override 
    public boolean isEnabled(int position) { 
     return this.mEnabled[position]; 

    } 

    @Override 
    public void onCheckedChanged(CompoundButton compoundButton, boolean b) { 
     this.mSelected[(Integer) compoundButton.getTag()] = b; 

    } 
} 

,並使用它像這樣:

@Override 
public void onClick(View view) { 
    // Tell what string should be shown 
    String[] entries = this.getResources().getStringArray(R.array.reminder_notifications); 

    // Tell what entries should be already selected 
    final boolean[] selectedEntries = new boolean[entries.length]; 
    selectedEntries[2] = true; 

    // Tell what entries should be enabled 
    boolean[] enabledEntries = new boolean[entries.length]; 
    enabledEntries[0] = true; 
    enabledEntries[1] = true; 
    enabledEntries[2] = true; 
    enabledEntries[3] = true; 

    // Create the adapter 
    ReminderNotificationsAdapter a = new ReminderNotificationsAdapter(this, entries, selectedEntries, enabledEntries); 

    // Create and show the dialog 
    new AlertDialog.Builder(this) 
      .setTitle("Add notification") 
      .setAdapter(a, null) 
      .setPositiveButton("Set", new DialogInterface.OnClickListener() { 
       @Override 
       public void onClick(DialogInterface dialogInterface, int i) { 
        // Do what you want to do with the selected entries 
        Toast.makeText(MainActivity.this, Arrays.toString(selectedEntries), Toast.LENGTH_SHORT).show(); 

       } 
      }) 
      .setNegativeButton("Dismiss", null) 
      .show(); 

} 

我只是用一個布爾數組告訴應啓用哪些條目和選擇,你可以,如果你做的東西更優雅有想。在提供給適配器構造函數的數組中更新用戶的選擇。該AlertDialog看起來是這樣的:

Screenshot

看到完整的示例應用程序here

+0

男人,你真棒。謝謝!並非常感謝您的解釋!告訴我什麼是更好的CheckedTextView或TextView + CheckBox? –

+1

CheckedTextView旨在與ListView和setMultipleChoiceItems(...)以及setSingleChoiceItems(...)配合使用,而不是像我的解決方案中那樣單獨使用或作爲普通視圖使用。使用TextView和RelativeLayout,完成後,這也支持RTL佈局,並且沒有視覺差異。查看我在回答結尾處鏈接的GitHub倉庫中使用的佈局。 我對我的解決方案做了一些細微的更改(用BaseAdapter替換了ArrayAdapter,更改了一些填充) – crysxd