效果展示:
布局主要就是一个外部的RelativeLayout,里面放置一个NestedScrollView,NestedScrollView中只能有一个直接的ViewGroup。里面放置一个视频播放器。与NestedScrollView同级放置一个RelativeLayout(即固定在顶部的导航栏,效果就是与视频组件重合并且显示在视频之上)。最下方也是一个RelativeLayout(固定在底部的输入框)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/ll_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fafafa"
android:fitsSystemWindows="true"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.widget.NestedScrollView
android:id="@+id/sv_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true">
<com.gif.gifchannel.videoplayer.TextureVideoPlayer
android:id="@+id/video_player"
android:layout_width="match_parent"
android:layout_height="200dp" />
</RelativeLayout>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
<RelativeLayout
android:id="@+id/rl_top"
android:layout_width="match_parent"
android:layout_height="44dp"
android:background="#ffffff"
android:orientation="horizontal">
<ImageView
android:id="@+id/iv_back"
android:layout_width="44dp"
android:layout_height="44dp"
android:layout_marginLeft="6dp"
android:cropToPadding="true"
android:padding="10dp"
android:src="@mipmap/icon_back_white" />
<ImageView
android:id="@+id/iv_more"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:padding="16dp"
android:scaleType="centerInside"
android:src="@mipmap/ic_more_white" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<include layout="@layout/layout_comment_post_share" />
</RelativeLayout>
</RelativeLayout>
</LinearLayout>
初始时设置隐藏状态栏,将顶部栏和底部栏也都隐藏
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
lay_comment_post.setVisibility(View.GONE);
rl_top.getBackground().mutate().setAlpha(0);
上面设置顶部导航栏透明度时需要用mutate方法,如果不用mutate的话,其他用了rl_top的地方也会因为这里的设置而被改变透明度。
监听scrollview的滑动事件:
这里我们想要的效果是初始时顶部导航栏隐藏(完全透明),随着不断向下滑动,透明度逐渐增加,最后完全不透明并且改变控件的drawable。底部评论栏的逻辑是:1。若视频高度过高,导致视频控件下方某个特定组件在初始时超出屏幕,此时不显示评论栏。2。随着不断滑动,视频控件下方某个特定组件在屏幕内或超出屏幕,此时评论栏随之显示或隐藏。
下面介绍scrollview滑动时的几个主要属性:
scrollY:表示ScrollView顶端已经滑出去的高度。
v.getHeight():表示ScrollView当前的可见高度
mScrollView.getChildAt(0).getMeasuredHeight():表示ScrollView所占的高度.即ScrollView内容的高度.常常有一部分内容要滑动后才可见,这部分的高度也包含在了mScrollView.getChildAt(0).getMeasuredHeight()中。
1:顶部导航栏的控制方式:随着scrollY的增加或减,调用rl_top.getBackground().mutate().setAlpha()方法,控制透明度
2:底部评论栏的控制方法:首先计算一个特定的组件的顶部高度的坐标值(这个特定组件相当于一个标志位,高度超过这个位置就显示,高度低于这个位置就隐藏),然后在滑动过程中根据scrollY(顶端已经滑出去的高度)+v.getHeight()(ScrollView当前的可见高度)与标志位的高度值进行比较,若大于标志位的高度则显示,小于标志位的高度则隐藏。
scrollView.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() {
@Override
public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
//底部评论栏显示、隐藏
if (scrollY + v.getHeight() - Dp2px.UseDp2Px(mContext, 48) >= videoHeight) {
// LinearLayout.LayoutParams layoutParams= (LinearLayout.LayoutParams) lay_comment_post.getLayoutParams();
// layoutParams.bottomMargin
lay_comment_post.setVisibility(View.VISIBLE);
} else if (scrollY + v.getHeight() < videoHeight) {
lay_comment_post.setVisibility(View.GONE);
}
//顶部栏透明度控制
if (scrollY >= 0 && scrollY < 765) {
rl_top.getBackground().mutate().setAlpha(scrollY / 3);
back.setImageDrawable(getResources().getDrawable(R.mipmap.icon_back_white));
iv_more.setImageDrawable(getResources().getDrawable(R.mipmap.ic_more_white));
} else if (scrollY >= 755) {
rl_top.getBackground().mutate().setAlpha(255);
back.setImageDrawable(getResources().getDrawable(R.mipmap.ic_back));
iv_more.setImageDrawable(getResources().getDrawable(R.mipmap.ic_more));
}
}
});
videoOffset = new Point();
getDeepChildOffset(scrollView, ugc_show_detail_divide_line.getParent(), ugc_show_detail_divide_line, videoOffset);
videoHeight = videoOffset.y;
Log.d("fuck", "videoheight " + videoHeight + "screen " + ScreenUtils.getScreenHeight(mContext));
if (videoHeight < ScreenUtils.getScreenHeight(mContext)) {
lay_comment_post.setVisibility(View.VISIBLE);
}
计算某个控件的顶部坐标值和左部坐标值(从最顶部开始,即从0开始)
private void getDeepChildOffset(final ViewGroup mainParent, final ViewParent parent, final View child, final Point accumulatedOffset) {
ViewGroup parentGroup = (ViewGroup) parent;
accumulatedOffset.x += child.getLeft();
accumulatedOffset.y += child.getTop();
if (parentGroup.equals(mainParent)) {
return;
}
getDeepChildOffset(mainParent, parentGroup.getParent(), parentGroup, accumulatedOffset);
}