2011-01-12 64 views
2

我的应用程序有一个ListPreference,其条目来自网络API。在我的PreferenceActivity的onCreate()中,我产生了一个后台线程,它使API调用,然后在一两秒后填充ListPreference的条目。Android:防止首选项的首选项对话框必须通过网络加载

如果用户在下载选项之前单击首选项屏幕上的ListPreference按钮,我想阻止显示首选项对话框,而是通知用户选项列表仍在加载中。

我怀疑是正确的做法是重写OnPreferenceClickListener,就像这样:

ListPreference dpref = (ListPreference) findPreference("debug"); 
String[] s = {"one", "two", "three"}; 
dpref.setEntries(s); 
dpref.setEntryValues(s); 
dpref.setOnPreferenceClickListener(new OnPreferenceClickListener() { 
    @Override 
    public boolean onPreferenceClick(Preference preference) { 
     Toast.makeText(this, "hi there", Toast.LENGTH_SHORT).show(); 
     return true; 
    } 
}); 

的面包被显示,但显示的ListPreference选择对话框为好。 OnPreferenceClickListener documentation表示如果处理点击,onPreferenceClick应返回true,但返回false具有相同的结果。

如何防止显示偏好对话框?

有没有更好的方法来处理在浏览前必须下载选项的偏好?

回答

1

我不知道为什么你的方式是行不通的,但这里是一个快速的解决方法解决:

添加存根Preference为应下载每首。您可以通过任何您想要的方式自定义您的操作。没有对话框会显示。

当您的首选项已准备就绪时,remove旧的首选项(按其名称)并使用您的选项创建新的ListPreference(与刚删除的名称相同的名称)。

这会给您一个灵活性,可以在您需要的任何事件上添加任何种类的自定义首选项。尽管如您所见,但仍需要一些额外的编码。

+0

这是我落得这样做。谢谢! – Noah 2011-01-29 20:57:48

+0

我必须这样做。您是否找到了将新偏好设置放在已删除的PreferenceScreen(在我的情况下)而不是将其添加到列表末尾的方法? – lapis 2011-09-06 15:38:02

+0

我自己找到了答案:我将容器的OrderingAsAdded设置为false,并且在更换首选项期间,我根据列表中的当前位置设置每个首选项的顺序,因此我只需将相同的顺序分配给新的首选项首选项。 – lapis 2011-09-06 15:51:07

0

我会使用代理Activity(样式为对话框)下载首选项,并在完成后启动实际的PreferenceActivity

0

你可以在你的偏好活动onResume()如下:

  • 启动async call到...
    • 的偏好设置为禁用一个暗示,值被提取
    • 网络提取值(无论是没有值还是始终) - 异步,因此它不会停止继续使用提取的值更新首选项条目
    • 启用偏好和显示默认的提示

的缺点,如果这是你的偏好要么太频繁更新(例如总是自己的喜好屏幕启动时),但是有了这个,你可以处理当网络调用的结果产生一个列表,其中之前选定的值不再存在的情况下(例如,向用户显示其表示他的选择不再可用的对话)。

此外,这是一个相当复杂的任务(因为你必须定义一个Handler,因为异步执行住在另一个线程...)

