我已根据this answer创建了ParallaxScrollView
,视差效果与ImageView
的效果很好。
public class ParallaxScrollView extends ScrollView {
private Activity activity;
private View imgContainer;
private ImageView imageView;
private float parallaxValue;
public ParallaxScrollView(final Context context) {
this(context, null);
}
public ParallaxScrollView(final Context context, final AttributeSet attrs) {
this(context, attrs, 0);
}
public ParallaxScrollView(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
}
public void setParallaxParams(final Activity activity, final View imgContainer, final ImageView imageView, final float parallaxValue) {
this.activity = activity;
this.imgContainer = imgContainer;
this.imageView = imageView;
this.parallaxValue = parallaxValue;
}
@Override
protected void onScrollChanged(final int l, final int t, final int oldl, final int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
if (activity == null || imgContainer == null || imageView == null) {
throw new IllegalStateException("Please set parallax parameters via setParallaxParams() method!");
}
if (imageView.getTop() == 0) {
imageView.setTranslationY(getScrollY() * parallaxValue);
return;
}
// Get scroll view screen bound
final Rect scrollBounds = new Rect();
getHitRect(scrollBounds);
// Check if image container is visible in the screen
// so to apply the translation only when the container is visible to the user
if (imgContainer.getLocalVisibleRect(scrollBounds)) {
final Display display = activity.getWindowManager().getDefaultDisplay();
final DisplayMetrics outMetrics = new DisplayMetrics ();
display.getMetrics(outMetrics);
// Get screen density
final float density = getResources().getDisplayMetrics().density;
// Get screen height in pixels
final float dpHeight = outMetrics.heightPixels / density;
final float screenHeightPixels = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpHeight, getResources().getDisplayMetrics());
final float halfScreenHeight = screenHeightPixels / 2;
// Get image container height in pixels
final float containerHeightPixels = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, imgContainer.getHeight(), getResources().getDisplayMetrics());
// Get the location that consider a vertical center for the image (where the translation should be zero)
final float center = halfScreenHeight - (containerHeightPixels / 2);
// get the location (x,y) of the image container in pixels
final int[] locScreen = {0,0};
imgContainer.getLocationOnScreen(locScreen);
// trying to transform the current image container location into percentage
// so when the image container is exaclty in the middle of the screen percentage should be zero
// and as the image container getting closer to the edges of the screen should increase to 100%
final float finalLoc = ((locScreen[1]-center) * 100)/ halfScreenHeight;
// translate the inner image taking consideration also the density of the screen
imageView.setTranslationY(-finalLoc * parallaxValue * density);
}
}
}
以下是我如何使用它:
parallaxScrollView.setParallaxParams(getActivity(), imageContainer, image, 0.5f);
现在,我想向Toolbar
添加一个粘性标题,因此当用户向下滚动并且标题位于Toolbar
下面的屏幕顶部时,它将会#34;棒"到Toolbar
,当用户向上滚动并且标题下方的内容到达顶部时,它应该"解开"。很难解释,但我希望很清楚:)
以下是布局的样子:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ParallaxScrollView
android:id="@+id/scroll_view"
android:fillViewport="true"
android:overScrollMode="never"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<FrameLayout
android:id="@+id/image_container"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adjustViewBounds="true"
android:scaleType="centerCrop" />
</FrameLayout>
<FrameLayout
android:id="@+id/sticky_header"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<!-- Content -->
</FrameLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="@dimen/padding_big"
android:paddingBottom="@dimen/padding_big"
android:paddingEnd="@dimen/padding_big"
android:paddingStart="@dimen/padding_big"
android:paddingLeft="@dimen/padding_big"
android:paddingRight="@dimen/padding_big">
<!-- Content -->
所以,基本上我想要&#34;坚持&#34;用户滚动时,FrameLayout
{id @+id/stickyHeader
位于顶部。
AirBnb在其Android应用程序(take a look at sticky tab bar at this link)中使用的方法非常类似。
任何想法如何做到这一点? 理想情况下,不使用第三方库。