代码已同步至码云上,有兴趣的小伙伴可以去看下:

    https://git.oschina.net/joy_yuan/ShoppingMall


    前面第二天的博文里,讲了利用radiogroup的状态切换的回调方法,来实现fragment的切换,下面讲第一个页面,即homeFragment的导航图片的切换功能。

        具体效果图如下: 上面的图片是几个远程图片,需要实现几张图片的循环切换

wKioL1mWSGbjh7ieAAC-WXmka70903.png-wh_50


    一、主页面的布局

    主页面布局,整体上分三块:

    1、头部的搜索框

    2、头部下面的主题部分,是一个recycleview构成的内容展示区域

    3、右下角的一个图片,实现点击一下后,直接跳转到顶部的功能


    a 头部搜索框布局

        是在2个textview的基础上做的更改:

            搜索框那个textview实现了背景图就是搜索框的效果,drawableleft放一个搜索图片即可实现

            消息那块,是在textview的 drawabletop放一个图片即可

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:background="#ed3f3f"
              android:orientation="horizontal"
              android:layout_width="match_parent"
              android:layout_height="wrap_content">

    <TextView
        android:id="@+id/tv_search_home"
        android:layout_gravity="center_vertical"
        android:gravity="center_vertical"
        android:drawableLeft="@drawable/home_search_icon"
        android:background="@drawable/home_search_shape"
        android:layout_weight="1"
        android:drawablePadding="10dp"
        android:padding="5dp"
        android:text="请输入搜索信息"
        android:textSize="13sp"
        android:layout_width="wrap_content"
        android:layout_height="35dp"/>

    <TextView
        android:id="@+id/tv_message_home"
        android:drawableTop="@drawable/new_message_icon"
        android:textColor="#fff"
        android:text="消息"
        android:layout_margin="10dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</LinearLayout>

     b 、主页面布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent">
<include
    android:id="@+id/titlebar"
    layout="@layout/titlebar" />

    <ImageButton
        android:id="@+id/ib_top"
        android:layout_marginRight="20dp"
        android:layout_marginBottom="20dp"
        android:layout_alignParentRight="true"
        android:layout_alignParentBottom="true"
        android:background="@drawable/top_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="gone"
        />

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv_home"
        android:layout_below="@+id/titlebar"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </android.support.v7.widget.RecyclerView>
</RelativeLayout>

       

    二 主页面的功能

            1、继承自baseFragment,实现里面的方法,即inITview和inItdata().

        在inITview里,返回要展示给首页显示的布局,即

            View view=View.inflate(context,R.layout.fragment_home,null);

        最后return view; 展示这个fragment_home.xml布局给页面显示。

/**
 * 强制子类实现他,让在oncreateview里显示这个布局。
 *
 * @return
 */
@Override
public View initview() {

    View view=View.inflate(context, R.layout.fragement_home,null);
    tv_search_home= (TextView) view.findViewById(R.id.tv_search_home);
    tv_message_home= (TextView) view.findViewById(R.id.tv_message_home);
    rv_home= (RecyclerView) view.findViewById(R.id.rv_home);
    ib_top= (ImageButton) view.findViewById(R.id.ib_top);

    //设置监听
    initListener();
    return view;
}

private void initListener() {
    //设置置顶按钮监听
    ib_top.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            rv_home.scrollToPosition(0);
        }
    });

    tv_search_home.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Toast.makeText(context,"点击了搜索",Toast.LENGTH_SHORT).show();
        }
    });

    tv_message_home.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Toast.makeText(context,"点击了消息",Toast.LENGTH_SHORT).show();
        }
    });
}

            2、利用fragment的生命周期,在创建完homeFragment,这个fragment开始展示时,即homefragment回调onActivityCreated()方法时,加载数据。具体可看看我写的父类,BaseFragment。

            3、加载数据时,即调用initData()方法时,去联网获取数据,在这里利用了okhttpUtils,去获取数据

        

@Override
public void initData() {
    super.initData();

    System.out.println("开始加载数据--------------------------");
    getDataFromNet();
}

