툴바 홈 버튼 클릭 이벤트를 포착 할 수 없습니다.


106

최신 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);
}

메뉴 항목을 클릭하면 "선택된 항목"로그가 호출됩니다. 그러나 홈 버튼을 클릭하면 탐색 창이 열리지 만 "홈 선택"로그는 호출되지 않습니다. onOptionsItemSelected내 내부 Activity에도 메서드를 설정 했지만 여전히 호출되지 않습니다.

답변:


224

집이 언제 클릭되는지 알고 싶다면 AppCompatActivity다음과 같이 시도해야합니다.

먼저 다음을 사용하고 싶다고 Android에 알려 Toolbar주세요 ActionBar.

setSupportActionBar(toolbar);

그런 다음 다음 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"홈"버튼이 있던 곳의 왼쪽에 나타납니다 .

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있으므로 이러한 콜백이 요구 사항에 맞는지 확인하고 싶을 것입니다.


1
전에 첫 번째 부분을 시도했지만 작동하지 않습니다. 두 번째 부분을 시도했는데 작동합니다. 하지만 내비게이션 드로어에 툴바를 등록하면 아이콘이 바뀌지 않습니다. 한 가지 더 질문, 이것에 대한 setDrawerIndicatorEnabled 대체가 있습니까? 이 새로운 탐색 서랍으로 시도했지만 오류가 발생했습니다. 감사합니다
Dark Leonhart 2014 년

두 번째 해결책이 효과가 있습니다. 그러나 두 번째 솔루션에서 클릭 한 홈 버튼과 서랍 버튼을 어떻게 감지 할 수 있습니까? 서랍 아이콘을 클릭하면 서랍이 열리지 않습니다.
Dory 2011

2
당신은 setNavigationOnClickListener 도구 모음에 대한 당신은 "기본"서랍 행동 :( 잃을 때
IlyaEremin

7
이제 조각에서 이전에 onOptionsItemSelected ()에서 android.R.id.home을 확인할 수 있었을 때 별도의 클릭 리스너가 필요합니까? 그건 정말 짜증나
다니엘 윌슨

1
re : 툴바, 새 NavigationOnClickListener를 설정 한 경우 (setNavigationOnClickListener 사용) 적절한 경우 나중에 ActionBarDrawerToggle로 setDrawerListener를 다시 호출하여 NavDrawer를 복원 할 수 있습니다.
straya

24
    mActionBarDrawerToggle = mNavigationDrawerFragment.getActionBarDrawerToggle();
    mActionBarDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // event when click home button
        }
    });

내 경우에는이 코드가 완벽하게 작동합니다.


당신은 정말 대단해요, 잘 됐어요. DrawerToggle을 통해 툴바 뒤로 버튼을 처리 할 수있을 거라고는 생각도 못했어요 ..
Sai

ActionBarDrawerToggle.setToolbarNavigationClickListener가 작동하게하려면 먼저 다음을 호출해야합니다. mActionBarDrawerToggle.setHomeAsUpIndicator (R.drawable.menu_icon); mActionBarDrawerToggle.setDrawerIndicatorEnabled (false); 클릭 이벤트를 직접 관리합니다. (클릭시 서랍 열기 / 닫기)
luky

10

이것은 내가 올바른 조각으로 돌아가는 방법입니다. 그렇지 않으면 같은 수준에 여러 조각이있는 경우 도구 모음 뒤로 단추 동작을 재정의하지 않으면 첫 번째 조각으로 돌아갑니다.

toolbar.setNavigationOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            finish();
        }
    });

Kotlin에 '재정의'클릭 방법이 있나요?
Akhila Madari

@AkhilaMadari는 Kotlin에서 다음과 같이 시도해보십시오. val toolbar = findViewById (R.id.toolbar) as Toolbar setSupportActionBar (toolbar) toolbar.setNavigationOnClickListener {/ * 원하는 작업을 수행 * / finish ()}
Marcos

3

지원 라이브러리 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                          
        }                       
    });                 
}

에서 this.getResValues().homeIconDrawable(), 누구 this입니까?
LuisComS 2015 년

이것은 활동입니다. Getresvalues는 내 방법이므로 여기서는 관련이 없습니다. Setlogo는 드로어 블 리소스 ID를 허용합니다.
Čikić Nenad

4
전체 도구 모음에서, 나는 그가 대해 물어 된이 무엇을 생각 해달라고 곳은 어떤에서 사용자가 클릭을 처리합니다
미나 Fawzy

1

탐색 창에서 뒤로 및 홈 버튼을 처리했습니다.

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");
}

0

이것이 제가 프리 머티리얼 디자인을 구현 한 방법이며 지금도 여전히 작동하는 것 같습니다 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);
}

아, 프래그먼트에서 홈 버튼 클릭을 잡을 수 없다는 것을 잊었습니다. 여기에서 질문을하고 이벤트를 모든 프래그먼트에 수동으로 전달하는 해결 방법을 제안했습니다. stackoverflow.com/q/21938419/1007151
darnmason 2014 년

0

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();
    }

}

0

우리가 할 수있는 가장 쉬운 방법은 홈 아이콘을 알려진 아이콘으로 변경하고 드로어 블을 비교하는 것입니다 (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 
                    }
                }
            }

0

제 경우에는 다음을 사용하여 아이콘을 넣어야했습니다.

toolbar.setNavigationIcon(R.drawable.ic_my_home);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);

그런 다음 기본 onOptionsItemSelected 및 android.R.id.home ID로 클릭 이벤트를 수신합니다.


1
이것은 작동하지 않습니다. android.R.id.home절대 발사하지 마십시오
Trancer

0

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);

그리고 클릭 이벤트가 처리 된 사용자 지정 메뉴 버튼이 있습니다.


0

이 코드 시도

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();
    if(id == android.R.id.home){
        //You can get 
    }
    return super.onOptionsItemSelected(item);
}

onCreate () metod에 아래 코드를 추가하십시오.

ActionBar ab = getSupportActionBar();
    ab.setDisplayHomeAsUpEnabled(true);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.