5

Uygulamamda iOS benzeri sıçrama overscroll efekti uygulamak istiyorum.iOS Android üzerinde kaydırma efekti gibi

Özel bir ScrollView oluşturulmasını öneren bu link ile karşılaştım. Ama sorun şu ki, hızlı bir şekilde yukarı ve aşağı doğru kaydırdığımda iyi çalışıyor, ancak ekranın alt ya da üst kısmını çeker çekmez takıldım ve efekt artık çalışmıyor. Animasyonun tür bir örnek olarak

Bunu bakabilirsiniz ulaşmak istiyoruz:

public class ObservableScrollView extends ScrollView 
{ 
    private static final int MAX_Y_OVERSCROLL_DISTANCE = 150; 

    private Context mContext; 
    private int mMaxYOverscrollDistance; 

    public ObservableScrollView(Context context) 
    { 
     super(context); 
     mContext = context; 
     initBounceScrollView(); 
    } 

    public ObservableScrollView(Context context, AttributeSet attrs) 
    { 
     super(context, attrs); 
     mContext = context; 
     initBounceScrollView(); 
    } 

    public ObservableScrollView(Context context, AttributeSet attrs, int defStyle) 
    { 
     super(context, attrs, defStyle); 
     mContext = context; 
     initBounceScrollView(); 
    } 

    private void initBounceScrollView() 
    { 
     //get the density of the screen and do some maths with it on the max overscroll distance 
     //variable so that you get similar behaviors no matter what the screen size 

     final DisplayMetrics metrics = mContext.getResources().getDisplayMetrics(); 
     final float density = metrics.density; 

     mMaxYOverscrollDistance = (int) (density * MAX_Y_OVERSCROLL_DISTANCE); 
    } 

    @Override 
    protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) 
    { 
     //This is where the magic happens, we have replaced the incoming maxOverScrollY with our own custom variable mMaxYOverscrollDistance; 
     return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, mMaxYOverscrollDistance, isTouchEvent); 
    } 
} 

cevap

13

çabuk koyduk:

Bu şu anda var kodudur CoordinatorLayout.Behavior'u temel alan basit bir çözüm. Mükemmel değil, belki biraz ince ayar yapabilirsin, ama bu kötü değil. Neyse sonuçta aşağıdaki gibi görünmelidir:

enter image description here

küçük bir yan not olarak ben cevap başlamadan önce: şiddetle yerine normal ScrollView destek kütüphanesinden NestedScrollView kullanmanız önerilir. Bunlar herhangi bir şekilde aynıdır, ancak NestedScrollView, daha düşük API düzeylerinde doğru iç içe kaydırma davranışını uygular.

Neyse benim cevap başlayalım: Ben ile geldi çözüm herhangi kaydırılabilir konteyner ile çalışacak olmak bir ScrollView, ListView veya RecyclerView ve bunu uygulamak için herhangi Views alt sınıf gerekmez. Zaten kullanmıyorsanız

Öncelikle projeye Google'ın Tasarım Destek Kütüphanesi eklemem gerekiyor:

compile 'com.android.support:design:25.0.1' 

unutmayın bu arada (API düzeyi 25 hangi gerektiğini hedeflemesi değilse) daha sonra API seviyeniz için en yeni sürümü eklemeniz gerekir (ör. API seviyesi 24 için compile 'com.android.support:design:24.2.0').

Kullandığınız her hangi bir kaydırılabilir kapsayıcı, sizin düzeninizde CoordinatorLayout ürününe sarılması gerekir. Benim örnekte ben bir NestedScrollView kullanıyorum:

<?xml version="1.0" encoding="utf-8"?> 
<android.support.design.widget.CoordinatorLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 

    <android.support.v4.widget.NestedScrollView 
     android:layout_width="match_parent" 
     android:layout_height="match_parent"> 

     <!-- content --> 

    </android.support.v4.widget.NestedScrollView> 

</android.support.design.widget.CoordinatorLayout> 

CoordinatorLayout Eğer doğrudan alt görünümlere Behavior atamak için izin verir. Bu durumda, aşırı kaydırma sıçrama efekti gerçekleştirecek olan NestedScrollView'a bir Behavior atayacağız. Sadece çabuk yukarıda ne açıklamak için gidiyorum bu yüzden bir Behavior ne açıklanması

public class OverScrollBounceBehavior extends CoordinatorLayout.Behavior<View> { 

