SmartBeijingNotes Day02

本文介绍了在Android开发中如何自定义NoScrollViewPager和RadioGroup,处理ViewPager触摸事件,优化性能,搭建新闻中心页面的UI框架,包括网络请求、Gson解析和数据缓存,以及使用ViewPagerIndicator创建动态页签。
摘要由CSDN通过智能技术生成

Day02

2.1细节处理

  • 自定义NoScrollViewPager

      继承ViewPager, 实现onTouchEvent, return true;
    
      /**
       * 拦截ViewPager的触摸事件, 不做任何处理
       */
      @Override
      public boolean onTouchEvent(MotionEvent arg0) {
      	return true;
      }
    
  • RadioGroup处理

      监听RadioGroup选择事件, 对ViewPager的当前页面进行切换
    
      mRadioGroup.check(R.id.rb_home);// 设置默认选项为首页
    
      mRadioGroup.setOnCheckedChangeListener(new OnCheckedChangeListener() {
    
      	@Override
      	public void onCheckedChanged(RadioGroup group, int checkedId) {
      		switch (checkedId) {
      		case R.id.rb_home:
      			mViewPager.setCurrentItem(0);// 让ViewPager切换到第一个页面
      			setSlidingMenuEnable(false);
      			break;
      		}
      	}
      });
    
  • 性能优化

      为了节省流量, 只有用户切换到该页面时,才加载当前页面的数据. ViewPager会默认预加载下一页数据.
    
      // 监听ViewPager的选中事件
      	mViewPager.setOnPageChangeListener(new OnPageChangeListener() {
    
      		@Override
      		public void onPageSelected(int position) {
      			mPagerList.get(position).initData();// 当该页面选中时,才开始初始化当前页面的数据
      		}
      	);
    
  • 设置"首页"和"设置"页面SlidingMenu不可用

      private void setSlidingMenuEnable(boolean enable) {
      	MainActivity mainUI = (MainActivity) mActivity;
      	SlidingMenu slidingMenu = mainUI.getSlidingMenu();
      	
      	if(enable) {
      		slidingMenu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
      	}else {
      		slidingMenu.setTouchModeAbove(SlidingMenu.TOUCHMODE_NONE);
      	}
      }
    

2.2新闻中心页面UI框架搭建

  • 新闻中心页面布局分析

  • 服务器环境搭建

    将服务器相关代码和文件(zhbj)拷贝到"apache-tomcat-7.0.57\webapps\ROOT"目录下

  • 访问链接http://10.0.2.2:8080/zhbj/categories.json, 获取json数据

  • 使用工具格式化json, 方便查看.(HiJson,JsonView,在线网站等)

  • 使用xUtils访问网络数据

      HttpUtils utils = new HttpUtils();
      	// RequestCallBack的泛型表示返回的数据类型, 在此我们只需要json的字符串文本, 所以传递String就可以
      	utils.send(HttpMethod.GET, GlobalContants.NEWS_URL,
      		new RequestCallBack<String>() {
    
      			// 请求成功
      			@Override
      			public void onSuccess(ResponseInfo<String> responseInfo) {
      				String result = responseInfo.result;
      				Log.d(TAG, "result-->" + result);
      				processData(result);
      			}
    
      			// 请求失败
      			@Override
      			public void onFailure(HttpException error, String msg) {
      				Log.e(TAG, "请求失败:" + msg);
      			}
      		});
    
  • 使用gson解析

      Gson(又称Google Gson)是Google公司发布的一个开放源代码的Java库,主要用途为序列化Java对象为JSON字符串,或反序列化JSON字符串成Java对象。
    
      Gson gson = new Gson();
      NewsBean news = gson.fromJson(result, NewsBean.class);
    
  • 新闻中心对象的创建

      /**
       * 封装新闻中心的对象
       * 
       * 注意: 参数起名一定要和json中的命名一致, 否则gson无法解析
       * 
       * @author Kevin
       * 
       */
      public class NewsBean {
      
      	public ArrayList<NewsMenuBean> data;
      	public ArrayList<String> extend;
      	public int retcode;
      
      	public class NewsMenuBean {
      		public ArrayList<NewsMenuTab> children;
      		public String id;
      		public String title;
      		public int type;
      		public String url;
      		public String url1;
      		
      		@Override
      		public String toString() {
      			return "NewsMenuBean [children=" + children + ", title=" + title
      					+ "]";
      		}
      	}
      
      	public class NewsMenuTab {
      		public String id;
      		public String title;
      		public int type;
      		public String url;
      		
      		@Override
      		public String toString() {
      			return "NewsMenuTab [id=" + id + ", title=" + title + "]";
      		}
      	}
      
      	@Override
      	public String toString() {
      		return "NewsBean [data=" + data + ", retcode=" + retcode + "]";
      	}
      }
    
  • 侧边栏数据填充

    • 初始化ListView

        mListView = new ListView(mActivity);
        mListView.setBackgroundColor(Color.BLACK);//设置背景色
        mListView.setDividerHeight(0);//分割线高度设置为0(去掉分割线)
        mListView.setSelector(android.R.color.transparent);//将点击效果设置为透明(去掉点击效果)
        mListView.setPadding(0, 40, 0, 0);//设置边距
      
    • ListView的item布局:

      • left_menu_item.xml

      • txt_left_menu_selector.xml

          <item android:state_enabled="true" android:color="#ff0000"/>
          <item android:color="#ffffff" android:state_enabled="false"/>
        
          </selector>
        
      • btn_left_menu_selector.xml

          <selector xmlns:android="http://schemas.android.com/apk/res/android">
        
          <item android:drawable="@drawable/menu_arr_select" android:state_enabled="true"/>
          <item android:drawable="@drawable/menu_arr_normal"/>
        
          </selector>
        
  • 侧边栏菜单点击事件处理

    • 点击item, 切换颜色

        记录选中item的位置, 点击后刷新listview,更新item状态
      
    • 点击item, 隐藏侧边栏

        MainActivity mainUI = (MainActivity) mActivity;
        SlidingMenu slidingMenu = mainUI.getSlidingMenu();
        slidingMenu.toggle();// 如果侧边栏打开,则关闭;如果关闭,则打开
      
    • 点击标题栏的菜单按钮,显示侧边栏

  • 侧边栏对应的4个详情页面 *

    • 分析UI框架结构, 抽取菜单详情页基类

        基类: BaseMenuDetailPager
      
        public abstract class BaseMenuDetailPager {
        	public Activity mActivity;
        	public View mRootView;
        
        	public BaseMenuDetailPager(Activity activity) {
        		this.mActivity = activity;
        		mRootView = initView();
        	}
        
        	/**
        	 * 初始化界面
        	 * @return
        	 */
        	public abstract View initView();
        
        	/**
        	 * 初始化数据
        	 */
        	public void initData() {
        
        	};
        }
      
      
        NewsMenuDetailPager//新闻
        TopicMenuDetailPager//专题
        PhotosMenuDetailPager//组图
        InteractMenuDetailPager//互动
      
    • NewsCenterPager中, 维护菜单详情页面的集合

    • 点击侧边栏item, 切换不同页面, 标题也要发生相应变化

  • 缓存处理

      将json数据保存在SharedPreference中, 每次读取网络数据前,先从SP从获取数据, 然后继续访问网络,加载最新数据
    
      // 先从缓存中读取数据并展示
      String cache = CacheUtils.getCache(mActivity, GlobalContants.NEWS_URL);
      if (!TextUtils.isEmpty(cache)) {
      	processData(cache);
      }
    
      // 请求成功
      @Override
      public void onSuccess(ResponseInfo<String> responseInfo) {
      	String result = responseInfo.result;
      	Log.d(TAG, "网络Json数据: " + result);
      	CacheUtils.setCache(mActivity, GlobalContants.NEWS_URL,
      			result);
      	processData(result);
      }
    

2.3.新闻详情页开发

  • 定义TabDetailPager

      继承BaseMenuDetailPager, 表示每一个页签的对象, 填充ViewPager数据
    
  • 滑动事件处理

      /**
       * 表示不对事件进行拦截, 从而可以使嵌套在ViewPager内部的ViewPager可以响应滑动动作
       * 
       * @param arg0
       * @return
       */
      @Override
      public boolean onInterceptTouchEvent(MotionEvent arg0) {
      	return false;
      }
    
      /**
       * 拦截ViewPager的触摸事件, 不做任何处理
       */
      @Override
      public boolean onTouchEvent(MotionEvent arg0) {
      	return false;
      }
    
  • ViewPagerIndicator

      ViewPager指针项目,在使用ViewPager的时候能够指示ViewPager所在的位置,就像Google Play中切换的效果一样,还能使用在应用初始化的介绍页面
    
      下载开源项目, 演示Demo
      下载地址: https://github.com/JakeWharton/Android-ViewPagerIndicator
    
  • NewsMenuDetailPager

      菜单新闻详情页
    
      TabPageIndicator mIndicator; 
      @Override
      public void initData() {
      	mTabDetailPagers = new ArrayList<TabDetailPager>();
    
      	// 初始化页签数据
      	for (NewsMenuTab tab : mNewsMenuTabs) {
      		TabDetailPager pager = new TabDetailPager(mActivity, tab);
      		mTabDetailPagers.add(pager);
      	}
    
      	mTabAdapter = new TabDetailPagerAdapter();
      	mViewPager.setAdapter(mTabAdapter);
      	mIndicator.setViewPager(mViewPager);
      }
    

2.4.ViewPagerIndicator使用流程

  • 引入library库

  • 布局文件

      在布局文件中声明TabPageIndicator控件, 必须和ViewPager搭配使用
      <com.viewpagerindicator.TabPageIndicator
          android:id="@+id/tpi_news_menu"
          android:layout_width="fill_parent"
          android:layout_height="wrap_content" />
    
      <android.support.v4.view.ViewPager
          android:id="@+id/vp_news_menu"
          android:layout_width="fill_parent"
          android:layout_height="0dp"
          android:layout_weight="1" />
    
  • 初始化

      1. 将指针和ViewPager关联起来, ViewPager页面发生变化时, 指针也会跟随变化
    
      	mIndicator.setViewPager(mViewPager);
      	mAdapter = new NewsMenuAdapter();
      	mViewPager.setAdapter(mAdapter);
    
      2. 在ViewPager的Adapter中,重写该方法:
    
      /**
       * 返回页面标题, 用于在指针中显示
       */
      @Override
      public CharSequence getPageTitle(int position) {
      	return mNewsTabDataList.get(position).title;
      }
    
  • 样式修改

      参照Demo, 给Activity设置主题样式
        <activity
          android:name=".MainActivity"
          android:theme="@style/Theme.PageIndicatorDefaults" />
    
      修改样式中的图片, 文字颜色等
      <style name="Theme.PageIndicatorDefaults" parent="android:Theme">
          <item name="vpiIconPageIndicatorStyle">@style/Widget.IconPageIndicator</item>
          <item name="vpiTabPageIndicatorStyle">@style/Widget.TabPageIndicator</item>
       </style>
    
      //页签样式修改
      <style name="Widget.TabPageIndicator" parent="Widget">
          <item name="android:gravity">center</item>
          <item name="android:background">@drawable/vpi__tab_indicator</item>//修改页签背景
          <item name="android:paddingLeft">22dip</item>
          <item name="android:paddingRight">22dip</item>
          <item name="android:paddingTop">12dp</item>
          <item name="android:paddingBottom">12dp</item>
          <item name="android:textAppearance">@style/TextAppearance.TabPageIndicator</item>
          <item name="android:textSize">16sp</item>
          <item name="android:textColor">@drawable/vpi__tab_text_color</item>//修改页签字体颜色
          <item name="android:maxLines">1</item>
      </style>
    
      vpi__tab_indicator.xml
      将默认图片改为透明: @android:color/transparent
      将选中图片改为自定义图片
    
      vpi__tab_textcolor.xml
      将vpi__tab_indicator.xml代码拷贝一份,重命名为vpi__tab_textcolor.xml,
      其中的drawable改为color, 默认颜色为黑色,选中颜色为红色
    

2.5第二天课程总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值