需求描述:整个页面有一个头布局和内容显示布局,头布局会根据下面内容区域的上下滑动来隐藏或显示(隐藏或显示时均有动画)。

内容布局可以是任何可以上下滑动的布局。当头布局隐藏时,整个页面都要可以显示内容,所以内容布局高度需match_parent。

6be26b0e86c2fa71f3c3f60f31061923.png

实现思路:

1.将头布局用ViewSwitcher(ViewSwitcher最多两个子View)包裹,另外在ViewSwitcher中添加一个高度为0dp的布局跟这个头布局进行交替显示。

@Override

public void addView(View child, int index, ViewGroup.LayoutParams params) {

if (getChildCount() >= 2) {

throw new IllegalStateException("Can't add more than 2 views to a ViewSwitcher");

}

super.addView(child, index, params);

}

2.可以在ViewSwitcher中设置动画。

3.内容布局设置滚动监听,根据上下滑动的偏移量来控制ViewSwitcher具体显示哪个子View。

代码实现:

布局文件

android:layout_width="match_parent"

android:layout_height="match_parent">

android:layout_width="match_parent"

android:layout_height="match_parent"/>

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_below="@id/head"

android:inAnimation="@anim/slide_in_top"

android:outAnimation="@anim/slide_out_top"

android:persistentDrawingCache="animation">

android:layout_width="match_parent"

android:layout_height="200dp"

android:background="@color/white"

android:gravity="center">

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:paddingBottom="6dp"

android:paddingTop="6dp"

android:textColor="@color/colorTitle2"

android:textSize="@dimen/text_size_14"

android:text="头布局" />

android:layout_height="0dp" />

动画文件

slide_in_top.xml

android:duration="300"

android:fromYDelta="-100%p"

android:interpolator="@android:anim/decelerate_interpolator"

android:toYDelta="0" />

slide_out_top.xml

android:duration="300"

android:fromYDelta="0"

android:interpolator="@android:anim/accelerate_interpolator"

android:toYDelta="-100%p" />

自定义ViewSwitcher:MyViewSwitcher

在MyViewSwitcher中封装了具体显示哪个子View的方法

public class MyViewSwitcher extends ViewSwitcher {

/**

* 真正的头布局

*/

private View firstChildView;

/**

* 高度为0的空布局

*/

private View secondChildView;

private static final int DELTA = 400;//根据具体情况设置值的大小

/**

* y方向偏移量总和

*/

private int DY = 0;

public MyViewSwitcher(Context context) {

this(context, null);

}

public MyViewSwitcher(Context context, AttributeSet attrs) {

super(context, attrs);

}

@Override

protected void onFinishInflate() {

super.onFinishInflate();

firstChildView = getChildAt(0);

secondChildView = getChildAt(1);

}

/**

* 根据外部传入的y值来设置显示哪个子View

* 如果向上滑动了好几页,突然想回到头布局时,只需向下滑动DELTA偏移即可显示头布局(语言功底差,描述不到位,相信大家都懂)

*

*@param delta

*/

public void whichOneShow(int delta) {

DY += delta;

//向上滑动

//当y偏移量总和大于DELTA,且第一个子View显示时,设置第二个子View显示

if (DY > DELTA && firstChildView.getVisibility() == VISIBLE) {

DY = 0;

setDisplayedChild(1);

} else if (DY > 0 && secondChildView.getVisibility() == VISIBLE) {

//继续向上滑动,且第二个子View一直处于显示状态,则将偏移量总和置零

DY = 0;

}

//向下滑动

//当y偏移量总和大于DELTA(即小于[-DELTA]),且第二个子View显示时,设置第一个子View显示

if (DY < -DELTA && secondChildView.getVisibility() == VISIBLE) {

DY = 0;

setDisplayedChild(0);

} else if (DY < 0 && firstChildView.getVisibility() == VISIBLE) {

//继续向下滑动,且第一个子View一直处于显示状态,则将偏移量总和置零

DY = 0;

}

}

}

MainActivity

public class MainActivity extends AppCompatActivity{

private RecyclerView mRecyclerView;

private MyViewSwitcher mViewSwitch;

@Override

public void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) {

super.onCreate(savedInstanceState, persistentState);

setContentView(R.layout.activity_search_movie);

initViews();

}

protected void initViews() {

mRecyclerView = (RecyclerView) findViewById(R.id.rv_movie);

mViewSwitch = (MyViewSwitcher) findViewById(R.id.viewswitch);

//RecyclerView设置数据部分代码省略

//...

//根据RecyclerView在竖直方向滑动的偏移量来控制头布局显示/隐藏

mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {

@Override

public void onScrolled(RecyclerView recyclerView, int dx, int dy) {

super.onScrolled(recyclerView, dx, dy);

mViewSwitch.whichOneShow(dy);

}

});

}

}

如有错误或不足之处,欢迎指正。。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