2016-06-29 17 views
0

私はアプリケーションのチュートリアルを開発しており、ツールバーの特定のアイコンを指す必要があります。 、View mErase = findViewById(R.id.AbErase);mEraseアクションメニューでアイコンの場所を取得するにはどうすればよいですか?

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    isBeingRestored = (savedInstanceState != null); 

    Toolbar scToolbar = (Toolbar) findViewById(R.id.Sc_toolbar); 
    setSupportActionBar(scToolbar); 

    scToolbar.post(new Runnable() { 
     @Override 
     public void run() { 
      if (!isBeingRestored) { 
       //View mErase = findViewById(R.id.AbErase); 
       View mErase = overflowMenu.getItem(0).getActionView(); 
       int[] location = new int[2]; 
       mErase.getLocationOnScreen(location); 
       eraseIconLeft = location[0]; 
      } 
     } 
    } 

nullに設定されている**** EDITを開始:ここ

<menu xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:app="http://schemas.android.com/apk/res-auto" 
xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity"> 

<item android:id="@+id/AbErase" 
    android:title="@string/Erase" 
    android:icon="@android:drawable/ic_delete" 
    android:orderInCategory="10" 
    app:showAsAction="ifRoom|collapseActionView" /> 

<item android:id="@+id/AbSuggest" 
    android:title="@string/Suggest" 
    android:icon="@mipmap/ic_lightbulb_outline_white_48dp" 
    android:orderInCategory="50" 
    app:showAsAction="ifRoom|collapseActionView" /> 
<item android:id="@+id/AbUndo" 
    android:title="@string/ActionBarUndo" 
    android:icon="@android:drawable/ic_menu_revert" 
    android:orderInCategory="51" 
    app:showAsAction="ifRoom|collapseActionView" /> 
... 

は私のコードです:ここでは

は、アクションメニューのためのXMLの抽出物であります **** AbEraseはViewのidではなくMenuItemのIDなので、驚くべきことではありません。 **** end EDIT **** View mErase = overflowMenu.getItem(0).getActionView();locationは(0,24)に設定されています。これは既にロゴアイコンとタイトルがツールバーにあるため間違っています。

ツールバーのAbEraseビューの絶対座標を取得するにはどうすればよいですか?

**** EDIT **** ここで静的変数overflowMenuの初期化を見つけることができるコードです:メソッドは時期尚早である

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    // Inflate the menu; this adds items to the action bar if it is present. 
    getMenuInflater().inflate(R.menu.menu_main, menu); 

    actionBar.collapseActionView(); 

    overflowMenu = menu; 

    isInitializedMenuItem = menu.findItem(R.id.AbInitialized); 
    isInitializedMenuItem.setChecked(isInitializeCbxChecked); 

    return super.onCreateOptionsMenu(menu); 
} 

答えて

3

android.support.v7.widgetが使用されたと仮定し、次のコード・スニペット

@Nullable 
View getMenuItemView(Toolbar toolbar, @IdRes int menuItemId) throws IllegalAccessException,NoSuchFieldException { 
    Field mMenuView = Toolbar.class.getDeclaredField("mMenuView"); 
    mMenuView.setAccessible(true); 
    Object menuView = mMenuView.get(toolbar); 
    Field mChildren = menuView.getClass() //android.support.v7.internal.view.menu.ActionMenuView 
          .getSuperclass() //android.support.v7.widget.LinearLayoutCompat 
          .getSuperclass() //android.view.ViewGroup 
          .getDeclaredField("mChildren"); 
    mChildren.setAccessible(true); 
    View[] children = (View[]) mChildren.get(menuView); 
    for (View child : children) { 
     if (child.getId() == menuItemId) { 
      return child; 
     }       
    } 
    return null;      
} 

を試してみてください。上記のメソッドは、あなたのメニュー項目に対応するViewを返します。

View menuItemView = getMenuItemView(scToolbar,R.id.AbErase); 
int x = menuItemView.getX(); 
int y = menuItemView.getY(); 

とあなたの座標があります。

EDIT

もう少し研究を重ねた結果、反射が必要ないことがわかりました。

menuItemViewをフェッチする前に、私たちはそのレイアウトを終了するToolbarのを待たなければならない上記のスニペットが動作するようにテストされ

scToolbar.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { 
     @Override 
     public void onGlobalLayout() { 
      scToolbar.getViewTreeObserver().removeOnGlobalLayoutListener(this); 
      View menuItem = findViewById(R.id.AbErase); 
      if (menuItem != null) { 
       int[] location = new int[2]; 
       menuItem.getLocationOnScreen(location); 
       int x = location[0]; //x coordinate 
       int y = location[1]; //y coordinate 
      } 
     } 
    }); 

を渡し、それは任意の便利なライフサイクル・コールバック・メソッドに配置することができます。

EDIT

活動の源で忘れてはならない重要なものを探しにView menuItem = findViewById(R.id.AbErase);のみViewTreeObserver.OnGlobalLayoutListeneronGlobalLayoutコールバックから呼び出さなければならないということです。

+0

私は誤っていない場合、ツールバーが配置された後に実行されるべきです、私のRunnableに 'menuItemView'に関する上記の3つの命令を挿入しました。 '.getSuperclass()// android.support.v7.internal.widget.LinearLayoutICS'を削除した後、' menuItemView'が正しく設定されています。ただし、左、上、右、下のフィールドはすべてゼロに等しい。このコードは早すぎますか?ユーザー対話の前に実行する必要があると仮定して、いつ実行する必要がありますか? – ema3272

+0

@ ema3272どのバージョンのAndroidサポートライブラリを使用していますか?私は何かを見逃しているかどうかを確認するために、関連する情報源を調べます。 技術的には、ビューが可視状態にあるときに実行する必要があります。「onCreate」はあまりにも早いので、動作するはずの「onResume」を試してみてください。 –

+0

'.getSuperclass()//android.support.v7.internal.widget.LinearLayoutICS'は 'ActionMenuView'が 'LinearLayoutCompat'の子になりましたので、エラーが解消されました。 –

0

onCreateでは。ビューはまだ測定されていません。 onPrepareOptionMenu()を上書きし、コードを入力します。また、不要なRunnableを削除してください。

+0

私はRunnableを使用しています。私は[2。レイアウトキューにRunnableを追加する:View.post()](http://stackoverflow.com/questions/3591784/getwidth-and-getheight-of-view-returns-0)非常にエレガントでパフォーマンス重視。とにかく、コードを 'onPrepareOptionMenu'に移動すると、' mErase'はそれを初期化する方法に関係なく 'null'になります。だからこれはどちらもうまくいかない。 – ema3272

関連する問題