private void getDataFromNet() {
    String url = Constants.HOME_URL;
    OkHttpUtils
            .get()
            .url(url)
            .build()
            .execute(new StringCallback()
            {
                /**
                 * 联网失败,调用此方法
                 * @param call
                 * @param e
                 * @param id
                 */
                @Override
                public void onError(Call call, Exception e, int id) {
                    Log.e(TAG, "onError: 首页失败时返回错误=="+e.getMessage());
                }

                /**
                 * 联网成功,调用此方法
                 * @param response
                 * @param id
                 */
                @Override
                public void onResponse(String response, int id) {

                    Log.d(TAG, "onResponse: "+response);
                    /**
                     * 解析json字符串
                     */
                    processData(response);
                }
            });

}

        

            4、获取到网络上的数据json字符串后,利用阿里巴巴的fastjson去解析字符串,将字符串解析为实体类对象。    在解析为实体类对象前,我们需要知道实体类有哪些属性,根据json返回的数据,利用gson,将返回的字符串,反向生成实体类。步骤如下:

            a、打开Android studio的setting

            b、找到plugins,在右侧搜索框输入gson,找到gsonformat,点击安装,安装后,需要重启Androidstudio。

            c 、在homeFragment类的任何一个位置,放置光标,然后点击Androidstudio上方工具栏里的code,选择generate,然后选择Gsonformat,在弹出的框内,将返回的json字符串全部复制粘贴到这个框内,点击OK

            d、上步中点ok后,会自动分析json字符串构成,然后会预生成实体类的属性给用户,如果确认,点击OK即可生成该json字符串对应的实体类,ResultDataBean.java类。

            5、开始解析json字符串,利用fastjson时,需要在build.glide里加入

compile 'com.alibaba:fastjson:1.1.61.android'  引用fastjson的jar包到项目

            6、解析完字符串后,就像给listview设置适配器一样,需要给recycleview也设置适配器,然后设置它的布局管理者来显示这个recycleview里的图片轮播

/**
 * 解析字符串
 * @param json
 */
private void processData(String json) {
    ResultBeanData result = (ResultBeanData) JSON.parseObject(json,ResultBeanData.class);
    resultBean = result.getResult();
    if (resultBean!=null){
        //将数据传给适配器
        adapter=new HomeFragmentAdapter(context,resultBean);
        rv_home.setAdapter(adapter);

        //给recycleview设置布局管理者
        rv_home.setLayoutManager(new GridLayoutManager(context,1));
    }

}


    三、recycleview的适配器

            1、自定义HomeFragmentAdapter必须继承extends RecycleView.Adapter,然后必须重写它的三个方法

            2、重写构造方法,接收上面6里面传给适配器里的数据

public HomeFragmentAdapter(Context context, ResultBeanData.ResultBean resultBean) {
    this.context=context;
    this.resultBean=resultBean;

    /**
     * 加载布局文件的类对象
     */
    layoutInflater = LayoutInflater.from(context);
}

            3、在适配器里,定义内部类BannerViewHolder 必须extends RecycleView.ViewHolder,在里面写了一个方法,setData(),往banner里加载图片,用到了Glide

    

/**
 * 所有类型的viewholder都要继承recycleview的viewholder
 */
class BannerViewHolder extends RecyclerView.ViewHolder{

    private Context context;
    private View view;
    private Banner banner;  //banner_viewpager里的banner控件id

    /**
     * 构造方法,实例化其中的参数
     * @param context
     * @param inflate
     */
    public BannerViewHolder(Context context, View inflate) {
        super(inflate);
        this.context=context;
        this.view=inflate;
        banner= (Banner) view.findViewById(R.id.banner);
    }

    /**
    * 往banner里加载数据,根据第三方框架Banner的方法
    **/
    public void setData(List<ResultBeanData.ResultBean.BannerInfoBean> banner_info) {

       
        List<String> p_w_picpathsUrl=new ArrayList<>();
        for (ResultBeanData.ResultBean.BannerInfoBean bannerInfoBean:banner_info){
            String p_w_picpathurl=bannerInfoBean.getImage();  //这个路径是例如: /14782094.jpg这样子的路径,需要在前面加上图片的根路径
            p_w_picpathsUrl.add(Constants.IMG_URL+p_w_picpathurl);
        }

        //利用glide加载远程图片,这里的path,就是setImages传过来的参数p_w_picpathsUrl的每个具体路径
        banner.setImageLoader(new ImageLoader() {
            @Override
            public void displayImage(Context context, Object path, ImageView p_w_picpathView) {
                Glide.with(context).load(path).into(p_w_picpathView);  //使用glide来加载远程图片
            }
        });
         //通过banner的setp_w_picpaths来绑定数据
        banner.setImages(p_w_picpathsUrl);
        banner.setDelayTime(1000);
        banner.start();
    }
}


    至此,主页面的banner轮播图片功能完成,具体代码可以参看上传到码云上的代码。


    在网上找到了一些关于Banner的一些资料,一起放到下面。

