For my requirement I have written a custom NestedScrollingChild to use in AppBarLayout.
Requirement was I need a custom view which will be partially displayed could be scrolled up to its full visibility. And another Layout which will be above the partially displayed view and and will scroll up when we scroll up the custom view. The Layout will stop when toolbar is slide up, after that custom view could be further scrolled up to its full display
It is the code which I am working on now when I try to move up the custom view it is shaking and the Toolbar is also shaking.
import android.content.Context;
import android.graphics.RectF;
import android.support.v4.view.GestureDetectorCompat;
import android.support.v4.view.NestedScrollingChild;
import android.support.v4.view.NestedScrollingChildHelper;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
public class MyCustomView extends LinearLayout
implements NestedScrollingChild,
GestureDetector.OnGestureListener {
private static final String TAG = "MyCustomView";
LinearLayout mainView;
private GestureDetectorCompat mDetector;
NestedScrollingChildHelper nestedScrollingChildHelper;
public MyCustomView(Context context) {
super(context);
LayoutInflater mInflater = LayoutInflater.from(context);
mInflater.inflate(R.layout.fragment_footer , this);
mDetector = new GestureDetectorCompat(context,this);
nestedScrollingChildHelper = new NestedScrollingChildHelper(this);
nestedScrollingChildHelper.setNestedScrollingEnabled(true);
}
public MyCustomView(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater mInflater = LayoutInflater.from(context);
mInflater.inflate(R.layout.fragment_footer , this);
mDetector = new GestureDetectorCompat(context,this);
nestedScrollingChildHelper = new NestedScrollingChildHelper(this);
nestedScrollingChildHelper.setNestedScrollingEnabled(true);
}
public MyCustomView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
final boolean handled = mDetector.onTouchEvent(event);
if (!handled && event.getAction() == MotionEvent.ACTION_UP) {
nestedScrollingChildHelper.stopNestedScroll();
}
return true;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
Log.d(TAG,"widthMeasureSpec"+widthMeasureSpec+", heightMeasureSpec"+heightMeasureSpec );
}
public int dpToPx(int dp) {
DisplayMetrics displayMetrics = this.getResources().getDisplayMetrics();
int px = Math.round(dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
return px;
}
@Override
public boolean onDown(MotionEvent e) {
nestedScrollingChildHelper.startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL);
return true;
}
@Override
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
nestedScrollingChildHelper.dispatchNestedPreScroll(0, (int) distanceY, null, null);
nestedScrollingChildHelper.dispatchNestedScroll(0, 0, 0, 0, null);
Log.d(TAG, "DistanceX " + distanceX + ", DistanceY" + distanceY);
Log.d(TAG, "e1X " + e1.getX() + ", e1Y" + e1.getY());
Log.d(TAG, "e2X " + e2.getX() + ", e2Y" + e2.getY());
if(Math.abs(e1.getY() - e2.getY()) > 10) {
setTop(getTop() - (int) (e1.getY() - e2.getY()));
}
return false;
}
@Override
public void onLongPress(MotionEvent e) {
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
return false;
}
}
Layout code
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<ImageView
android:id="@+id/imageView1"
android:layout_width="100dp"
android:layout_height="65dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginLeft="5dp"
android:src="@drawable/logo" />
</android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_main" />
<com.sample.custom.MyCustomView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
/>
</android.support.design.widget.CoordinatorLayout>
If I comment setTop(getTop() - (int) (e1.getY() - e2.getY()));
the the scroll on custome view will hide/show the toolbar properly