Không thể bắt sự kiện nhấp vào nút trang chủ trên thanh công cụ


106

Tôi đã triển khai thư viện appcompat mới nhất và sử dụng Toolbarlàm thanh tác vụ. Nhưng vấn đề là tôi không thể bắt được sự kiện nhấp vào nút trang chủ / biểu tượng bánh hamburger. Tôi đã thử và xem xét mọi thứ nhưng dường như không tìm thấy vấn đề tương tự.

Đây là Activitylớp học của tôi :

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

Và đây là lớp NavigationDrawerFragment của tôi:

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

khi tôi nhấp vào một mục menu, nhật ký "mục đã chọn" sẽ được gọi. Nhưng khi tôi nhấp vào nút trang chủ, nó sẽ mở ngăn điều hướng nhưng nhật ký "nhà đã chọn" không bao giờ được gọi. Tôi cũng đã thiết lập onOptionsItemSelectedphương thức bên trong của mình Activity, nhưng nó vẫn không được gọi.

Câu trả lời:


224

Nếu bạn muốn biết khi nào trang chủ được nhấp là một AppCompatActivitythì bạn nên thử nó như sau:

Trước tiên, hãy nói với Android rằng bạn muốn sử dụng của mình Toolbarlàm của bạn ActionBar:

setSupportActionBar(toolbar);

Sau đó, đặt Trang chủ được hiển thị setDisplayShowHomeEnablednhư sau:

getSupportActionBar().setDisplayShowHomeEnabled(true);

Cuối cùng lắng nghe các sự kiện nhấp chuột vào android.R.id.homenhư bình thường:

@Override
public boolean onOptionsItemSelected(MenuItem menuItem) {
    if (menuItem.getItemId() == android.R.id.home) {
        Timber.d("Home pressed");
    }
    return super.onOptionsItemSelected(menuItem);
}

Nếu bạn muốn biết khi nào nút điều hướng được nhấp vào một Toolbartrong một lớp khác, AppCompatActivitybạn có thể sử dụng các phương pháp này để đặt biểu tượng điều hướng và lắng nghe các sự kiện nhấp trên đó. Biểu tượng điều hướng sẽ xuất hiện ở phía bên trái của Toolbarnút "trang chủ" trước đây của bạn.

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

Nếu bạn muốn biết khi nào bánh hamburger được nhấp và khi nào ngăn kéo mở ra, bạn đã lắng nghe các sự kiện này qua onDrawerOpenedonDrawerClosedvì vậy bạn sẽ muốn xem liệu các lệnh gọi lại đó có phù hợp với yêu cầu của mình hay không.


1
Đã thử phần đầu tiên trước đó, nhưng nó không hoạt động. Đã thử phần thứ hai, và nó hoạt động. Nhưng biểu tượng không thay đổi nếu tôi đăng ký thanh công cụ với ngăn kéo điều hướng. Một câu hỏi nữa, có sự thay thế nào cho setDrawerIndicatorEnabled cho điều này không? Tôi đã thử với ngăn điều hướng mới này và gặp lỗi. Cảm ơn u
tối Leonhart

Giải pháp thứ hai đang hoạt động. Nhưng làm thế nào chúng ta có thể phát hiện nút trang chủ được nhấp và nút ngăn kéo trong giải pháp thứ hai. Khi tôi nhấp vào biểu tượng ngăn kéo, nó sẽ không mở ngăn.
Dory

