实现并按预期工作,因此确实没有值得发布的代码,只是想知道是否有人有加快抽屉打开和关闭所需时间的经验?例如,YouTube应用程序要快得多!
adn*_*eal 24
您绝对可以调整动画的持续时间,但它需要您从支持库中复制类,然后相应地编辑它们.
ViewDragHelper
然后应用到DrawerLayout时候ViewDragHelper.smoothSlideViewTo被调用
您需要创建一个ViewDragHelper.forceSettleCapturedViewAt在持续时间参数中传递的修改版本.
forceSettleCapturedViewAt(... int duration)
Run Code Online (Sandbox Code Playgroud)
然后创建你的版本ViewDragHelper.smoothSlideViewTo.
public boolean smoothSlideViewTo(... int duration) {
...
return forceSettleCapturedViewAt(... int duration);
}
Run Code Online (Sandbox Code Playgroud)
DrawerLayout
接下来,您需要修改DrawerLayout.closeDrawer并DrawerLayout.closeDrawers匹配您的新ViewDragHelper修改.
ActionBarDrawerToggle
你还需要复制ActionBarDrawerToggle和ActionBarDrawerToggleHoneycomb.这些文件不需要任何编辑.
加速动画并等待它完成的另一种方法是首先简单地避免动画:只是在startActivity()不打电话的情况下打电话closeDrawer().虽然您没有看到抽屉关闭,但活动过渡动画仍然提供了非常好的效果,并且它立即发生,无需等待抽屉关闭动画首先完成稳定,没有波动,以及更短的感知延迟.
(如果您只想查看代码,可以跳过此解释.)
为了完成这项工作,您需要一种方法来关闭抽屉,而无需使用后退按钮导航回活动时的任何关闭动画.(不调用closeDrawer()会使抽屉在该活动实例中打开;相对浪费的解决方法是recreate()在导航时强制执行活动,但是可以在不执行此操作的情况下解决此问题.)您还需要确保只关闭抽屉,如果你在导航后返回,而不是在方向改变后,但这很容易.
尽管调用closeDrawer()from onCreate()会使抽屉在没有任何动画的情况下开始关闭,但事实并非如此onResume().调用closeDrawer()来自onResume()将关闭抽屉与动画是给用户随时可见.DrawerLayout没有提供任何方法来关闭没有动画的抽屉,但可以添加一个.
正如@syesilova指出的那样,关闭抽屉实际上只是将它从屏幕上滑下来.因此,您可以通过将抽屉直接移动到"关闭"位置来有效地跳过动画.翻译方向将根据重力(无论是左侧还是右侧抽屉)而变化,确切位置取决于抽屉与其所有儿童一起布置后的尺寸.
然而,简单地移动它是不够的,因为它DrawerLayout保持一些内部状态扩展LayoutParams,它用于知道抽屉是否打开.如果您只是将抽屉移出屏幕,它将不会知道它已关闭,这将导致其他问题.(例如,抽屉将在下一个方向更改时重新出现.)
由于您正在将支持库编译到您的应用程序中,因此您可以在android.support.v4.widget包中创建一个类以访问其默认(包私有)部分,或者在DrawerLayout不复制所需的任何其他类的情况下进行扩展.这也将减少更新代码的负担,以及将来对支持库的更改.(最好尽可能地将代码与实现细节隔离开来.)您可以使用moveDrawerToOffset()移动抽屉,并设置它LayoutParams以便知道抽屉已关闭.
这是跳过动画的代码:
// move drawer directly to the closed position
moveDrawerToOffset(drawerView, 0.f);
/* EDIT: as of v23.2.1 this direct approach no longer works
because the LayoutParam fields have been made private...
// set internal state so DrawerLayout knows it's closed
final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams();
lp.onScreen = 0.f;
lp.knownOpen = false;
invalidate();
/*/
// ...however, calling closeDrawer will set those LayoutParams
// and invalidate the view.
closeDrawer(drawerView);
/**/
Run Code Online (Sandbox Code Playgroud)
注意:如果您只是在moveDrawerToOffset()不改变的情况下打电话LayoutParams,抽屉将在下一个方向更改时移回其打开位置.
这种方法为support.v4包添加了一个实用程序类,以便访问DrawerLayout中我们需要的包私有部分.
将此类放入/ src/android/support/v4/widget /:
package android.support.v4.widget;
import android.support.annotation.IntDef;
import android.support.v4.view.GravityCompat;
import android.view.Gravity;
import android.view.View;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
public class Support4Widget {
/** @hide */
@IntDef({Gravity.LEFT, Gravity.RIGHT, GravityCompat.START, GravityCompat.END})
@Retention(RetentionPolicy.SOURCE)
private @interface EdgeGravity {}
public static void setDrawerClosed(DrawerLayout drawerLayout, @EdgeGravity int gravity) {
final View drawerView = drawerLayout.findDrawerWithGravity(gravity);
if (drawerView == null) {
throw new IllegalArgumentException("No drawer view found with gravity " +
DrawerLayout.gravityToString(gravity));
}
// move drawer directly to the closed position
drawerLayout.moveDrawerToOffset(drawerView, 0.f);
/* EDIT: as of v23.2.1 this no longer works because the
LayoutParam fields have been made private, but
calling closeDrawer will achieve the same result.
// set internal state so DrawerLayout knows it's closed
final DrawerLayout.LayoutParams lp = (DrawerLayout.LayoutParams) drawerView.getLayoutParams();
lp.onScreen = 0.f;
lp.knownOpen = false;
drawerLayout.invalidate();
/*/
// Calling closeDrawer updates the internal state so DrawerLayout knows it's closed
// and invalidates the view for us.
drawerLayout.closeDrawer(drawerView);
/**/
}
}
Run Code Online (Sandbox Code Playgroud)
当您离开时,在您的活动中设置一个布尔值,表示应该关闭抽屉:
public static final String CLOSE_NAV_DRAWER = "CLOSE_NAV_DRAWER";
private boolean mCloseNavDrawer;
@Override
public void onCreate(Bundle savedInstanceState) {
// ...
if (savedInstanceState != null) {
mCloseNavDrawer = savedInstanceState.getBoolean(CLOSE_NAV_DRAWER);
}
}
@Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
// ...
startActivity(intent);
mCloseNavDrawer = true;
}
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putBoolean(CLOSE_NAV_DRAWER, mCloseNavDrawer);
super.onSaveInstanceState(savedInstanceState);
}
Run Code Online (Sandbox Code Playgroud)
...并使用该setDrawerClosed()方法关闭抽屉onResume()而没有动画:
@Overrid6e
protected void onResume() {
super.onResume();
if(mCloseNavDrawer && mDrawerLayout != null && mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
Support4Widget.setDrawerClosed(mDrawerLayout, GravityCompat.START);
mCloseNavDrawer = false;
}
}
Run Code Online (Sandbox Code Playgroud)
此方法扩展DrawerLayout以添加setDrawerClosed()方法.
将此类放入/ src/android/support/v4/widget /:
package android.support.v4.widget;
import android.content.Context;
import android.support.annotation.IntDef;
import android.support.v4.view.GravityCompat;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
public class CustomDrawerLayout extends DrawerLayout {
/** @hide */
@IntDef({Gravity.LEFT, Gravity.RIGHT, GravityCompat.START, GravityCompat.END})
@Retention(RetentionPolicy.SOURCE)
private @interface EdgeGravity {}
public CustomDrawerLayout(Context context) {
super(context);
}
public CustomDrawerLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomDrawerLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void setDrawerClosed(View drawerView) {
if (!isDrawerView(drawerView)) {
throw new IllegalArgumentException("View " + drawerView + " is not a sliding drawer");
}
// move drawer directly to the closed position
moveDrawerToOffset(drawerView, 0.f);
/* EDIT: as of v23.2.1 this no longer works because the
LayoutParam fields have been made private, but
calling closeDrawer will achieve the same result.
// set internal state so DrawerLayout knows it's closed
final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams();
lp.onScreen = 0.f;
lp.knownOpen = false;
invalidate();
/*/
// Calling closeDrawer updates the internal state so DrawerLayout knows it's closed
// and invalidates the view for us.
closeDrawer(drawerView);
/**/
}
public void setDrawerClosed(@EdgeGravity int gravity) {
final View drawerView = findDrawerWithGravity(gravity);
if (drawerView == null) {
throw new IllegalArgumentException("No drawer view found with gravity " +
gravityToString(gravity));
}
// move drawer directly to the closed position
moveDrawerToOffset(drawerView, 0.f);
/* EDIT: as of v23.2.1 this no longer works because the
LayoutParam fields have been made private, but
calling closeDrawer will achieve the same result.
// set internal state so DrawerLayout knows it's closed
final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams();
lp.onScreen = 0.f;
lp.knownOpen = false;
invalidate();
/*/
// Calling closeDrawer updates the internal state so DrawerLayout knows it's closed
// and invalidates the view for us.
closeDrawer(drawerView);
/**/
}
}
Run Code Online (Sandbox Code Playgroud)
使用CustomDrawerLayout的,而不是DrawerLayout在你的活动布局:
<android.support.v4.widget.CustomDrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
>
Run Code Online (Sandbox Code Playgroud)
...当您离开时,在您的活动中设置一个布尔值,表示应该关闭抽屉:
public static final String CLOSE_NAV_DRAWER = "CLOSE_NAV_DRAWER";
private boolean mCloseNavDrawer;
@Override
public void onCreate(Bundle savedInstanceState) {
// ...
if (savedInstanceState != null) {
mCloseNavDrawer = savedInstanceState.getBoolean(CLOSE_NAV_DRAWER);
}
}
@Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
// ...
startActivity(intent);
mCloseNavDrawer = true;
}
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putBoolean(CLOSE_NAV_DRAWER, mCloseNavDrawer);
super.onSaveInstanceState(savedInstanceState);
}
Run Code Online (Sandbox Code Playgroud)
...并使用该setDrawerClosed()方法关闭抽屉onResume()而没有动画:
@Overrid6e
protected void onResume() {
super.onResume();
if(mCloseNavDrawer && mDrawerLayout != null && mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
mDrawerLayout.setDrawerClosed(GravityCompat.START);
mCloseNavDrawer = false;
}
}
Run Code Online (Sandbox Code Playgroud)
我发现这是避免波动的最佳方法,没有任何长时间的感知延迟.
你可以几乎使用类似的技术来模拟在一个活动到达后关闭抽屉,在意图传递一个值来告诉新的活动打开了抽屉,没有从动画onCreate(),然后动画它关闭了活动的布局完成后,但是在我的实验中,活动转换破坏了模拟的效果,所以你还需要禁用它.
| 归档时间: |
|
| 查看次数: |
15027 次 |
| 最近记录: |