私は最新のappcompatライブラリを実装し、アクションバーとしてToolbar
を使用しました。しかし問題は、ホームボタン/ハンバーガーのアイコンクリックイベントをキャッチできないことです。私はすべてを試してみましたが、似たような問題を見つけられないようです。
これは私のActivity
クラスです。
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Set up the drawer.
navDrawerFragment =
(NavigationDrawerFragment) getSupportFragmentManager()
.findFragmentById(R.id.navigation_drawer);
navDrawerFragment.setUp(
R.id.navigation_drawer,
(DrawerLayout) findViewById(R.id.drawer_layout),
toolbar);
}
そしてこれは私のNavigationDrawerFragmentクラスです:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
currentSelectedPosition = savedInstanceState.getInt(
STATE_SELECTED_POSITION);
fromSavedInstanceState = true;
}
// Select either the default item (0) or the last selected item.
selectItem(currentSelectedPosition);
}
@Override
public void onActivityCreated (Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Indicate that this fragment would like
// to influence the set of actions in the action bar.
setHasOptionsMenu(true);
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
drawerListView = (ListView) inflater.inflate(
R.layout.fragment_navigation_drawer, container, false);
drawerListView.setOnItemClickListener(
new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent,
View view, int position, long id) {
selectItem(position);
}
});
//mDrawerListView.setAdapter();
//mDrawerListView.setItemChecked(mCurrentSelectedPosition, true);
return drawerListView;
}
public void setUp(int fragmentId, DrawerLayout drawerLayout, Toolbar toolbar) {
fragmentContainerView = getActivity().findViewById(fragmentId);
this.drawerLayout = drawerLayout;
// set a custom shadow that overlays the main
// content when the drawer opens
drawerLayout.setDrawerShadow(
R.drawable.drawer_shadow, GravityCompat.START);
// set up the drawer's list view
// with items and click listener
ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeButtonEnabled(true);
// ActionBarDrawerToggle ties together the the proper interactions
// between the navigation drawer and the action bar app icon.
drawerToggle = new ActionBarDrawerToggle(
getActivity(),
drawerLayout,
toolbar,
R.string.navigation_drawer_open,
R.string.navigation_drawer_close) {
public void onDrawerClosed(View view) {
super.onDrawerClosed(view);
}
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
}
};
// If the user hasn't 'learned' about the drawer,
// open it to introduce them to the drawer,
// per the navigation drawer design guidelines.
if (!userLearnedDrawer && !fromSavedInstanceState) {
drawerLayout.openDrawer(fragmentContainerView);
}
// Defer code dependent on restoration of previous instance state.
drawerLayout.post(new Runnable() {
@Override
public void run() {
drawerToggle.syncState();
}
});
drawerLayout.setDrawerListener(drawerToggle);
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(STATE_SELECTED_POSITION, currentSelectedPosition);
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Forward the new configuration the drawer toggle component.
drawerToggle.onConfigurationChanged(newConfig);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
Log.d("cek", "item selected");
if (drawerToggle.onOptionsItemSelected(item)) {
Log.d("cek", "home selected");
return true;
}
return super.onOptionsItemSelected(item);
}
メニュー項目をクリックすると、ログ「item selected」が呼び出されます。しかし、ホームボタンをクリックすると、ナビゲーションドロワーが開きますが、ログ「home selected」は呼び出されません。 onOptionsItemSelected
メソッドもActivity
内に設定しましたが、それでも呼び出されません。
いつ家がクリックされたのか知りたい場合はAppCompatActivity
で、次のように試してください。
最初にあなたのToolbar
としてあなたのActionBar
を使いたいとAndroidに伝えます:
setSupportActionBar(toolbar);
次にHomeをsetDisplayShowHomeEnabled
で表示するように設定します。
getSupportActionBar().setDisplayShowHomeEnabled(true);
最後に、いつものようにAndroid.R.id.home
のクリックイベントを待ちます。
@Override
public boolean onOptionsItemSelected(MenuItem menuItem) {
if (menuItem.getItemId() == Android.R.id.home) {
Timber.d("Home pressed");
}
return super.onOptionsItemSelected(menuItem);
}
Toolbar
以外のクラスのAppCompatActivity
でナビゲーションボタンがいつクリックされたかを知りたい場合は、これらのメソッドを使用してナビゲーションアイコンを設定し、それに対するクリックイベントをリスンできます。ナビゲーションアイコンがあなたのToolbar
の左側に表示されます。そこには "home"ボタンがありました。
toolbar.setNavigationIcon(getResources().getDrawable(R.drawable.ic_nav_back));
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("cek", "home selected");
}
});
ハンバーガーがクリックされたときと引き出しが開いたときを知りたい場合は、onDrawerOpened
とonDrawerClosed
を介してこれらのイベントを既にリスニングしているので、これらのコールバックが要件を満たしているかどうかを確認します。
mActionBarDrawerToggle = mNavigationDrawerFragment.getActionBarDrawerToggle();
mActionBarDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// event when click home button
}
});
私の場合、このコードは完璧に動作します
これは、同じレベルに複数のフラグメントがある場合に正しいフラグメントに戻るための方法です。ツールバーの戻るボタンの動作をオーバーライドしないと、最初のフラグメントに戻ります。
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});
サポートライブラリ21の正しい解決策は以下のようになります。
// action_bar is def resource of appcompat;
// if you have not provided your own toolbar I mean
Toolbar toolbar = (Toolbar) findViewById(R.id.action_bar);
if (toolbar != null) {
// change home icon if you wish
toolbar.setLogo(this.getResValues().homeIconDrawable());
toolbar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//catch here title and home icon click
}
});
}
Navigation Drawerの戻るボタンとHomeボタンは次のように処理しました
public class HomeActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
private ActionBarDrawerToggle drawerToggle;
private DrawerLayout drawerLayout;
NavigationView navigationView;
private Context context;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
resetActionBar();
navigationView = (NavigationView) findViewById(R.id.navigation_view);
navigationView.setNavigationItemSelectedListener(this);
//showing first fragment on Start
getSupportFragmentManager().beginTransaction().setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN).replace(R.id.content_fragment, new FirstFragment()).commit();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
//listener for home
if(id==Android.R.id.home)
{
if (getSupportFragmentManager().getBackStackEntryCount() > 0)
onBackPressed();
else
drawerLayout.openDrawer(navigationView);
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onBackPressed() {
if (drawerLayout.isDrawerOpen(GravityCompat.START))
drawerLayout.closeDrawer(GravityCompat.START);
else
super.onBackPressed();
}
@Override
public boolean onNavigationItemSelected(MenuItem item) {
// Begin the transaction
Fragment fragment = null;
// Handle navigation view item clicks here.
int id = item.getItemId();
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (id == R.id.nav_companies_list) {
fragment = new FirstFragment();
// Handle the action
}
// Begin the transaction
if(fragment!=null){
if(item.isChecked()){
if(getSupportFragmentManager().getBackStackEntryCount()==0){
drawer.closeDrawers();
}else{
removeAllFragments();
getSupportFragmentManager().beginTransaction().setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE).replace(R.id.WikiCompany, fragment).commit();
drawer.closeDrawer(GravityCompat.START);
}
}else{
removeAllFragments();
getSupportFragmentManager().beginTransaction().setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE).replace(R.id.WikiCompany, fragment).commit();
drawer.closeDrawer(GravityCompat.START);
}
}
return true;
}
public void removeAllFragments(){
getSupportFragmentManager().popBackStackImmediate(null,
FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
public void replaceFragment(final Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.replace(R.id.WikiCompany, fragment).addToBackStack("")
.commit();
}
public void updateDrawerIcon() {
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
try {
Log.i("", "BackStackCount: " + getSupportFragmentManager().getBackStackEntryCount());
if (getSupportFragmentManager().getBackStackEntryCount() > 0)
drawerToggle.setDrawerIndicatorEnabled(false);
else
drawerToggle.setDrawerIndicatorEnabled(true);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}, 50);
}
public void resetActionBar()
{
//display home
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
}
public void setActionBarTitle(String title) {
getSupportActionBar().setTitle(title);
}
}
そしてそれぞれのonViewCreated
の中で私が呼ぶ
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
((HomeActivity)getActivity()).updateDrawerIcon();
((HomeActivity) getActivity()).setActionBarTitle("List");
}
このコードを試す
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if(id == Android.R.id.home){
//You can get
}
return super.onOptionsItemSelected(item);
}
あなたのonCreate()メソッドに以下のコードを追加してください
ActionBar ab = getSupportActionBar();
ab.setDisplayHomeAsUpEnabled(true);
私の場合は、次のようにアイコンを配置する必要がありました。
toolbar.setNavigationIcon(R.drawable.ic_my_home);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
そして、デフォルトのonOptionsItemSelectedとAndroid.R.id.home idでクリックイベントを聴きます。
最も簡単な方法は、ホームアイコンを既知のアイコンに変更してドロアブルを比較することです(Android.R.id.homeアイコンは異なるapiバージョンとは異なる可能性があるため)。
ツールバーをアクションバーとして設定します。SetSupportActionBar(_toolbar);
_toolbar.NavigationIcon = your_known_drawable_here;
for (int i = 0; i < _toolbar.ChildCount; i++)
{
View v = _toolbar.GetChildAt(i);
if (v is ImageButton)
{
ImageButton imageButton = v as ImageButton;
if (imageButton.Drawable.GetConstantState().Equals(_bookMarkIcon.GetConstantState()))
{
//here v is the widget that contains the home icon you can add your click events here
}
}
}
これは私がプリマテリアルデザインを実装した方法で、今でもまだうまくいくようです。新しいToolbar
に切り替えました。私の場合は、ログアウト中にサイドナビゲーションを開こうとした場合にログインします(サイドナビゲーションが開かないようにイベントをキャッチします)。あなたの場合あなたはreturn true;
できませんでした。
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (!isLoggedIn() && item.getItemId() == Android.R.id.home) {
login();
return true;
}
return mDrawerToggle.onOptionsItemSelected(item) || super.onOptionsItemSelected(item);
}
Xamarinの実装を探している人のために(イベントはC#では異なる方法で行われるので)、私は単にこのNavClickHandler
クラスを次のように作成しました。
public class NavClickHandler : Java.Lang.Object, View.IOnClickListener
{
private Activity mActivity;
public NavClickHandler(Activity activity)
{
this.mActivity = activity;
}
public void OnClick(View v)
{
DrawerLayout drawer = (DrawerLayout)mActivity.FindViewById(Resource.Id.drawer_layout);
if (drawer.IsDrawerOpen(GravityCompat.Start))
{
drawer.CloseDrawer(GravityCompat.Start);
}
else
{
drawer.OpenDrawer(GravityCompat.Start);
}
}
}
次に、次のようにカスタムハンバーガーメニューボタンを割り当てます。
SupportActionBar.SetDisplayHomeAsUpEnabled(true);
SupportActionBar.SetDefaultDisplayHomeAsUpEnabled(false);
this.drawerToggle.DrawerIndicatorEnabled = false;
this.drawerToggle.SetHomeAsUpIndicator(Resource.Drawable.MenuButton);
そして最後に、前に作成したクラス型のToolbarNavigationClickListenerに引き出しメニュートグルを割り当てました。
this.drawerToggle.ToolbarNavigationClickListener = new NavClickHandler(this);
そして、クリックイベントを処理するカスタムメニューボタンを用意しました。
私はDrawerLayoutを少し変更して、イベントを取得し、詳細ビューにいる場合はactionToggleを戻るように使用したい場合など、イベントを消費してイベントを実行できるようにします。
public class ListenableDrawerLayout extends DrawerLayout {
private OnToggleButtonClickedListener mOnToggleButtonClickedListener;
private boolean mManualCall;
public ListenableDrawerLayout(Context context) {
super(context);
}
public ListenableDrawerLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ListenableDrawerLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
/**
* Sets the listener for the toggle button
*
* @param mOnToggleButtonClickedListener
*/
public void setOnToggleButtonClickedListener(OnToggleButtonClickedListener mOnToggleButtonClickedListener) {
this.mOnToggleButtonClickedListener = mOnToggleButtonClickedListener;
}
/**
* Opens the navigation drawer manually from code<br>
* <b>NOTE: </b>Use this function instead of the normal openDrawer method
*
* @param drawerView
*/
public void openDrawerManual(View drawerView) {
mManualCall = true;
openDrawer(drawerView);
}
/**
* Closes the navigation drawer manually from code<br>
* <b>NOTE: </b>Use this function instead of the normal closeDrawer method
*
* @param drawerView
*/
public void closeDrawerManual(View drawerView) {
mManualCall = true;
closeDrawer(drawerView);
}
@Override
public void openDrawer(View drawerView) {
// Check for listener and for not manual open
if (!mManualCall && mOnToggleButtonClickedListener != null) {
// Notify the listener and behave on its reaction
if (mOnToggleButtonClickedListener.toggleOpenDrawer()) {
return;
}
}
// Manual call done
mManualCall = false;
// Let the drawer layout to its stuff
super.openDrawer(drawerView);
}
@Override
public void closeDrawer(View drawerView) {
// Check for listener and for not manual close
if (!mManualCall && mOnToggleButtonClickedListener != null) {
// Notify the listener and behave on its reaction
if (mOnToggleButtonClickedListener.toggleCloseDrawer()) {
return;
}
}
// Manual call done
mManualCall = false;
// Let the drawer layout to its stuff
super.closeDrawer(drawerView);
}
/**
* Interface for toggle button callbacks
*/
public static interface OnToggleButtonClickedListener {
/**
* The ActionBarDrawerToggle has been pressed in order to open the drawer
*
* @return true if we want to consume the event, false if we want the normal behaviour
*/
public boolean toggleOpenDrawer();
/**
* The ActionBarDrawerToggle has been pressed in order to close the drawer
*
* @return true if we want to consume the event, false if we want the normal behaviour
*/
public boolean toggleCloseDrawer();
}
}