24

Theo mặc định trong Android 3.0 trở lên, khi ActionBar.hide()/show() được gọi là thanh được làm động với một hình ảnh động mờ dần trong/ra.Thay đổi hoạt ảnh ẩn của ActionBar?

Dường như không thuộc tính kiểu XML in this list được liên kết với tài nguyên hoạt ảnh.

Có cách nào để thay đổi hoạt ảnh này không? Trong trường hợp của tôi, tôi chỉ muốn thay đổi thời gian hoạt hình, nhưng nó cũng có thể có một hình ảnh động trượt?

Trả lời

34

số

Ít nhất là không bằng 3.0, 3.1 hoặc 3.2. Nếu bạn nhìn vào các nguồn bị biên dịch của com.android.internal.app.ActionBarImpl bạn sẽ thấy rằng các hình động được mã hóa cứng.

Ví dụ, từ 3.2:

.method public hide()V 
    .locals 8 

    .prologue 
    const/4 v5, 0x0 

    const/4 v7, 0x0 

    const/4 v6, 0x1 

    .line 529 
    iget-object v2, p0, Lcom/android/internal/app/ActionBarImpl;->mCurrentAnim:Landroid/animation/Animator; 

    if-eqz v2, :cond_0 

    .line 530 
    iget-object v2, p0, Lcom/android/internal/app/ActionBarImpl;->mCurrentAnim:Landroid/animation/Animator; 

    invoke-virtual {v2}, Landroid/animation/Animator;->end()V 

    .line 532 
    :cond_0 
    iget-object v2, p0, Lcom/android/internal/app/ActionBarImpl;->mContainerView:Lcom/android/internal/widget/ActionBarContainer; 

    invoke-virtual {v2}, Lcom/android/internal/widget/ActionBarContainer;->getVisibility()I 

    move-result v2 

    const/16 v3, 0x8 

    if-ne v2, v3, :cond_1 

    .line 553 
    :goto_0 
    return-void 

    .line 536 
    :cond_1 
    iget-boolean v2, p0, Lcom/android/internal/app/ActionBarImpl;->mShowHideAnimationEnabled:Z 

    if-eqz v2, :cond_3 

    .line 537 
    iget-object v2, p0, Lcom/android/internal/app/ActionBarImpl;->mContainerView:Lcom/android/internal/widget/ActionBarContainer; 

    const/high16 v3, 0x3f80 

    invoke-virtual {v2, v3}, Lcom/android/internal/widget/ActionBarContainer;->setAlpha(F)V 

    .line 538 
    iget-object v2, p0, Lcom/android/internal/app/ActionBarImpl;->mContainerView:Lcom/android/internal/widget/ActionBarContainer; 

    invoke-virtual {v2, v6}, Lcom/android/internal/widget/ActionBarContainer;->setTransitioning(Z)V 

    .line 539 
    new-instance v0, Landroid/animation/AnimatorSet; 

    invoke-direct {v0}, Landroid/animation/AnimatorSet;-><init>()V 

    .line 540 
    .local v0, anim:Landroid/animation/AnimatorSet; 
    iget-object v2, p0, Lcom/android/internal/app/ActionBarImpl;->mContainerView:Lcom/android/internal/widget/ActionBarContainer; 

    const-string v3, "alpha" 

    new-array v4, v6, [F 

    aput v5, v4, v7 

    invoke-static {v2, v3, v4}, Landroid/animation/ObjectAnimator;->ofFloat(Ljava/lang/Object;Ljava/lang/String;[F)Landroid/animation/ObjectAnimator; 

    move-result-object v2 

    invoke-virtual {v0, v2}, Landroid/animation/AnimatorSet;->play(Landroid/animation/Animator;)Landroid/animation/AnimatorSet$Builder; 

    move-result-object v1 

    .line 541 
    .local v1, b:Landroid/animation/AnimatorSet$Builder; 
    iget-object v2, p0, Lcom/android/internal/app/ActionBarImpl;->mContentView:Landroid/view/View; 

    if-eqz v2, :cond_2 

    .line 542 
    iget-object v2, p0, Lcom/android/internal/app/ActionBarImpl;->mContentView:Landroid/view/View; 

    const-string/jumbo v3, "translationY" 

    const/4 v4, 0x2 

    new-array v4, v4, [F 

    aput v5, v4, v7 

    iget-object v5, p0, Lcom/android/internal/app/ActionBarImpl;->mContainerView:Lcom/android/internal/widget/ActionBarContainer; 

    invoke-virtual {v5}, Lcom/android/internal/widget/ActionBarContainer;->getHeight()I 

    move-result v5 

    neg-int v5, v5 

    int-to-float v5, v5 

    aput v5, v4, v6 

    invoke-static {v2, v3, v4}, Landroid/animation/ObjectAnimator;->ofFloat(Ljava/lang/Object;Ljava/lang/String;[F)Landroid/animation/ObjectAnimator; 

    move-result-object v2 

    invoke-virtual {v1, v2}, Landroid/animation/AnimatorSet$Builder;->with(Landroid/animation/Animator;)Landroid/animation/AnimatorSet$Builder; 

    .line 544 
    iget-object v2, p0, Lcom/android/internal/app/ActionBarImpl;->mContainerView:Lcom/android/internal/widget/ActionBarContainer; 

    const-string/jumbo v3, "translationY" 

    new-array v4, v6, [F 

    iget-object v5, p0, Lcom/android/internal/app/ActionBarImpl;->mContainerView:Lcom/android/internal/widget/ActionBarContainer; 

    invoke-virtual {v5}, Lcom/android/internal/widget/ActionBarContainer;->getHeight()I 

    move-result v5 

    neg-int v5, v5 

    int-to-float v5, v5 

    aput v5, v4, v7 

    invoke-static {v2, v3, v4}, Landroid/animation/ObjectAnimator;->ofFloat(Ljava/lang/Object;Ljava/lang/String;[F)Landroid/animation/ObjectAnimator; 

    move-result-object v2 

    invoke-virtual {v1, v2}, Landroid/animation/AnimatorSet$Builder;->with(Landroid/animation/Animator;)Landroid/animation/AnimatorSet$Builder; 

    .line 547 
    :cond_2 
    iget-object v2, p0, Lcom/android/internal/app/ActionBarImpl;->mHideListener:Landroid/animation/Animator$AnimatorListener; 

    invoke-virtual {v0, v2}, Landroid/animation/AnimatorSet;->addListener(Landroid/animation/Animator$AnimatorListener;)V 

    .line 548 
    iput-object v0, p0, Lcom/android/internal/app/ActionBarImpl;->mCurrentAnim:Landroid/animation/Animator; 

    .line 549 
    invoke-virtual {v0}, Landroid/animation/AnimatorSet;->start()V 

    goto :goto_0 

    .line 551 
    .end local v0   #anim:Landroid/animation/AnimatorSet; 
    .end local v1   #b:Landroid/animation/AnimatorSet$Builder; 
    :cond_3 
    iget-object v2, p0, Lcom/android/internal/app/ActionBarImpl;->mHideListener:Landroid/animation/Animator$AnimatorListener; 

    const/4 v3, 0x0 

    invoke-interface {v2, v3}, Landroid/animation/Animator$AnimatorListener;->onAnimationEnd(Landroid/animation/Animator;)V 

    goto :goto_0 
.end method 

CẬP NHẬT

Cùng đi cho ICS và Jellybean

+3

+1 cho groking đang decompiled! – dokkaebi

+1

Mọi cập nhật cho ICS? –

+0

@ N.R.S.Sowrabh No. Nor Jelly Bean. –

15

Một hack cho việc vô hiệu hóa hình ảnh động ActionBar (tìm thấy bằng cách kiểm tra mã nguồn) có thể được thực hiện thông qua nội tâm thông qua:

try 
{ 
    getActionBar().getClass().getDeclaredMethod("setShowHideAnimationEnabled", boolean.class).invoke(getActionBar(), false); 
} 
catch (Exception exception) 
{ 
    // Too bad, the animation will be run ;(
} 

Xấu xí, tất nhiên, nhưng điều này thực sự hiệu quả, ít nhất là từ Android v4.2.

+0

cách làm cho nó hoạt động từ 3.0? –

+0

Làm tốt lắm! Tôi ghét để hack nhưng đôi khi không có sự lựa chọn! – PiersyP

+0

Thực sự hữu ích !! – user782104

4

nếu bạn sử dụng hỗ trợ-v7-compat, bạn có thể tắt hide hoạt hình như thế này:

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    //消除动画效果 
    disableABCShowHideAnimation(getSupportActionBar()); 
    return super.onCreateOptionsMenu(menu); 
} 



public static void disableABCShowHideAnimation(ActionBar actionBar) { 
    try 
    { 
     actionBar.getClass().getDeclaredMethod("setShowHideAnimationEnabled", boolean.class).invoke(actionBar, false); 
    } 
    catch (Exception exception) 
    { 
     try { 
      Field mActionBarField = actionBar.getClass().getSuperclass().getDeclaredField("mActionBar"); 
      mActionBarField.setAccessible(true); 
      Object icsActionBar = mActionBarField.get(actionBar); 
      Field mShowHideAnimationEnabledField = icsActionBar.getClass().getDeclaredField("mShowHideAnimationEnabled"); 
      mShowHideAnimationEnabledField.setAccessible(true); 
      mShowHideAnimationEnabledField.set(icsActionBar,false); 
      Field mCurrentShowAnimField = icsActionBar.getClass().getDeclaredField("mCurrentShowAnim"); 
      mCurrentShowAnimField.setAccessible(true); 
      mCurrentShowAnimField.set(icsActionBar,null); 
      //icsActionBar.getClass().getDeclaredMethod("setShowHideAnimationEnabled", boolean.class).invoke(icsActionBar, false); 
     }catch (Exception e){ 
      //.... 
     } 
    } 
} 
3

Cả các giải pháp không làm việc cho tôi vì vậy tôi cố gắng này để vô hiệu hóa hình ảnh động ở tất cả các :

public View setActionBarVisible(boolean isVisible) { 
    View decorView = getWindow().getDecorView(); 
    int resId; 
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB 
     || Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
     resId = getResources().getIdentifier(
       "action_bar_container", "id", getPackageName()); 
    } else { 
     resId = Resources.getSystem().getIdentifier(
       "action_bar_container", "id", "android"); 
    } 
    if (resId != 0) { 
     decorView.findViewById(resId).setvisibility(isVisible ? View.VISIBLE : View.GONE); 
    } 
} 

Và nó hoạt động tốt cho tôi. Bạn có thể thử animate toàn bộ thanh tác vụ của viewGroup để đạt được hiệu ứng tương tự.

+0

Tôi đã thêm sửa lỗi cho API21 + – MikhailKrishtop

1

Có, bạn chắc chắn nhất có thể.

Trước tiên, bạn có được cái nhìn ActionBar như thế này:

public View getActionBarView() { 
    Window window = getActivity().getWindow(); 
    View v = window.getDecorView(); 
    int resId = getResources().getIdentifier("action_bar_container", "id", "android"); 
    return v.findViewById(resId); 
} 

Sau đó, bạn có thể áp dụng các hình ảnh động trực tiếp trên quan điểm như thế này:

View actionbar = getActionBarView(); 
actionbar.setTranslation(-48); // move it out of the screen 
+0

Không có phương thức setTranslation trong chế độ xem –

+0

@Mik bạn có thể sử dụng setVisibility() thay vì – torvin

+0

Có, nhưng nó không giúp loại bỏ hoặc thay đổi hoạt ảnh. –