android 轮播下标,Android 首页轮播图和list混合(RecyclerView 添加 Header)
使用 convenientBanner 轮播图给 RecyclerView 添加 header先来看看效果图。我们要实现的就是上面轮播图轮播,下面是列表 list 展示数据。实际应用中很多都会使用轮播图去插入广告,活动等。那么我们要怎么实现呢?思路有很多,可以用 ViewPager 去实现轮播图,不过使用比较麻烦,要自己实现无限循环轮播,自动轮播等。还可以用 RecyclerView 去打造一个轮
使用 convenientBanner 轮播图给 RecyclerView 添加 header
先来看看效果图。我们要实现的就是上面轮播图轮播,下面是列表 list 展示数据。实际应用中很多都会使用轮播图去插入广告,活动等。
那么我们要怎么实现呢?
思路有很多,可以用 ViewPager 去实现轮播图,不过使用比较麻烦,要自己实现无限循环轮播,自动轮播等。
还可以用 RecyclerView 去打造一个轮播图。LinearSnapHelper 可以帮助你滑动停止的时候某页居中。设置定时器可以实现自动轮播。
这里我们并不使用以上的方法,我们使用外部的框架 convenientBanner 去直接使用轮播图。有关详细使用可以搜一下或者点github地址 有说明。
效果图
项目开始
新建之后添加依赖
// 轮播器
compile 'com.bigkoo:convenientbanner:2.0.5'
//图片加载框架
compile 'com.github.bumptech.glide:glide:3.7.0'
因为这里的例子是使用网络图片加载的方式,所以还要添加网络权限和存储权限。
布局
主布局添加 RecyclerView 即可。整个主界面其实就是一个 RecyclerView,轮播图其实是 Rv 根据不同的 Type 添加不同的 View 来放到 Rv 头部的。后面会再提到。
另外就是 rv_header_banner.xml,这个就是放到 Rv 头部的。
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/banner"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:canLoop="true" />
还有一个 rv_header_img.xml。这个是构建 Banner 的视图的时候用到。
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
android:id="@+id/iv_head"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"/>
最后一个 rv_item.xml,这个是展示 list 数据。
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:id="@+id/tv_item"
android:layout_marginBottom="20dp"
android:textSize="20sp"
android:text="item"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
以上布局基本完成。
细心的人会发现,轮播图那里有几个小点指示器。这个的样式是我们自定义的。所以我们这里还要在 drawable 下新建两个圆点的样式文件
android:shape="oval"
xmlns:android="http://schemas.android.com/apk/res/android">
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
Adapter
在这里,Adapter 配置的核心是根据不同的 itemType 加载不同的 View。
/**
* 根据不同的 ViewType 返回不同的 ViewHolder
* 通过 setter 方法将不同的 View 注入进 Adapter
*/
public class MyAdapter extends RecyclerView.Adapter {
public static final int TYPE_HEADER = 0;
public static final int TYPE_NOMAL = 1;
private View mHeaderView;
private List mDatas = new ArrayList<>();
private OnItemClickListener mListener;
public View getmHeaderView() {
return mHeaderView;
}
public void setmHeaderView(View mHeaderView) {
this.mHeaderView = mHeaderView;
notifyItemInserted(0);//插入下标0位置
}
public void addDatas(List datas){
mDatas.addAll(datas);
notifyDataSetChanged();
}
@Override
public int getItemViewType(int position) {
if(mHeaderView == null){
return TYPE_NOMAL;
}
if(position == 0){
return TYPE_HEADER;
}
return TYPE_NOMAL;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if(mHeaderView != null && viewType == TYPE_HEADER){
return new MyViewHolder(mHeaderView);
}
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.rv_item, parent, false);
return new MyViewHolder(itemView);
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
if (getItemViewType(position) == TYPE_HEADER) {
return;
}
final int pos = getRealPosition(holder);//这里的 position 实际需要不包括 header
final String data = mDatas.get(pos);
holder.textView.setText(data);
if(mListener == null) return;
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mListener.onItemClick(pos, data);
}
});
}
/**
* 添加头部布局后的位置
* headerView 不为空则 position - 1
*/
private int getRealPosition(MyViewHolder holder) {
int position = holder.getLayoutPosition();
return mHeaderView == null ? position : position - 1;
}
@Override
public int getItemCount() {
//header 不为空,则 rv 的总 Count 需要 +1(把 Header 加上算一个 item)
return mHeaderView == null ? mDatas.size() : mDatas.size() + 1;
}
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView textView;
public MyViewHolder(View itemView) {
super(itemView);
if(itemView == mHeaderView){ return; }
textView = (TextView) itemView.findViewById(R.id.tv_item);
}
}
public void setOnItemClickListener(OnItemClickListener listener){
mListener = listener;
}
public interface OnItemClickListener{//item 点击事件接口
void onItemClick(int position, String data);
}
}
以上是 Adapter 的代码,可见加了两个 TYPE 来区分 header 和 正常的数据 item。(我们也可以加更多的 Type 去实现更复杂的布局)在 onCreateViewHolder 里面判断 TYPE 如果是 header 则返回 headerView,否则加载正常的 item 布局。里面一些函数还有逻辑都加了注释说明了,这里就不详细说了。
MainActivity
让我们回到 MainActivity,这里我们将初始化 Banner,并用 adapter.setmHeaderView 放进 Adapter 中。在使用 LayoutManager 设置一下 Rv 的布局,然后就基本完成了。
private void initBanner(){
networkImage = Arrays.asList(images);
mBanner.setPages(new CBViewHolderCreator() {
@Override
public NetWorkImageHolderView createHolder() {
return new NetWorkImageHolderView();
}
}, networkImage)
.setPageIndicatorAlign(ConvenientBanner.PageIndicatorAlign.ALIGN_PARENT_RIGHT) //设置指示器的方向(左、中、右)
.setPageIndicator(new int[] { R.drawable.indicator_gray, R.drawable.indicator_red })//设置指示器样式
.setOnItemClickListener(this)//点击事件
.setScrollDuration(1500);//滑动的时间
}
@Override
public void onItemClick(int position) {//Banner 点击事件
Toast.makeText(MainActivity.this, "Banner:"+position, Toast.LENGTH_SHORT).show();
}
public class NetWorkImageHolderView implements Holder{
private ImageView imageView;
@Override
public View createView(Context context) {
View view = LayoutInflater.from(context).inflate(R.layout.rv_header_img, null);
imageView = (ImageView) view.findViewById(R.id.iv_head);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
return view;
}
@Override
public void UpdateUI(Context context, int position, String data) {
//Glide.with(context).load(data.getImgUrl()).into(imageView);
Log.d("imgUrl", "UpdateUI: "+data);
Glide.with(context).load(data).placeholder(R.mipmap.ic_launcher_round).into(imageView);
}
}
}
convenientBanner 的基本设置就是这样。通过 setPages 来配置,上面的配置都加了注释说明,更多的配置样式可以查查。
mBanner 绑定的是 rv_header_banner.xml 视图下的 banner 。而 NetWorkImageHolderView 里面的 view 绑定了 rv_header_img.xml.里面的图片 ImageView 则是绑定了 R.id.iv_head 这个 img 控件。 总的来说,Banner 的视图 View 实际是 NetWorkImageHolderView 的 onCreateView 里面返回的。类同 Adapter 的使用
UpdateUI 这里用 Glide 加载了网络图片。Glide 不是这里的主角所以不说明了,用法也很简单。placeholder 是设置占位图。
以上就基本完成了 Banner 的配置。在 onResume 里面添加一句 mBanner.startTurning(3000) 就可以自动轮播了。
剩下的就是 Rv 的基本用法了。
View header = LayoutInflater.from(this).inflate(R.layout.rv_header_banner, null);
mBanner = (ConvenientBanner) header.findViewById(R.id.banner);
//设置高度是屏幕1/4
mBanner.setLayoutParams(new RecyclerView.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, getWindowManager().getDefaultDisplay().getHeight()/3));
mRecyclerView = (RecyclerView) findViewById(R.id.rv_content);
mLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
initBanner();
myAdapter = new MyAdapter();
myAdapter.addDatas(mData);
myAdapter.setmHeaderView(mBanner);
mRecyclerView.setAdapter(myAdapter);
myAdapter.setOnItemClickListener(new MyAdapter.OnItemClickListener() {
@Override
public void onItemClick(int position, String data) {
Toast.makeText(MainActivity.this, data, Toast.LENGTH_SHORT).show();
}
});
还有需要的可以看一下我的源码。
更多推荐
所有评论(0)