2012-11-12 53 views
4

我想實現的是禁用除ActionBar之外的所有項目。我有一個自定義的ActionBarMenu,幾個TextViews,一個Button和一個來自ListNavigation的Spinner。 微調創建因爲bar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);這樣的:我可以禁用ActionBar的導航微調嗎?

SpinnerAdapter spinnerAdapter = new ArrayAdapter<String>(this.getActivity(), R.layout.action_bar_spinner, names); 
    // "listener" for spinner 
    bar.setListNavigationCallbacks(spinnerAdapter, new OnNavigationListener() { 
     @Override 
     public boolean onNavigationItemSelected(int position, long itemId) { 
      // do some stuff 

      return true; 
     } 
    }); 

我想禁用Spinner,所以它是無效的,但仍與最後一項可見選擇禁用it.In短之前,我需要這樣的東西bar.getNavigationSpinner.setEnabled(false)如果存在。問題是:是否有某種解決方法?如果沒有,是否有辦法禁用整個ActionBar,但保持可見?

注:我要實現它的一個片段。

回答

6

是的,可以禁用在ActionBar的列表導航中使用的Spinner。但不是一個簡單的解決方案,而是一個黑客。 ActionBar不提供直接訪問Spinner視圖。不幸的是,Spinner是在沒有任何ID的私人代碼中創建的。

那麼如何訪問Spinner實例呢?一種解決方案可能是通過Java反射API訪問它,但我不會推薦。

更好的解決方案是獲取當前Activity的根視圖,遍歷它的子視圖(操作欄及其視圖中存在的所有視圖)並找到合適的Spinner。由於動作欄中的Spinner大概是您自己創建的唯一一個,因此您應該能夠將它與其他人區分開來。

this SO question中描述了獲得根View

遍歷是相當簡單,只需記住,如果你正在使用ActionBarSherlock,你必須尋找IcsSpinner而不是SpinnerIcsSpinner不從Spinner延伸)。

private View findActionBarSpinner() { 
    View rootView = findViewById(android.R.id.content).getRootView(); 
    List<View> spinners = traverseViewChildren((ViewGroup) rootView); 
    return findListNavigationSpinner(spinners); // implement according to your layouts 
} 

private List<View> traverseViewChildren(ViewGroup parent) { 
    List<View> spinners = new ArrayList<View>(); 
    for (int i = 0; i < parent.getChildCount(); i++) { 
     View child = parent.getChildAt(i); 
     if (child instanceof Spinner) { 
      spinners.add(child); 
     } else if (child instanceof IcsSpinner) { // add this if you are using ActionBarSherlock 
      spinners.add(child); 
     } else if (child instanceof ViewGroup) { 
      spinners.addAll(traverseViewChildren((ViewGroup) child)); 
     } 
    } 
    return spinners; 
} 

功能findListNavigationSpinner應的方式,你可以區分其他微調來實現。如果您沒有使用任何Spinner(或從中派生的任何視圖),則返回的列表應只包含一個項目。

上面的代碼描述瞭如何在Activity中獲取Spinner。當然,從Fragment內禁用Spinner不是問題。片段引用了它的活動,所以活動可以通過某個接口將代碼暴露給片段。

+0

Thannks很多。按預期工作。我想知道爲什麼沒有方法直接訪問這個微調器。 – slezadav

+0

這很難說。可能會故意禁用一些不需要的定製。無論如何,在操作欄中有一些設計相當糟糕的東西。 – Tomik

+0

@Tomik請看http://stackoverflow.com/questions/26034733/disable-onclick-actionbar-spinner-until-a-process-is-complete – kittu88

1

上面的代碼不工作與操作欄COMPAT(V7支持庫)。我需要啓用/禁用我的應用程序使用此支持庫(API 2.2)的動作欄微調,但我已經注意到,類名是SpinnerICS代替Spinner

完整的包名是

android.support.v7.internal.widget.SpinnerICS 

因爲這個類是不可見的,並且不能在我的代碼需要進口,我不能使用:

if (child instanceof SpinnerICS) ... 

所以最後我解決了我的問題使用getClass().getName。因此,對於啓用/禁用使用操作欄微調代碼COMPAT支持庫(V7)將是:

private List<View> traverseViewChildren(ViewGroup parent) { 
    List<View> spinners = new ArrayList<View>(); 
    for (int i = 0; i < parent.getChildCount(); i++) { 
     View child = parent.getChildAt(i); 

     String className = child.getClass().getName(); 
     if (child instanceof Spinner || className.equals("android.support.v7.internal.widget.SpinnerICS")) { 
      spinners.add(child); 
     } else if (child instanceof ViewGroup) { 
      spinners.addAll(traverseViewChildren((ViewGroup) child)); 
     } 
    } 
    return spinners; 
} 

而且,我已經修改了我的findListNavigationSpinner方法來檢查紡紗列表具有的元素,以防止ArrayIndexOutOfBoundsException。因爲我只有在我的應用程序一個微調(在操作欄compat的),所以我的代碼是這樣的(你要適應它,如果你有一個以上的微調):

private View findListNavigationSpinner(List<View> spinners) { 
    // We only have one spinner in the app 
    View result = null; 
    if (spinners != null && spinners.size() > 0) { 
     result = spinners.get(0); 
    } 
    return result; 
} 
1

這可以通過注意被簡化ActionBar(和Spinner)位於根視圖和內容之間(id = android.R.id.content)。因此,您可以實現廣度優先搜索並返回您找到的第一個Spinner,一旦用id == android.R.id.content點擊視圖,就不會再添加到隊列中。

還是做深度優先搜索,但停止遞歸當你點擊視圖ID爲== android.R.id.content作爲微調不包含在裏面。

所以沒有必要保持任何列表,只返回第一個微調發現。

相關問題