2
Khi bạn đặtNavigationOnClickListener cho thanh công cụ thì bạn sẽ mất hành vi ngăn kéo "gốc" :(
IlyaEremin

7
Vì vậy, bây giờ chúng ta cần một trình nghe nhấp chuột riêng biệt khi trước đây trong các phân đoạn, chúng ta có thể kiểm tra android.R.id.home trong onOptionsItemSelected ()? Điều đó thực sự rất khó chịu
Daniel Wilson

1
re: Thanh công cụ, nếu bạn đặt NavigationOnClickListener mới (sử dụng setNavigationOnClickListener), bạn có thể khôi phục NavDrawer sau khi thích hợp bằng cách gọi lại setDrawerListener bằng ActionBarDrawerToggle của mình.
straya

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

trong mycase, mã này hoạt động hoàn hảo


Bạn thực sự tuyệt vời, nó đã hoạt động, tôi chưa bao giờ nghĩ rằng tôi có thể xử lý nút quay lại của thanh công cụ thông qua DrawerToggle ..
Sai

Để ActionBarDrawerToggle.setToolbarNavigationClickListener hoạt động trước tiên người ta phải gọi cái này: mActionBarDrawerToggle.setHomeAsUpIndicator (R.drawable.menu_icon); mActionBarDrawerToggle.setDrawerIndicatorEnabled (false); và tự quản lý các sự kiện nhấp chuột. (mở / đóng ngăn khi nhấp chuột)
luky

10

Đây là cách tôi thực hiện để quay trở lại đúng phân đoạn, nếu không nếu bạn có nhiều phân đoạn ở cùng cấp độ, nó sẽ trở về phân đoạn đầu tiên nếu bạn không ghi đè hành vi nút quay lại của thanh công cụ.

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

Chúng ta có Phương pháp nhấp "Ghi đè" trong Kotlin không?
Akhila Madari

@AkhilaMadari hãy thử một cái gì đó như thế này trong Kotlin: val toolbar = findViewById (R.id.toolbar) as Toolbar setSupportActionBar (toolbar) toolbar.setNavigationOnClickListener {/ * làm điều gì đó bạn muốn * / finish ()}
Marcos

3

Tôi nghĩ giải pháp chính xác với thư viện hỗ trợ 21 là như sau

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

trong this.getResValues().homeIconDrawable(), Ai là this?
LuisComS

Đây là một hoạt động. Getresvalues ​​là phương pháp của tôi, vì vậy nó không liên quan ở đây. Setlogo chấp nhận một id tài nguyên có thể vẽ được.
Čikić Nenad

4
này sẽ xử lý người sử dụng nhấp chuột vào bất cứ nơi tại toàn bộ thanh công cụ, tôi không nghĩ rằng điều này ông được hỏi về
Mina Fawzy

1

Tôi đã xử lý nút quay lại và nút Trang chủ trong Ngăn điều hướng như

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

và trong mỗi lần onViewCreatedtôi gọi

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    ((HomeActivity)getActivity()).updateDrawerIcon();
    ((HomeActivity) getActivity()).setActionBarTitle("List");
}

0

Đây là cách tôi triển khai thiết kế pre-material và nó dường như vẫn hoạt động bây giờ tôi đã chuyển sang thiết kế mới Toolbar. Trong trường hợp của tôi, tôi muốn đăng nhập người dùng nếu họ cố gắng mở điều hướng bên trong khi đăng xuất, (và nắm bắt sự kiện để điều hướng bên không mở). Trong trường hợp của bạn, bạn không thể 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);
}

Ah, tôi quên rằng tôi đã phát hiện ra mình không thể bắt được nhấp chuột vào nút trang chủ trong một phân đoạn, tôi đã đặt một câu hỏi ở đây và đề xuất một giải pháp là chuyển sự kiện theo cách thủ công vào tất cả các phân đoạn của bạn. stackoverflow.com/q/21938419/1007151
darnmason

0

Tôi đã thay đổi DrawerLayout một chút để nhận các sự kiện và có thể sử dụng và sự kiện, chẳng hạn như nếu bạn muốn sử dụng actionToggle nếu bạn đang xem chi tiết:

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

Cách tiếp cận dễ nhất mà chúng tôi có thể làm là thay đổi biểu tượng trang chủ thành một biểu tượng đã biết và so sánh các biểu tượng có thể kéo được (vì biểu tượng android.R.id.home có thể khác với các phiên bản api khác nhau

vì vậy hãy đặt thanh công cụ làm thanh hành động 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

Trong trường hợp của tôi, tôi phải đặt biểu tượng bằng cách sử dụng:

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

Và sau đó lắng nghe các sự kiện nhấp chuột với id onOptionsItemSelected và android.R.id.home mặc định


1
Điều này sẽ không hoạt động. android.R.id.homekhông bao giờ bắn
Trancer

0

Đối với bất kỳ ai đang tìm cách triển khai Xamarin (vì các sự kiện được thực hiện khác nhau trong C #), tôi chỉ cần tạo NavClickHandlerlớp này như sau:

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

Sau đó, gán một nút menu bánh hamburger tùy chỉnh như sau:

        SupportActionBar.SetDisplayHomeAsUpEnabled(true);
        SupportActionBar.SetDefaultDisplayHomeAsUpEnabled(false);
        this.drawerToggle.DrawerIndicatorEnabled = false;
        this.drawerToggle.SetHomeAsUpIndicator(Resource.Drawable.MenuButton);

Và cuối cùng, đã chỉ định trình đơn ngăn kéo chuyển đổi một ToolbarNavigationClickListener của loại lớp tôi đã tạo trước đó:

        this.drawerToggle.ToolbarNavigationClickListener = new NavClickHandler(this);

Và sau đó, bạn có một nút menu tùy chỉnh, với các sự kiện nhấp chuột được xử lý.


0

Hãy thử mã này

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

Thêm mã bên dưới vào siêu dữ liệu onCreate () của bạn

ActionBar ab = getSupportActionBar();
    ab.setDisplayHomeAsUpEnabled(true);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.