效果图
源码
activity_main.xml
<FrameLayout android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<android.support.v7.widget.RecyclerView
android:id="@+id/feed_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:scrollbars="vertical" />
<RelativeLayout
android:id="@+id/suspension_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white">
<ImageView
android:id="@+id/iv_avatar"
android:layout_width="44dp"
android:layout_height="44dp"
android:src="@mipmap/ic_launcher"/>
<TextView
android:id="@+id/tv_nickname"
android:layout_width="wrap_content"
android:layout_height="44dp"
android:layout_marginLeft="8dp"
android:layout_toRightOf="@id/iv_avatar"
android:gravity="center_vertical"
android:text="snowbean"
android:textSize="12sp" />
<View
android:id="@+id/top_divider"
android:layout_width="match_parent"
android:layout_height="0.2dp"
android:layout_below="@id/tv_nickname"
android:background="#33000000" />
</RelativeLayout>
</FrameLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
private RecyclerView mFeedList;
private RelativeLayout mSuspensionBar;
private TextView mSuspensionTv;
private ImageView mSuspensionIv;
private int mCurrentPosition = 0;
private int mSuspensionHeight;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSuspensionBar = (RelativeLayout) findViewById(R.id.suspension_bar);
mSuspensionTv = (TextView) findViewById(R.id.tv_nickname);
mSuspensionIv = (ImageView) findViewById(R.id.iv_avatar);
final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
final FeedAdapter adapter = new FeedAdapter();
mFeedList = (RecyclerView) findViewById(R.id.feed_list);
mFeedList.setLayoutManager(linearLayoutManager);
mFeedList.setAdapter(adapter);
mFeedList.setHasFixedSize(true);
mFeedList.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
mSuspensionHeight = mSuspensionBar.getHeight();
}
@Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
View view = linearLayoutManager.findViewByPosition(mCurrentPosition + 1);
if (view != null) {
if (view.getTop() <= mSuspensionHeight) {
mSuspensionBar.setY(-(mSuspensionHeight - view.getTop()));
} else {
mSuspensionBar.setY(0);
}
}
if (mCurrentPosition != linearLayoutManager.findFirstVisibleItemPosition()) {
mCurrentPosition = linearLayoutManager.findFirstVisibleItemPosition();
mSuspensionBar.setY(0);
updateSuspensionBar();
}
}
});
updateSuspensionBar();
}
private void updateSuspensionBar() {
if(mCurrentPosition%2==0){
mSuspensionIv.setImageResource(R.mipmap.pic2);
}else{
mSuspensionIv.setImageResource(R.mipmap.pic1);
}
mSuspensionTv.setText("Errol " + mCurrentPosition);
}
}
FeedAdapter.java
public class FeedAdapter extends RecyclerView.Adapter<FeedAdapter.FeedHolder> {
private static final String TAG = "FeedAdapter";
@Override
public FeedHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView =
LayoutInflater.from(parent.getContext()).inflate(R.layout.item_feed, parent, false);
return new FeedHolder(itemView);
}
@Override
public void onBindViewHolder(FeedHolder holder, int position) {
if(position%2==0){
holder.mIvAvatar.setImageResource(R.mipmap.pic2);
holder.mIvContent.setImageResource(R.mipmap.pic2);
}else{
holder.mIvAvatar.setImageResource(R.mipmap.pic1);
holder.mIvContent.setImageResource(R.mipmap.pic1);
}
holder.mTvNickname.setText("Errol " + position);
}
@Override
public int getItemCount() {
return 100;
}
public static class FeedHolder extends RecyclerView.ViewHolder {
ImageView mIvAvatar;
ImageView mIvContent;
TextView mTvNickname;
public FeedHolder(View itemView) {
super(itemView);
mIvAvatar = (ImageView) itemView.findViewById(R.id.iv_avatar);
mIvContent = (ImageView) itemView.findViewById(R.id.iv_content);
mTvNickname = (TextView) itemView.findViewById(R.id.tv_nickname);
}
}
}
item_feed.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/iv_avatar"
android:layout_width="44dp"
android:layout_height="44dp"
android:padding="8dp"
/>
<TextView
android:id="@+id/tv_nickname"
android:layout_width="wrap_content"
android:layout_height="44dp"
android:layout_marginLeft="8dp"
android:layout_toRightOf="@id/iv_avatar"
android:gravity="center_vertical"
android:text="Snowbean"
android:textSize="12sp" />
<View
android:id="@+id/top_divider"
android:layout_width="match_parent"
android:layout_height="0.2dp"
android:layout_below="@id/tv_nickname"
android:background="#33000000" />
<ImageView
android:id="@+id/iv_content"
android:layout_width="match_parent"
android:layout_height="350dp"
android:layout_below="@id/top_divider"
android:scaleType="centerCrop" />
</RelativeLayout>
解释
其中activity_main.xml中布局代码为
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<android.support.v7.widget.RecyclerView
android:id="@+id/feed_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:scrollbars="vertical" />
<your-head-layout>
……
</your-head-layout>
</FrameLayout>
注意这里FrameLayout的第二个child应该为你列表项要悬浮显示的布局
这里我们使用的是RecyclerView来实现列表,我们都知道RecyclerView的列表布局是由LayoutManager来确定的,由于一般要实现悬浮条显示效果的列表一般都为线性列表,即我们一般会使用LinearLayoutManager。通过LinearLayoutManager,我们可以很方便的获取到RecyclerView中相应位置的View,这里我们需要获取当前悬浮条数据来源的View和其下一个数据来源的View。这两个View有什么用呢?悬浮条显示的信息是来自第一个可见View的,而其下方的View正是第二个列表项,我们可以获取到它的top值。好了接下来就真的很简单了,我们只要给RecyclerView加一个ScrollListener,并在相应的回调里做之前我们想好的事就ok了,来看一下代码
mFeedList.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
mSuspensionHeight = mSuspensionBar.getHeight();
}
@Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
View view = linearLayoutManager.findViewByPosition(mCurrentPosition + 1);
if (view != null) {
if (view.getTop() <= mSuspensionHeight) {
mSuspensionBar.setY(-(mSuspensionHeight - view.getTop()));
} else {
mSuspensionBar.setY(0);
}
}
if (mCurrentPosition != linearLayoutManager.findFirstVisibleItemPosition()) {
mCurrentPosition = linearLayoutManager.findFirstVisibleItemPosition();
mSuspensionBar.setY(0);
updateSuspensionBar();
}
}
});
其中mCurrentPosition为悬浮条信息来自的那个列表项在RecyclerView的位置