/* * Copyright 2014 Alex Curran * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.github.amlcurran.showcaseview.targets; import android.util.Log; import android.view.View; import android.view.ViewParent; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; /** * Class which wraps round the many implementations of ActionBarView and allows finding of Action * items */ class ActionBarViewWrapper { private ViewParent mActionBarView; private Class mActionBarViewClass; private Class mAbsActionBarViewClass; public ActionBarViewWrapper(ViewParent actionBarView) { if (!actionBarView.getClass().getName().contains("ActionBarView")) { String previousP = actionBarView.getClass().getName(); actionBarView = actionBarView.getParent(); String throwP = actionBarView.getClass().getName(); if (!actionBarView.getClass().getName().contains("ActionBarView")) { throw new IllegalStateException("Cannot find ActionBarView for " + "Activity, instead found " + previousP + " and " + throwP); } } mActionBarView = actionBarView; mActionBarViewClass = actionBarView.getClass(); mAbsActionBarViewClass = actionBarView.getClass().getSuperclass(); } /** * Return the view which represents the spinner on the ActionBar, or null if there isn't one */ public View getSpinnerView() { try { Field spinnerField = mActionBarViewClass.getDeclaredField("mSpinner"); spinnerField.setAccessible(true); return (View) spinnerField.get(mActionBarView); } catch (NoSuchFieldException e) { Log.e("TAG", "Failed to find actionbar spinner", e); } catch (IllegalAccessException e) { Log.e("TAG", "Failed to access actionbar spinner", e); } return null; } /** * Return the view which represents the title on the ActionBar, or null if there isn't one */ public View getTitleView() { try { Field mTitleViewField = mActionBarViewClass.getDeclaredField("mTitleView"); mTitleViewField.setAccessible(true); return (View) mTitleViewField.get(mActionBarView); } catch (NoSuchFieldException e) { Log.e("TAG", "Failed to find actionbar title", e); } catch (IllegalAccessException e) { Log.e("TAG", "Failed to access actionbar title", e); } return null; } /** * Return the view which represents the overflow action item on the ActionBar, or null if there isn't one */ public View getOverflowView() { try { Field actionMenuPresenterField = mAbsActionBarViewClass.getDeclaredField("mActionMenuPresenter"); actionMenuPresenterField.setAccessible(true); Object actionMenuPresenter = actionMenuPresenterField.get(mActionBarView); Field overflowButtonField = actionMenuPresenter.getClass().getDeclaredField("mOverflowButton"); overflowButtonField.setAccessible(true); return (View) overflowButtonField.get(actionMenuPresenter); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } return null; } /** * Return the view which represents the MediaRouterButton action item on the ActionBar, or null * if there isn't one */ public View getMediaRouterButtonView() { try { Field actionMenuPresenterField = mActionBarViewClass.getDeclaredField("mOptionsMenu"); actionMenuPresenterField.setAccessible(true); Object optionsMenu = actionMenuPresenterField.get(mActionBarView); Field actionItemsField = optionsMenu.getClass().getDeclaredField("mActionItems"); actionItemsField.setAccessible(true); List actionItems = (ArrayList) actionItemsField.get(optionsMenu); if (null != actionItems) { for(Object obj : actionItems) { System.out.println(obj); Object view = getMediaRouteButton(obj); if (null != view) { return (View) view; } } } return null; } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } return null; } private Object getMediaRouteButton(Object obj) { try { Field f = obj.getClass().getDeclaredField("mActionView"); f.setAccessible(true); Object view = f.get(obj); if("android.support.v7.app.MediaRouteButton".equals(view.getClass().getName())) { return view; } } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return null; } public View getActionItem(int actionItemId) { try { Field actionMenuPresenterField = mAbsActionBarViewClass.getDeclaredField("mActionMenuPresenter"); actionMenuPresenterField.setAccessible(true); Object actionMenuPresenter = actionMenuPresenterField.get(mActionBarView); Field menuViewField = actionMenuPresenter.getClass().getSuperclass().getDeclaredField("mMenuView"); menuViewField.setAccessible(true); Object menuView = menuViewField.get(actionMenuPresenter); Field mChField; if (menuView.getClass().toString().contains("com.actionbarsherlock")) { // There are thousands of superclasses to traverse up // Have to get superclasses because mChildren is private mChField = menuView.getClass().getSuperclass().getSuperclass() .getSuperclass().getSuperclass().getDeclaredField("mChildren"); } else if (menuView.getClass().toString().contains("android.support.v7")) { mChField = menuView.getClass().getSuperclass().getSuperclass() .getSuperclass().getDeclaredField("mChildren"); } else { mChField = menuView.getClass().getSuperclass().getSuperclass() .getDeclaredField("mChildren"); } mChField.setAccessible(true); Object[] mChs = (Object[]) mChField.get(menuView); for (Object mCh : mChs) { if (mCh != null) { View v = (View) mCh; if (v.getId() == actionItemId) { return v; } } } } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } return null; } }