2013-02-26 52 views
0

我有一個片段,它包含我的應用程序的所有配置文件的列表。該列表使用自定義BaseAdapter。以下是此適配器的規格:開關自定義BaseAdapter問題

  • 用戶一次只能啓用一個配置文件。
  • 如果用戶嘗試禁用所有配置文件,則用戶將被警告並且上次啓用的配置文件將被設置爲啓用。
  • 如果用戶嘗試啓用未配置的配置文件,將會警告用戶,並且上次啓用的配置文件將設置爲啓用。
  • 用戶可以配置每個配置文件。

一切工作發現除,這裏是我目前的執行存在的第一次創建列表中的一個問題:

  • 如果用戶啓用(用戶檢查開關)在第一輪廓列表第一次創建列表,然後嘗試啓用另一個配置文件,第一個仍然被選中(Switch仍然被選中)。另請注意,即使選中了第一個配置文件,實際啓用的配置文件也將是稍後檢查的配置文件。
  • 如果選擇其他配置文件,則不會發生這種情況。每當啓用其他 配置文件時,所有其他配置文件都被禁用。
  • 但是,活動暫停並恢復後,一切工作 像預期的那樣。意思是第一個開關仍然 獲得檢查問題將消失。

下面是此問題的圖形表示: enter image description here

下面是該片段承載BaseAdapter(AdapterProfiles)的代碼。 PreferenceData是處理與共享偏好:

public class Profiles extends Fragment implements OnCustomClickListener { 

private View view_profiles; 
private ListView lv_profiles; 

private PreferenceData dataPreferenceObj; 

private AdapterProfiles adapter; 
private ArrayList<String> profileList = new ArrayList<String>(); 
private final ArrayList<HashMap<String, String>> profilesList = new ArrayList<HashMap<String, String>>(); 

public View onCreateView(LayoutInflater inflater, ViewGroup container, 
     Bundle savedInstanceState) { 
    // ... 
    lv_profiles = (ListView) view_profiles.findViewById(R.id.lv_profiles); 
    // ... 
} 

@Override 
public void onResume() { 
    createProfileList(); 
    // Registers broadcast receiver 

    super.onResume(); 
} 

private void createProfileList() { 
    if (profilesList.isEmpty() == true) { 
     profileList = new ProfileList().getProfileList(); 

     for (int i = 0; i < profileList.size(); i++) { 
      HashMap<String, String> map = new HashMap<String, String>(); 
      map.put(Keys.KEY_PROFILE.toString(), profileList.get(i)); 
      profilesList.add(map); 
     } 
    } 

    adapter = new AdapterProfiles(getActivity(), profilesList, this); 
    lv_profiles.setAdapter(adapter); 
} 

/* 
* This is a custom onclick listener that gets handle from of list from 
* LazyAdapterProfiles 
*/ 
@Override 
public void OnCustomClick(View view, int position) { 
    switch (view.getId()) { 
    case R.id.iv_profiles_settings: 
     // Opens setting for settings of profile clicked on 
     break; 
    case R.id.sw_profiles: 
     Switch sw_profiles = (Switch) view.findViewById(R.id.sw_profiles); 

     // Stops user from enabling profile that is not configured. 
     if (dataPreferenceObj.getTemporaryRingtoneUri().equals("") == true 
       || dataPreferenceObj.getTemporaryLocation().equals("") == true) { 
      sw_profiles.setChecked(false); 

      showWarningDialog(
        "Profile Disabled", 
        "Profile location and ringtone must be selected in order to enable this profile."); 
     } else if (dataPreferenceObj.getTemporaryRingtoneUri().equals("") != true 
       && dataPreferenceObj.getTemporaryLocation().equals("") != true) { 
      if (sw_profiles.isChecked() == true) { 
       unselectProfileState(position); 
      } else if (sw_profiles.isChecked() == false) { 
       // Stops user from disabling profile as atleast one profile 
       // must be enabled 
       showWarningDialog("Profile Cannot Disable", 
         "Atleast one profile must be enabled"); 

       sw_profiles.setChecked(true); 
      } 

      // Rest of the code that writes the preference and broadcast it 
     } 
     break; 
    } 
} 

// Gets switch map of all profiles and uncheck profile other than one that 
// is selected. 
private void unselectProfileState(int position) { 
    for (int i = 0; i < profileList.size(); i++) { 
     if (position != i) { 
      AdapterProfiles.getMapHolder().get(i).sw_profiles 
        .setChecked(false); 
     } 
    } 
} 

}

我有一個自定義BaseAdapter及其各行持有的TextView,ImageView的和開關,一切類看起來像下面: enter image description here

這是我實現的是,在列表中創建行BaseAdapter的:

