https://github.com/helloworld107/CainiaoMarket
说到轮播图我们都不会陌生,常规的思想是通过listview或者recycerview的判断不同类型来去写轮播图布局并且做出判断,这样有一个缺点就是会增加适配器的代码量和复杂程度,根据高内度,低耦合的思想自然会把轮播图分开,于是listview有了addHeadView,recycerview虽然原生没有但是通过修改也可以达到添加头和尾的功能。下面重点说一下轮播图的实现。
其实轮播图就是一个布局,只不过这个布局一般是动态的可以操作的,所以只要一个类能返回布局并且进行操作即可,并不是四大组件,也不需要自定义控件,就是一个单独的类,下面分析源码
布局很简单,就是一个viewpager,linearlayout用来放置坐标点,如果需要显示文字内容,还可在添加一个半透明的textview
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="160dp">
<android.support.v4.view.ViewPager
android:id="@+id/item_home_picture"
android:layout_width="match_parent"
android:layout_height="160dp">
</android.support.v4.view.ViewPager>
<LinearLayout
android:id="@+id/item_home_picture_page"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="3dp"
android:layout_marginRight="10dp"
android:orientation="horizontal"
>
</LinearLayout>
</RelativeLayout>
public class HeadView {
@InjectView(R.id.item_home_picture)
ViewPager mItemHomePicture;
@InjectView(R.id.item_home_picture_page)
LinearLayout mItemHomePicturePage;
private List<HeadPicBean> mDatas;
private Context mContext;
private int length = 0;
private View mInflate;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (mItemHomePicture != null) {
int currentItem = mItemHomePicture.getCurrentItem();
currentItem++;
mItemHomePicture.setCurrentItem(currentItem);
}
轮播图无线循环的技巧之一,也可以通过写一个线程达到目的
mHandler.removeMessages(0);消除消息这句话一定要执行,放置过多的资源消耗导致oom
mHandler.sendEmptyMessageDelayed(0, 5000);
}
};
//这句话是listview最终需要的结果,既程序的出口
public View getInflate() {
return mInflate;
}
public HeadView(List<HeadPicBean> datas, Context context) {
mDatas = datas;//数据得有吧
mContext = context;
//原点长度
length = CommonUtils.dip2px(5, mContext);屏幕适配方法之一,其实就是根据像素,屏幕密度的关系做了一个简单计算
;
initView();//初始化我们的view
if (mDatas != null) {
refreshHoldView();//开始轮播吧
}
}
public View initView() {
mInflate = View.inflate(mContext, R.layout.item_home_picture, null);
ButterKnife.inject(this, mInflate);
return mInflate;
}
public void refreshHoldView() {
mItemHomePicture.setAdapter(new PictureAdapter());
//添加右侧下面的导航标题
for (int i = 0; i < mDatas.size(); i++) {
View point = new View(mContext);
point.setBackgroundResource(R.drawable.white_point);
//这个params修饰的还是point自己,为了适配,我们还会进行dp转px
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(length, length);
params.leftMargin = length;
params.bottomMargin = length;
mItemHomePicturePage.addView(point, params);
//默认第一个亮
if (i == 0) {
point.setBackgroundResource(R.drawable.red_point);
}
}
//处理点的变化
mItemHomePicture.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
position = position % mDatas.size();
//首先全黑,然后再选择对的亮
for (int i = 0; i < mDatas.size(); i++) {
mItemHomePicturePage.getChildAt(i).setBackgroundResource(R.drawable.white_point);
if (i == position) {
mItemHomePicturePage.getChildAt(i).setBackgroundResource(R.drawable.red_point);
}
}
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
//设置一个中间坐标是为了可以向左滑动
一定要注意为了左右滑动这里的值没必要取integer.max这样非常大的值,因为这样的值再取余数是一个非常复杂的运算,分分钟钟anr,放到子线程都不一定会解决,还有实际用户也不会往左边滑动太多,所以适合就是最好
int diff = 100 % mDatas.size();
int index = 100;
mItemHomePicture.setCurrentItem(index - diff);
//如果用户点到图片不应该移动吧
mItemHomePicture.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mHandler.removeMessages(0);
break;
case MotionEvent.ACTION_UP:
mHandler.sendEmptyMessageDelayed(0,5000);
break;
case MotionEvent.ACTION_MOVE:
break;
default:
break;
}
return false;
}
});
mHandler.sendEmptyMessageDelayed(0,5000);
}
class PictureAdapter extends PagerAdapter {
@Override
public int getCount() {
if (mDatas != null) {
return 1000;
}
return 0;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
ImageView imageView = new ImageView(mContext);
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
//默认位置肯定是从0开始的,取余是防止超出界限引发空指针,如果想左右滑动,就需要先把位置调整到中间
position = position % mDatas.size();
Glide.with(mContext).load(mDatas.get(position).getImgUrl()).into(imageView);
container.addView(imageView);
return imageView;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
}
public Handler getHandler() {
return mHandler;
}
}
之后就可以把轮播图通过listview.addHeadView(new headviwe(数据).getInflate)去用啦,是不是很简单