zoukankan      html  css  js  c++  java
  • 智慧北京02_初步ui框架_ 主界面_viewPager事件_xUtils_slidingMenu_网络缓存_数据传递

    1.使用Fragment搭建ui框架

    参考分析图

     

    1.1,Fragment生命周期

    Is added(被添加之后)

    >>onAttach()>>onCreate()>>onCreateView()//创建布局>>onActivityCreated();//activity创建好后(onCreate()执行完了之后)>>onStart()>>onResume()>>onPause()>>onStop()>>onDestory()

    1.2 创建一个Fragment的基类:参考名baseFragment(v4保持版本兼容)

    onCreate()//Fragment创建

    可以拿到这个Fragment所在的Activity对象

    mActivity = getActivity();//成员变量一般加m

    onCreateView()//初始化Fragment的布局

    返回的View就是Fragment对应的布局

    但因为这个类是基类,所以不应该直接返回View

    创建一个抽象方法让子类去实现,传入View并返回它

    然后在onCreateView()中返回这个View即可

    onActivityCreate()//fragment所依赖的acitivityonCreate()方法执行完毕

    可以用来初始化数据

    同样写一个抽象方法,让子类实现,在这个方法里重写数据

    1.3 创建两个子Fragment

     ①LeftMenuFragment的创建,继承基类,重写抽象的方法

    但是在这里View.inflate(),不能直接用this,因为Fragment是不继承上下文的,但是可以通过基类中获取的mActivity当做上下文传入

    ContentFragment的创建,步骤基本上一样

    重写该重写的方法,返回对应的布局文件

    1.4,在主界面的侧边栏和主菜单中,设置的布局文件清空(一般根节点用FrameLayout,干净)

    在主界面的activity,创建一个方法用来初始化Fragment

    ①拿到Fragment管理器>>

    fm = getSupportFragmentManager()//兼容低版本的管理器

    transaction = fm.beginTransaction();//开始事务

    Transaction.replace(id,fragment)//id,fragment提供的位置,fragment对象

    如果参数异常就写个配置文件,名称与jar包一致(包含后缀名.properties)

    内容为src=XXXX//源码的路径(sdk/extras/android/xxxv4包的源码)

    然后重启Eclipse即可

    //两个Fragment可以一起替换

    Transaction.commit()//提交事务

    ActivityonCreate()时调用

    Transaction.Replasc()也有三个参数的,tag(String)第三个参数,以后找起来会比较方便

    fm.findFragmentByTag(String tag)//通过Fragment管理器找到标记获取Fragment的对象.

    2,主页面

     

    2.1 主页面分析:从上至下(先不看内容填充)

    上面是一个Viewpager

    下面是一个RadioGroup + RadioButton

    2.2 ContentFragment,搭建ui框架

    2.2.1底部导航栏

    RadioButton中 可以设置属性Button = @null//去掉可以被选中的小圆框

    图片是通过drawableTop设置出来的

    RadioButton背景设置全透明(因为有的手机上会有显示问题)

    同样的,要设置状态选择器(选中的(state_checked)状态选择器)

    记得要设置ID,不设置ID的话,全部都会被选中

    默认设置首页被选中

    2.2.2 ViewPager显示

    ①界面分析:

     

    每一个ViewPager页面都有共同的地方,

    所以抽取一个布局基类base_pager

    抽取一个标题的布局title_bar

    base_pager include导入这个布局

    ② 创建一个类(base包下)(单纯的类,什么都不继承)

    BasePager表示ViewPager每一个页面的基类

    这个类代表五个标签页的基本类

    创建方法:initView()//初始化布局,在构造中把Activity传进来即可

    在这里把布局View找到,找到中间关心的控件

    //返回这个布局对应的View即可,在构造中把这个View用成员变量记录下来

    initData()//初始化数据

    ③创建实现类(impl):

    创建一个首页类继承base_pager

    重写的初始化数据方法中,new一个TextView(根据页面内容来,这里首页内容就只是一个TextView,所以只要new 一个TextView就可以了)

    拿到空的帧布局对象(Base_pager已经找到它了,可以以直接使用)

    然后依次把其它几个标签页的创建出来(这里先不用填充数据)

    3.填充标签页,禁用ViewPager的滑动事件

    3.1 创建ViewPager适配器

    3.2 初始化5个标签页

    创建一个集合保存五个BasePager对象

    PagerAdapterinstantiateItem()初始化一个View对象的时候

    通过BasePager.mRootView获取到这个标签页对应的View对象,返回它

    记得调用一下initData()让它生效

    然后添加到ViewPager上面

    额外:右击方法名,Open Call Hierachy可以看到调用的层级结构

    3.3 禁用ViewPager的滑动换页(自定义一个ViewPager)参考:noScrollViewPager

    重写一下onTouchEvent(event)直接返回true即可

    因为google的工程师就是在触摸事件里让页面滑动的,所以返回true就可以了

    3.4 点击标签切换页面&&性能优化

    ①拿到RadioGroup对象,设置切换监听器

    ②通过重写的方法里checkedId对应的选项,判断是哪一个标签卡被选中了.

    mViewPager.setCurrentItem(对应的索引就可以了,是否要平缓滑动效果(flase));

    一个参数的就默认带有动画效果了

    ViewPager会提前加载下一个标签,在这里是没有必要预加载的.

    ViewPager原生的方法修改起来很麻烦,所以在初始化数据的时候,不要直接调用initData()方法,因为初始化数据再有些标签卡中很耗时间

    解决方式:设置ViewPager的页面监听,或在RadioButton中里面写

    这里用ViewPager的页面监听来写,代码更简练一些?

    在监听方法中,通过页面被选中的方法,参数Position来初始化数据

    额外:进入界面的时候没有数据

    在接入界面的时候加载上默认的数据

    4,侧边栏的开启和禁用(在中间三个选项卡可以划出来侧边栏,第一个和最后一个标签没有侧边栏,这个根据情况来的)

    4.1 隐藏侧边栏的按钮,在每一个标签的实现类中,隐藏对应的按钮

    4.2 当第一个页面和最后一个页面被选中的时候

    ViewPager的监听器中,当选中的position为第一个或最后一个的时候

    禁用掉侧边栏

    获取侧边栏对象

    ContentFragment中通过mActivity(SlidingMenuFragmentActivity)强转拿到

    然后获取到侧边栏对象

    设置滑动模式

    SlidingMenu.setTouchMode(SlidingMenu.TOUCHMODE_NONE);//设置模式

    5,新闻中心页面的开发

     

    ①新闻中心的数据都是网络传递过来的,包括侧边栏的内容也是解析网络数据得到的(使用服务器数据,zhbj的文件夹丢到tomcat服务器的root下访问)

    访问地址:服务器//zhbj/categories.json

    工具:HiJson,JSON串拷贝进来,可以格式化JSON字符串,方便阅读

    解析JSON[]代表JSON数组,{}代表JSON对象

    有的JSON串最后会有retcode 表示这个JSON串是否获取成功

    ②使用XUtils请求数据

    在需要请求服务器的标签类中initData()中请求网络

    XUtils开源框架,四大模块

    DBUtils,ViewUtils,HttpUtils,BitMapUtils(这里会用到后面三个模块)

    6,Xutils使用

    获取Xutils对象

    HttpUtils utils = new HttpUtils();

    Utils.send(HttpMethod.GET,url(不写死,写到一个类中),new RequestCallBackXX())

    GlobalConstans类下

    Public static final String SERVER_URL=”服务器主域名”

    http://10.0.2.2(模拟器访问本机ip):8080/zhbj

    Public static final String categories_URL=SERVER_URL + ”/cetgories.json”;//类别

    在回调方法中,

    请求成功的方法,获取结果response.result.

    请求失败的方法参数error,msg

    error.printStackTrace()//打印错误信息

    msg String错误信息

    7,使用Gson解析Json

    Gson:google为了提高json解析效率搞出来的玩意(jar)

    Gson gson = new Gson();

    gson.fromjson(String,clazz);//clazz是保存服务器数据的javaBean

    创建一个JSON封装类(照着JSON串来写)

    遇到大括号,就是一个对象,遇到中括号就是一个集合

    最外层的大对象就

    public int retcode;

    Public ArrayList<Integer> extend //因为下面是一堆数据,一般用集合装下来

    Public ArrayList data//只要是中括号,大部分情况下可以用集合表示

    遇到大括号,在这个类中创建一个类,表示这个对象的内容

    如果是单个的字段(用不上的不用解析)直接创建成员变量就行

    Public int id ;

    如果又是一个大括号,再创建一个平行的内部类

    依次创建下去即可

    使用JSON解析时,对象书写技巧:

    {}创建对象,[]创建和,所有名称要和JSON字段高度一致(类名无所谓)

    创建完毕后

    gson.fromJson(json.clazz)//返回的就是这个clazz 对象

    8,网络缓存

    原理:JSON数据作为缓存的内容,标示为:URL路径

    缓存的东西就是JSON字符串.所以要保持URLJSON串相互对应的关系

    ①写一个工具类 CacheUtils

    应该有两个方法,

    写缓存setCache(String url,String json,Context,context)

    urlkey,jsonvalue,保存在本地

    这里保存在sp中比较方便

    读缓存getCache(String url);//通过sp读到缓存内容,返回缓存即可(默认为null)

    ②使用方式:

    需要请求数据的标签,先判断有没有缓存(是否为null)

    如果有的话,就直接解析数据,否则就访问网络,获取数据

    写缓存的位置,在请求完数据之后写入

    细节1:URL可能不是一直对应这个JSON

    解决1:给缓存设置有效期(一个礼拜或一天,必须刷新一次)

    解决2:读缓存的时候(读取完了缓存,调用一下解析数据的方法),不管是否有缓存都请求一次服务器(不用担心新旧缓存的问题,这样既有老的数据,可以让用户先看到一些数据,用户体验好一些,然后网络加载完之后更新,用户耐心更好)

    细节2:储存在sp中会导致sp可读性太差

    解决1:数据库

    解决2:用文件储存

    URL为文件名,JSON为文件内容,读缓存的时候就直接查找有没有缓存文件即可.

    但是URL有可能有特殊字符,所以可以用MD5转换一下,就可以作为文件名

    注意:网络缓存一般就是缓存的JSON,面试问到也就是缓存JSON

    如果URL后面带参数,也是同样要带参数的(路径拼接即可)

    9,设置新闻中心的侧边栏数据

    重点是如何拿到侧边栏对象

     

    在这里MainActivity其实已经获取到了,就是mActivity;

    在解析数据的方法里

    通过mActivity强转得到MainActivity

    MainActivity,创建一个方法,找到侧边栏对象

    FragmentManager .findFragmentByTag()//通过前面设置的标签获取Fragment对象

    然后在新闻中心的Pager类中,拿到侧边栏对象

    在侧边栏Fragment类中,创建一个方法设置数据,在新闻中心类中,把需要传递的数据通过参数传递过去(JSON串中的新闻中心数据)

    这里的侧边栏其实就是一个ListView

    把传递过来的新闻中心数据解析出来,传递到ListView

    这里使用ViewUtils模块,使用注解的方法替代fbconClick;

    ①注入View和事件

    ViewUtils.inject(this,view);

    ②创建需要替代的成员变量:

    @ViewInject(id)

    Private ListView mListView;

    ViewUtils底层其实也是fbc,不过是通过注解的方式封装好了.

    ③创建适配器,设置数据

    getItem()可以直接返回一个与position相关的对象(这里可以把它的返回值对象改了)

    getItemId()可以直接把position返回

    getView()方法

    需要再写一个item的布局文件

    这里的侧边栏条目状态选择器,通过enabled是否可用来设置状态

    (因为LIstView不像 RadioButton,有选中和不被选中的选择)

    定义一个成员变量记录被点击(也就是被选中的条目)就让它设置可用,否则设置不可用

    ④设置ListView点击事件监听器

    更新被点击的条目,然后刷新适配器(因为侧边栏条目比较少,所以不影响太多效率)

    ⑤优化:点击了其它条目,应该收集侧边栏

    创建一个方法,toggle()//开关的方法

    通过mainActivity(mainUi)拿到侧边栏对象

    slidingMenu.toggle()//调用之后会根据当前状态自动判断是否显示

    额外:设置左上角的按钮事件

    10,点击侧边栏切换菜单详情页

    侧边栏点击之后,要修改Fragment里面的内容

    搭建详情页Ui框架

     

    ①抽取一个菜单详情页的基类BaseMenuDetailPager

    同样的,在构造方法里获取到mActivity.调用initView()方法得到返回的View

    这个基类的initView()因为每个孩子的都不一样,所以让子类去强制实现

      initData()//这个方法可以强制,也可以不强制

    然后把四个详情页都创建出来

    这里为了观察方便,先返回四个简单的TextView

    ②在侧边栏页面中设置当前的菜单详情页(抽取方法)setCurrentDetailPager()

    重点是拿到菜单详情页对象

     

    先拿到MainActivity(mainUi),同拿到侧边栏一样,拿到主页

    通过主页的mPagers集合,拿到新闻中心的对象

    参考名getNewsCenterPager()

    然后在NewsCenterPager类中创建方法setCurrentDetailPager(int position)索引传递

    在侧边栏中,通过它的对象调用这个方法

    11.,实现侧边栏详情页的切换

    NewsCenterPager创建的方法setCurrentDetailPager(int position),

    重新给它所在的Fragment设置内容

    创建一个集合保存下这四个菜单详情页pager.

    在上面的方法里,拿到对应索引的pager对象,拿到布局

    然后把view添加到帧布局中

    添加的同时,也要初始化数据

    额外1:添加之前要把帧布局中之前的View清理掉,removeAllViews();

    额外2:新闻中心默认应该显示新闻菜单pager的内容

    解析完数据,切换新闻详情页

    额外3:更新标题,最简单方法,就是解析数据时候把网络数据的信息直接传进来

    额外4:下方导航栏切换之后,再切换到新闻中心,侧边栏数据不变

    需要在每次切换到新闻中心之后,会调用侧边栏设置数据的方法里,在这个方法里把侧边栏的索引归零(修改记录选中的变量即可)

  • 相关阅读:
    XGBoost原理解析
    变分贝叶斯学习(variational bayesian learning)及重参数技巧(reparameterization trick)
    Tensorflow Probability Distributions 简介
    树形dp--hdu 1520 anniversary party
    线段树II--区间修改
    leetcode---different ways to add parentheses
    线段树
    实现最大堆
    编写支持对齐分配的malloc和free函数
    指针和引用的区别,指针和数组的区别
  • 原文地址:https://www.cnblogs.com/adventurer/p/5662848.html
Copyright © 2011-2022 走看看