public class AdapterProfiles extends BaseAdapter { 

private ArrayList<HashMap<String, String>> data; 
private static LayoutInflater inflater = null; 

private String profile_name; 
private String retrived_profile_name; 

private ViewHolder holder; 
private Activity activity; 

private OnCustomClickListener callback; 
private static SparseArray<ViewHolder> mapHolder = new SparseArray<ViewHolder>(); 

public AdapterProfiles(Activity activity, 
     ArrayList<HashMap<String, String>> data, 
     OnCustomClickListener callback) { 

    this.activity = activity; 
    this.data = data; 
    this.callback = callback; 

    inflater = (LayoutInflater) activity 
      .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
} 

public AdapterProfiles(Activity activity, 
     ArrayList<HashMap<String, String>> data) { 
    this.data = data; 

    inflater = (LayoutInflater) activity 
      .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
} 

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

    if (convertView == null) { 
     convertView = inflater.inflate(R.layout.ui_profiles_row, null); 

     holder = new ViewHolder(); 

     holder.tv_profiles_name = (TextView) convertView 
       .findViewById(R.id.tv_profiles_name); 
     holder.tv_profiles_location_name = (TextView) convertView 
       .findViewById(R.id.tv_profiles_location_name); 
     holder.iv_profiles_settings = (ImageView) convertView 
       .findViewById(R.id.iv_profiles_settings); 
     holder.sw_profiles = (Switch) convertView 
       .findViewById(R.id.sw_profiles); 

     holder.iv_profiles_settings 
       .setOnClickListener(new CustomOnClickListener(callback, 
         position)); 
     holder.sw_profiles.setOnClickListener(new CustomOnClickListener(
       callback, position)); 

     convertView.setTag(holder); 

     mapHolder.put(position, holder); 
    } else { 
     holder = (ViewHolder) convertView.getTag(); 
    } 

    getPrefs(position); 
    setUIData(); 

    return convertView; 
} 

private void getPrefs(int position) { 
    HashMap<String, String> word = new HashMap<String, String>(); 
    word = data.get(position); 

    profile_name = word.get(Keys.KEY_PROFILE.toString()); 

    SharedPreferences settings = activity.getSharedPreferences(
      Keys.PREFS_APP.toString(), 0); 
    // This allows us to retrive unique data based on the profile names 
    String PROFILE_LOCATION = Keys.KEY_LOCATION.toString() + "_" 
      + profile_name; 
    retrived_profile_name = settings.getString(Keys.KEY_PROFILE.toString(), 
      ""); 
} 

// Sets UI data of item in the list 
private void setUIData() { 
    if (profile_name.equals(retrived_profile_name) == true) { 
     holder.sw_profiles.setChecked(true); 
    } else if (profile_name.equals(retrived_profile_name) == false) { 
     holder.sw_profiles.setChecked(false); 
    } 
} 

public static class ViewHolder { 
    public ImageView iv_profiles_settings; 
    public TextView tv_profiles_location_name; 
    public TextView tv_profiles_name; 
    public Switch sw_profiles; 
} 

public static SparseArray<ViewHolder> getMapHolder() { 
    return mapHolder; 
} 

}

終於這裏是CustomOnClickListener類,如果有人想知道它是什麼。這個類的實現是將回調映射到列表中的特定組件。這個類最初是由某人創建的(我沒有在我的書籤中找到它來稱讚作者),我使用他/她的示例來適合我自己的實現。下面是該代碼:

public class CustomOnClickListener implements OnClickListener { 
private int position; 
private OnCustomClickListener callback; 

public CustomOnClickListener(OnCustomClickListener callback, int position) { 
    this.position = position; 
    this.callback = callback; 
} 

@Override 
public void onClick(View v) { 
    callback.OnCustomClick(v, position); 
} 

} 

public interface OnCustomClickListener { 
    public void OnCustomClick(View view, int position); 
} 

回答

0

現在,這似乎是在這裏實現我自己的方法來取消選擇所有其他交換機-ES在適配器的時候我知道,notifyDataSetChanged()方法將刷新視圖改變愚蠢的。現在,我似乎被刪除這些代碼已經解決了這個問題:

if (sw_profiles.isChecked() == true) { 
       unselectProfileState(position); 
      } 

private void unselectProfileState(int position) { 
for (int i = 0; i < profileList.size(); i++) { 
    if (position != i) { 
     AdapterProfiles.getMapHolder().get(i).sw_profiles 
       .setChecked(false); 
    } 
} 

}

而且在OnCustomClick情況下R.id.sw_profiles的末尾添加以下。如前所述,這裏是Android文檔對此方法的快速描述「通知附加的觀察者,底層數據已更改,並且任何反映數據集的視圖都應刷新自身。」

adapter.notifyDataSetChanged();