不超过100行代码的实现,先上图~
效果图
简单的效果图MyAdapter
由效果图分析可知,我们需要一个ListView,所以这里先贴出MyAdapter的代码,由于主题是实现上拉停靠效果,这里就不对MyAdapter进行优化了。
public class MyAdapter extends BaseAdapter{
private List<String> mData;
public MyAdapter(List<String> data) {
mData = data;
}
@Override
public int getCount() {
return mData.size();
}
@Override
public Object getItem(int position)
{
return null;
}
@Override
public long getItemId(int position)
{
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view=LayoutInflater.from(parent.getContext())
.inflate(android.R.layout.simple_list_item_1, parent, false);
((TextView) view.findViewById(android.R.id.text1)).setText(mData.get(position));
return view;
}
}
思路分析
- ListView有两个头布局,分别为粉色块和褐色块
- ListView有个监听器OnScrollListener,在这个监听器中有onScroll方法可以获取当前第一个显示的view的position(即方法的参数firstVisibleItem)
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)
- 滑动逻辑,但firstVisibleItem为1时,此时褐色块已经滑出屏幕,屏幕只有粉色块和ListView,此时再往上滑粉色块不动,实现这种逻辑的方法有两个,我们可以通过监听手势来判断是否移动粉色块,这种方式稍微复杂。而这里我选择的是在activity_main.xml布局中添加一个Visibility为gone的粉色块,每当粉色块的头布局要停靠时我们就显示activity_main.xml布局中的粉色块,事实上,粉色块的头布局并没有停靠,但是我们用activity_main.xml布局的粉色块就从视觉上起到了这样的作用!!!
- 接下来贴出剩下的代码,并在注释中写出我遇到的坑=。=
head1.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
//坑1: ListView的头布局(ViewGroup)必须有个View或ViewGroup
android:layout_width="match_parent"
//褐色块高度100dp 粉色块高度50dp 只是用于区分而已
android:layout_height="100dp"
//褐色
android:background="#c2461d" />
</LinearLayout>
head2.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
//粉色
android:background="#FF4081"
android:orientation="vertical">
</LinearLayout>
</LinearLayout>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
//坑2: 这里用FrameLayout并将粉色块定义在ListView的后面,
// 这样显示粉色块时会盖在ListView的粉色块头布局上。
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ListView
android:id="@+id/lv"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<LinearLayout
android:id="@+id/tab"
//这里一开始要设置为gone,在代码中需要停靠时显示
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="50dp"
//粉色块 用于实现视觉上是停靠的~
android:background="#FF4081"
android:orientation="vertical"/>
</FrameLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity
implements AbsListView.OnScrollListener {
private View tab;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//开始创建假数据
List<String> list = new ArrayList<>();
for (int i = 0; i < 200; i++) {
list.add(i + "");
}
//假数据创建完毕
//-------------------华丽分隔线----------------------------
ListView listView = (ListView) findViewById(R.id.lv);
listView.setAdapter(new MyAdapter(list));
LayoutInflater inflater = LayoutInflater.from(this);
View view1 = inflater.inflate(R.layout.head1, null);
View view2 = inflater.inflate(R.layout.head2, null);
tab = findViewById(R.id.tab);
listView.addHeaderView(view1);
listView.addHeaderView(view2);
listView.setOnScrollListener(this);
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
//没用的方法 pass
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if (firstVisibleItem == 1)
{
//褐色块移除屏幕时,粉色块进行'停靠'
tab.setVisibility(View.VISIBLE);
}
if (firstVisibleItem == 0) {
//褐色块移入屏幕时,粉色块取消'停靠'
//此时必须得gone掉,不然看起来还是停靠在上面
tab.setVisibility(View.GONE);
}
}
}
结语
代码已上传github:https://github.com/ice45571/Docked
网友评论