它看起来像这样(假设你在做你的PreferenceActivity

import android.os.Handler; 
import android.os.AsyncTask; 
import android.os.Message; 

public class xyz extends PreferenceActivity { 
    ... 
    // define a handler to update the preference state 
    final Handler handler = new Handler() { 
     public void handleMessage(Message msg) { 
      ListPreference dpref = (ListPreference) getPreferenceManager().findPreference("debug"); 
      dpref.setEnabled(msg.getData().getBoolean("enabled")); 
      dpref.setSummary(msg.getData().getString("summary")); 
     } 
    }; 



    private class updatePref extends AsyncTask<Void, Void, Void> { 

     @Override 
     protected Void doInBackground(Void... arg) { 

      Message msg = handler.obtainMessage(); 
      Bundle data = new Bundle(); 
      data.putBoolean("enabled", false); // disable pref 
      data.putString("summary", "Getting vals from network..."); // set summary 
      msg.setData(data); 
      handler.sendMessage(msg); // send it do the main thread 

      ListPreference dpref = (ListPreference) getPreferenceManager().findPreference("debug"); 


      String values[]; 
      // call network function and let it fill values[] 

      // do things according to the returned values, 
      // eg check if there are any, check if the user has 
      // already selected one, display a message if the 
      // user has selected one before but the values do not 
      // contain them anymore, ... 

      // set the new values  
      dpref.setEntries(values); 
      dpref.setEntryValues(values); 

      data.putBoolean("enabled", true); // enable pref 
      data.putString("summary", "Please choose"); // set summary 
      msg.setData(data); 
      handler.sendMessage(msg); // send it do the main thread 

      return null; 
     } 
    } 

    public void onResume() { 
     .... 
     new updatePref().execute(); 

    } 

} 

当然你也可以拨打new updatePref().execute()任何地方,所以你也可以将它绑定到一个ButtononCreate()或徘徊无论(没有必要onResume()做到这一点)。

6

我在同一个问题上苦苦挣扎,但在一个更简单的环境中。我的PreferenceScreen是在一个xml文件中定义的。有一种偏好我想处理自己。所以我干脆把“首选项”对象到XML文件,而不是一个“ListPreference”或“EditTextPreference”

<Preference android:title="@string/preloadmaps1" android:summary="@string/preloadmaps2" 
     android:key="preloadMaps" /> 

现在没有更多的编辑connetcted与爱好,我可以savely处理编辑自己在“ OnPreferenceClickListener”

5

参考了Android dveloper文件,其中约showDialog

显示与此相关的偏好的对话框。 这通常是在点击首选项时自动启动的。如果您需要在某些其他事件上显示对话框,请调用此方法。

所以,当点击偏好会自动调用的ShowDialog(),如果你想控制,以防止上显示点击偏好一个对话框,您需要实现一个自定义的喜好,这样,

public class MyPreference extends ListPreference { 
    private Context context; 

    // a flag to control show dialog 
    private boolean showDialog = false; 

    public MyPreference(Context context) { 
     super(context); 
     this.context = context; 
    } 

    public MyPreference(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     this.context = context;  
    } 

    @Override 
    protected void showDialog(Bundle state) {   
     if (showDialog) { 
      // show dialog 
      super.showDialog(state); 
     } else { 
      // if you don't want to show a dialog when click preference 
      return; 
     } /* end of if */ 
    } 
} 
1

我知道这是一个老问题,但如何取消这些对话仍然没有答案。 因此,这里是你如何取消首选项对话框:

dpref.setOnPreferenceClickListener(new OnPreferenceClickListener() { 
    @Override 
    public boolean onPreferenceClick(Preference preference) { 
     ((ListPreference)preference).getDialog().dismiss(); <<< This will do it 
     Toast.makeText(this, "hi there", Toast.LENGTH_SHORT).show(); 
     return true; 
    } 
}); 

而不是关闭对话框,它能够更好地隐藏到以后能够表现出来,当选项列表是从网络加载。所以做:

dpref.setOnPreferenceClickListener(new OnPreferenceClickListener() { 
    @Override 
    public boolean onPreferenceClick(Preference preference) { 
     ((ListPreference)preference).getDialog().hide(); <<< This will just hide the dialog and you still can show it later 
     Toast.makeText(this, "hi there", Toast.LENGTH_SHORT).show(); 
     return true; 
    } 
}); 

后来,当加载选项列表DO:

... 
dpref.setEntries(<array_of_options_here>); 
dpref.getdialog().show(); <<< If you dismiss the dialog earlier and not hide it, then getDialog() returns null here 
...