    private int mOverScrollY; 

    public OverScrollBounceBehavior() { 
    } 

    public OverScrollBounceBehavior(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    @Override 
    public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) { 
     mOverScrollY = 0; 
     return true; 
    } 

    @Override 
    public void onNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) { 
     if (dyUnconsumed == 0) { 
      return; 
     } 

     mOverScrollY -= dyUnconsumed; 
     final ViewGroup group = (ViewGroup) target; 
     final int count = group.getChildCount(); 
     for (int i = 0; i < count; i++) { 
      final View view = group.getChildAt(i); 
      view.setTranslationY(mOverScrollY); 
     } 
    } 

    @Override 
    public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target) { 
     final ViewGroup group = (ViewGroup) target; 
     final int count = group.getChildCount(); 
     for (int i = 0; i < count; i++) { 
      final View view = group.getChildAt(i); 
      ViewCompat.animate(view).translationY(0).start(); 
     } 
    } 
} 

ve nasıl çalıştıkları bu yanıt kapsamı dışındadır:

Sadece Behavior koduna bakalım kod yok. Behavior, CoordinatorLayout'un doğrudan çocuklarında gerçekleşen tüm kaydırma olaylarını yakalar. onStartNestedScroll() yönteminde, herhangi bir kaydırma olayına ilgi duyduğumuzdan true dönüyoruz.onNestedScroll()'da, dikey konteynerin ne kadarının kaydırma konteyneri tarafından tüketilmediğini (diğer bir deyişle overscroll) bildiren dyUnconsumed parametresine bakın ve daha sonra kaydırma konteynerinin çocuklarını bu miktarla çevirin. Sadece delta değerleri aldığımız için, hepsini mOverscrollY değişkeninde toplamamız gerekiyor. Kaydırma etkinliği durduğunda onStopNestedScroll() çağrılır. Bu, kaydırma kabının tüm çocuklarını orijinal konumlarına geri döndürdüğümüz zamandır.

biz layout_behavior xml özelliğini kullanabilir ve biz kullanmak istiyorum Behavior tam sınıf adında geçmesi gerekiyor NestedScrollView için Behavior atamak için. Örneğimde yukarıdaki sınıf com.github.wrdlbrnft.testapp paketinde olduğundan com.github.wrdlbrnft.testapp.OverScrollBounceBehavior değerini değer olarak ayarladım.

<?xml version="1.0" encoding="utf-8"?> 
<android.support.design.widget.CoordinatorLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:app="http://schemas.android.com/apk/res-auto" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 

    <android.support.v4.widget.NestedScrollView 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     app:layout_behavior="com.github.wrdlbrnft.testapp.OverScrollBounceBehavior"> 

     <!-- content --> 

    </android.support.v4.widget.NestedScrollView> 

</android.support.design.widget.CoordinatorLayout> 

Bildirim ben CoordinatorLayout tarihinde eklendi ad ve ben NestedScrollView eklendi app:layout_behavior özellik: layout_behaviorCoordinatorLayout yüzden doğru ad, öneki gerekir özel bir niteliktir.

Ve tek yapmanız gereken bu! Bu cevabın planladığımdan daha uzun olduğu ortaya çıkarsa da, CoordinatorLayout ve Behaviors'u temel alan bazı temel bilgileri atladım. Yani bunlara aşina değilseniz veya başka sorularınız varsa sormaya çekinmeyin.

+0

Merhaba @Xaver Kapler teşekkürler. Ve bir kez daha şüphe duyuyoruz ki, bu durumda zıplamak için el ile aşağı doğru çekiyoruz. Ancak ekli ekranda gif, eğer kaydırırsak ve altına ulaştığında geri döner. Ayrıca aynı zamanda uygulamayı indirerek kontrol edin. Kaydırma görünümünde nasıl sağlanabilir? – Star

+0

@Star Ne dediğini anlamıyorum. Cevabım zaten cevabınızdaki GIF'i kopyalayan bir çözüm içeriyor. Başka ne istiyorsun? –

+0

@Shadow olduğundan emin olun. İhtiyacınız olan tek şey, üste kayma işlemini üstel bir şekilde kopyalamak için aynı matematiktir. –

0

kullanın güncellemeniz için bu

Private ScrollView scrMain; 

scrMain = (ScrollView) v.findViewbyId(R.id.scrMain); 

OverScrollDecorHandler.setScrollView(scrMain); 
İlgili konular