我在活动中有两个片段。当片段A显示时,我希望显示导航抽屉汉堡图标并使导航抽屉工作。当片段B显示时,我希望显示后退箭头以及何时单击它进行向上导航。但是,我似乎无法使用新的AppCompat v7工具栏在ActionBarActivity中显示向上箭头,除非导航抽屉打开。
在我的活动中,对于我的onCreate()方法,我有......
toolbar = (Toolbar) findViewById(R.id.toolbar);
if (toolbar != null) {
setSupportActionBar(toolbar);
}
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, toolbar, R.string.drawer_open, R.string.drawer_close);
mDrawerLayout.setDrawerListener(mDrawerToggle);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
然后我在onPostCreate()
中调用mDrawerToggle.syncState();
我已尝试搜索如何以编程方式触发工具栏图标到后退箭头但没有任何效果。从我收集到的,打电话
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
我的片段中的应该更改图标,但事实并非如此。这可能是一个愚蠢的问题,但我做错了什么?
答案 0 :(得分:10)
根据我在v7 ActionBarDrawerToggle
的源代码中看到的内容,您可以将图标设置为不同的状态,而无需打开抽屉。
private enum ActionDrawableState{
BURGER, ARROW
}
private static void toggleActionBarIcon(ActionDrawableState state, final ActionBarDrawerToggle toggle, boolean animate){
if(animate) {
float start = state == ActionDrawableState.BURGER ? 0f : 1.0f;
float end = Math.abs(start - 1);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
ValueAnimator offsetAnimator = ValueAnimator.ofFloat(start, end);
offsetAnimator.setDuration(300);
offsetAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
offsetAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float offset = (Float) animation.getAnimatedValue();
toggle.onDrawerSlide(null, offset);
}
});
offsetAnimator.start();
}else{
//do the same with nine-old-androids lib :)
}
}else{
if(state == ActionDrawableState.BURGER){
toggle.onDrawerClosed(null);
}else{
toggle.onDrawerOpened(null);
}
}
}
Burger和Arrow之间的变形取决于0f
和1.0f
之间的值,基本上这些是抽屉传递给ActionBarDrawerToggle的值。
我使用ValueAnimator
为此范围内的值设置动画,即模仿抽屉切换。
null
参数是安全的,因为ActionBarDrawerToggle
根本不关心抽屉视图。
确保你看看新的插补器,完全按照材料设计指南进行动画制作:
fast_out_linear_in
fast_out_slow_in
另一种方法是通过反射访问mSlider
的{{1}}私有字段,并调用ActionBarDrawer
方法在Burger和Arrow之间切换。
setPosition(float position)
的类型为(扩展)mSlider
。
就个人而言,只要没有其他方法可以做你的肮脏工作,我总是尽量避免反思。
答案 1 :(得分:3)
随着支持库更新到23.0.0,有一种更好的方式来播放抽屉箭头动画。所以我要改进@ Nikola的答案。这是代码:
public static void playDrawerToggleAnim(final DrawerArrowDrawable d) {
float start = d.getProgress();
float end = Math.abs(start - 1);
ValueAnimator offsetAnimator = ValueAnimator.ofFloat(start, end);
offsetAnimator.setDuration(300);
offsetAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
offsetAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float offset = (Float) animation.getAnimatedValue();
d.setProgress(offset);
}
});
offsetAnimator.start();
}
随时通过以下方式拨打电话:
playDrawerToggleAnim((DrawerArrowDrawable) toolbar.getNavigationIcon());
答案 2 :(得分:2)
getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
@Override
public void onBackStackChanged() {
int stackHeight = getSupportFragmentManager().getBackStackEntryCount();
if (stackHeight > 0) { // if we have something on the stack (doesn't include the current shown fragment)
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
} else {
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
getSupportActionBar().setHomeButtonEnabled(false);
}
}
});
之后......
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
getSupportFragmentManager().popBackStack();
return true;
....
}
答案 3 :(得分:1)
在我的情况下,图标是动画: 我使用过ActionBarDrawerToggle v7。
MainActivity:
Toolbar toolbar = (Toolbar) findViewById(R.id.tool1);
setSupportActionBar(toolbar);
toolbar.setTitle("ToolBar Demo");
toolbar.setLogo(R.drawable.ic_launcher);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout);
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, toolbar,
R.string.open_navigation_drawer,
R.string.close_navigation_drawer) {
@Override
public void onDrawerSlide(View drawerView, float slideOffset) {
// TODO Auto-generated method stub
super.onDrawerSlide(drawerView, slideOffset);
}
/** Called when a drawer has settled in a completely closed state. */
@Override
public void onDrawerClosed(View view) {
super.onDrawerClosed(view);
getSupportActionBar().setTitle("hello");
}
/** Called when a drawer has settled in a completely open state. */
@Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
getSupportActionBar().setTitle("hi");
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) { // <---- added
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onPostCreate(Bundle savedInstanceState) { // <---- added
super.onPostCreate(savedInstanceState);
mDrawerToggle.syncState(); // important statetment for drawer to
// identify
// its state
}
@Override
public void onConfigurationChanged(Configuration newConfig) { // <---- added
super.onConfigurationChanged(newConfig);
mDrawerToggle.onConfigurationChanged(newConfig);
}
@Override
public void onBackPressed() {
if (mDrawerLayout.isDrawerOpen(Gravity.START | Gravity.LEFT)) { // <----
// added
mDrawerLayout.closeDrawers();
return;
}
super.onBackPressed();
}