1. 首先看一下最终的效果图
2. 需求拆解
第一眼看见上面的效果,是不是有些朋友觉得这个效果很酷,有的高手会觉得这个效果很简单。笔者昨天刚拿到需求的时候,最开始也是觉得这个很简单,可是越分析越发现好像实现出来并不是那么容易。单个的效果可能很简单,但是这么多的效果叠在一起,可能就比较复杂了。我简单得将这个效果任务拆解一下:
- 一屏要展示3个View,支持左右滑动
- 屏幕中间两侧的View移向中间时,会有一个放大的效果;中间的View移向两侧时,会有一个缩小的效果
- 点击屏幕两侧的View,会自动滚动到屏幕的中间,同理效果要满足第2点
- 当滑动到最左侧或者最右侧时,需要立马衔接最末尾的View和最开头的View,也就是无限滚动
- 考虑性能问题,必须有一个缓存机制。否则控件的count大于30的时候,会有非常明显的卡顿
起初我想过用HorizontalScrollView来做,但是在性能问题和无限滚动的实现上有一点困难;然后我想过用RecyclerView来做横向的列表,但是在无限滚动和居中放大的实现上有一点困难;然后我考虑直接重写View来做,但是这样的风险和成本实在太高,我不能不负责任地把这种代码投放到实际项目中。最后想来想去,我觉得用ViewPager来实现是最稳妥的,虽然里面仍然有不少坑,不过都被我解决了。
3. 实现一个普通的ViewPager
这里实现一个最最最普通的ViewPager,一页一个Item,支持横向滑动:
activity_main.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">
<android.support.v4.view.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
MainActivity.java
public class MainActivity extends Activity {
private ViewPager viewPager;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager) findViewById(R.id.viewPager);
OnePageThreeItemAdapter adapter = new OnePageThreeItemAdapter(this);
viewPager.setAdapter(adapter);
}
}
OnePageThreeItemAdapter.java
public class OnePageThreeItemAdapter extends PagerAdapter {
private Context context;
private List<String> sourceData = new ArrayList<String>();
public OnePageThreeItemAdapter(Context context) {
this.context = context;
initData();
}
/**
* 初始化原始数据
*/
public void initData(){
sourceData.clear();
for(int i = 0 ; i < 5; i++){
sourceData.add(i + "");
}
}
@Override
public int getCount() {
return sourceData.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public Object instantiateItem(ViewGroup container, final int position) {
View view = View.inflate(context, R.layout.item, null);
view.setTag(String.valueOf(position));
TextView txt = (TextView) view.findViewById(R.id.txt);
txt.setText(sourceData.get(position));
container.addView(view);
return view;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
}
item.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="wrap_content"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="@+id/img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher" />
<TextView
android:id="@+id/txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:textColor="@android:color/black"
android:textSize="15sp" />
</LinearLayout>
4. 实现一屏三个View
这个功能网上已经有很多了,相信大家都已经看见过了,所以我也就简单得说一下
A. 首先ViewPager和包含ViewPager的ViewGroup设置clipChildren属性