在上一节《玩Android项目开发------首页(ViewPager+BottomNavigationBar实现导航栏)》中,实现了基本框架的搭建,现在就从首页,也就是MainFragment开始实现功能的填充。
1、Fragment的MVP框架搭建
在之前,我们都是使用Activity作为View层,那么本项目中,涉及到Fragment的使用,因为Fragment也是属于View层,因此先将BaseFragment搭建MVP框架。
public abstract class BaseFragment<V,P extends BasePresenter<V>> extends Fragment {
protected P fPresenter;
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
fPresenter = createPresenter();
if(fPresenter != null) {
fPresenter.attachView((V) this);
}
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return view();
}
protected abstract P createPresenter();
protected abstract View view();
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initData();
}
public void initData() {
}
@Override
public void onDetach() {
super.onDetach();
if(fPresenter != null){
fPresenter.detachView((V) view());
fPresenter = null;
}
}
}
其实和Activity类似,只不过是Fragment和Activity的生命周期有些不同,其他的思想和Activity一样。
2、实现首页轮播图
其实在实现轮播图时,有一个Banner开源框架可以直接使用,但是我还是使用ViewPager来自定义一个轮播图。
(1)还是通过网络请求获取轮播图的数据信息。
具体网络请求的API网站都有,就不在这里一一列举了,将获取的数据回调到MainFragment的showBanner
方法中。
(2)得到的轮播图数据,是一个List
集合,List
集合的大小就是轮播图的个数。
public void showBanner(List<BannerBean.DataBean> data) {
//轮播图的容器
List<ImageView> imageList = new ArrayList<>();
titleList = new ArrayList<>();
for (int i = 0; i < data.size(); i++) {
ImageView imageView = new ImageView(getContext());
//获取当前ImageView的url
String url = data.get(i).getImagePath();
Log.e("TAG","url===="+url);
//Glide加载图片
Glide.with(getContext()).load(url).into(imageView);
imageList.add(imageView);
//有几张图就几个圆点
ImageView point = new ImageView(getContext());
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
params.gravity = Gravity.CENTER;
params.rightMargin = 10;
point.setLayoutParams(params);
point.setBackgroundResource(R.drawable.point_selector);
ll_point.addView(point);
//设置红点颜色
if(i == 0){
point.setEnabled(true);
//刚进入界面就显示标题
tv_title.setText(data.get(i).getTitle());
}else{
point.setEnabled(false);
}
//标题数组
titleList.add(data.get(i).getTitle());
}
//设置适配器
adapter = new MainFragmentPagerAdapter(getContext(),imageList);
vp_banner.setAdapter(adapter);
//发送延时消息
handler.sendEmptyMessageDelayed(MSG_WHAT,3000);
}
适配器代码:
public class MainFragmentPagerAdapter extends PagerAdapter {
private final Context context;
private final List<ImageView> imageList;
public MainFragmentPagerAdapter(Context context, List<ImageView> imageList){
this.context = context;
this.imageList = imageList;
}
@Override
public int getCount() {
return imageList.size();
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view == object;
}
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
ImageView imageView = imageList.get(position);
container.addView(imageView);
return imageView;
}
@Override
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
// super.destroyItem(container, position, object);
container.removeView((View) object);
}
}
(3)添加底部圆点,有几张图就几个圆点,一样的逻辑思路;将创建好的圆点添加到LinearLayout。
//有几张图就几个圆点
ImageView point = new ImageView(getContext());
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
params.gravity = Gravity.CENTER;
params.rightMargin = 10;
point.setLayoutParams(params);
point.setBackgroundResource(R.drawable.point_selector);
ll_point.addView(point);
(4)滑动界面,对应的圆点也变化。
这个的实现就是根据ViewPager当前的位置,来设置当前位置的圆点的颜色:设置ViewPager监听,监听当前页面的位置,先设置一个prePosition为上一个页面的位置,当滑动到下一个页面时,将上一个页面的状态改变。
//preposition
private int prePosition = 0;
private class MainPagerChangedListener implements ViewPager.OnPageChangeListener {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
ll_point.getChildAt(prePosition).setEnabled(false);
ll_point.getChildAt(position).setEnabled(true);
prePosition = position;
//设置标题
tv_title.setText(titleList.get(position));
}
@Override
public void onPageScrollStateChanged(int state) {
}
}
(5)同样也在此设置标题,根据页面的切换切换标题。
注意:这里只是切换页面时,切换标题;刚进入应用的时候,也要显示标题。
//设置红点颜色
if(i == 0){
point.setEnabled(true);
//刚进入界面就显示标题
tv_title.setText(data.get(i).getTitle());
}else{
point.setEnabled(false);
}
(6)设置页面自动滑动
通过handler实现,发送延迟消息。
//发送延时消息
handler.sendEmptyMessageDelayed(MSG_WHAT,3000);
//Handler
private Handler handler = new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
int item = vp_banner.getCurrentItem() + 1;
vp_banner.setCurrentItem(item);
//循环发送
handler.sendEmptyMessageDelayed(MSG_WHAT,3000);
}
};
(7)支持左右无限滑动
在上边做了自动滑动操作之后,当滑动到最后一个图的时候,就不再滑动了,所以要支持无限滑动。
之所以不能无限滑动,因为在适配器中得到图的数量为imageList.size()
= 4:
@Override
public int getCount() {
return imageList.size();
}
因此将其设置为无限大,然后修改对应的position就可以实现无限滑动。
改动1:ViewPager适配器源码
@Override
public int getCount() {
return Integer.MAX_VALUE;
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view == object;
}
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
int realPosition = position % imageList.size();
ImageView imageView = imageList.get(realPosition);
container.addView(imageView);
return imageView;
}
改动2:ViewPager监听器源码
@Override
public void onPageSelected(int position) {
int realPosition = position % titleList.size();
ll_point.getChildAt(prePosition).setEnabled(false);
ll_point.getChildAt(realPosition).setEnabled(true);
prePosition = realPosition;
//设置标题
tv_title.setText(titleList.get(realPosition));
}
效果如下。
目前首页轮播图功能已经实现了,后边还会继续更新!