常量


常量名称描述所属方法
BannerConfig.NOT_INDICATOR不显示指示器和标题 setBannerStyle
BannerConfig.CIRCLE_INDICATOR

显示圆形指示器

setBannerStyle
BannerConfig.NUM_INDICATOR显示数字指示器setBannerStyle
BannerConfig.NUM_INDICATOR_TITLE显示数字指示器和标题setBannerStyle
BannerConfig.CIRCLE_INDICATOR_TITLE显示圆形指示器和标题(垂直显示)setBannerStyle
BannerConfig.CIRCLE_INDICATOR_TITLE_INSIDE显示圆形指示器和标题(水平显示)setBannerStyle
BannerConfig.LEFT指示器居左setIndicatorGravity
BannerConfig.CENTER指示器居中setIndicatorGravity
BannerConfig.RIGHT指示器居右setIndicatorGravity


动画常量类(setBannerAnimation方法调用)


常量类名

Transformer.Default

Transformer.Accordion

Transformer.BackgroundToForeground

Transformer.ForegroundToBackground
Transformer.CubeIn
Transformer.CubeOut
Transformer.DepthPage
Transformer.FlipHorizontal
Transformer.FlipVertical
Transformer.RotateDown
Transformer.RotateUp
Transformer.ScaleInOut
Transformer.Stack
Transformer.Tablet
Transformer.ZoomIn
Transformer.ZoomOut

Transformer.ZoomOutSlide


方法


方法名描述版本限制
setBannerStyle(int bannerStyle)设置轮播样式(默认为CIRCLE_INDICATOR)
setIndicatorGravity(int type)设置指示器位置(没有标题默认为右边,有标题时默认左边)
isAutoPlay(boolean isAutoPlay)设置是否自动轮播(默认自动) 
startAutoPlay()开始轮播 1.4开始,此方法只作用于banner加载完毕-->需要在start()后执行
stopAutoPlay()

结束轮播

1.4开始,此方法只作用于banner加载完毕-->需要在start()后执行
start()开始进行banner渲染1.4开始
setOffscreenPageLimit(int limit)同viewpager的方法作用一样 1.4.2开始
setBannerTitle(String[] titles)设置轮播要显示的标题和图片对应(如果不传默认不显示标题)1.3.3结束
setBannerTitleList(List titles)设置轮播要显示的标题和图片对应(如果不传默认不显示标题)1.3.3结束
setBannerTitles(List titles)设置轮播要显示的标题和图片对应(如果不传默认不显示标题)1.4开始
setDelayTime(int time)设置轮播图片间隔时间(单位毫秒,默认为2000)
setImages(Object[]/List<?> p_w_picpathsUrl)设置轮播图片(所有设置参数方法都放在此方法之前执行)1.4后去掉数组传参
setImages(Object[]/List<?> p_w_picpathsUrl,OnLoadImageListener listener)设置轮播图片,并且自定义图片加载方式1.3.3结束
setOnBannerClickListener(this)设置点击事件,下标是从1开始
setOnLoadImageListener(this)设置图片加载事件,可以自定义图片加载方式1.3.3结束
setImageLoader(Object implements ImageLoader)设置图片加载器1.4开始
setOnPageChangeListener(this)设置viewpager的滑动监听
setBannerAnimation(Class<? extends PageTransformer> transformer)设置viewpager的默认动画,传值见动画表
setPageTransformer(boolean reverseDrawingOrder, ViewPager.PageTransformer transformer)设置viewpager的自定义动画


Attributes属性(banner布局文件中调用)


Attributesformadescribe
delay_timeinteger轮播执行时间,默认2000
is_auto_playboolean是否自动轮播,默认true
title_backgroundcolorreference
title_textcolorcolor标题字体颜色
title_textsizedimension标题字体大小
title_heightdimension标题栏高度
indicator_widthdimension指示器圆形按钮的宽度
indicator_heightdimension指示器圆形按钮的高度
indicator_margindimension指示器之间的间距
indicator_drawable_selectedreference指示器选中效果
indicator_drawable_unselectedreference指示器未选中效果
p_w_picpath_scale_typeenum(fit_xy/center_crop)和p_w_picpathview的ScaleType作用一样