《新闻》之笔记五

来源:互联网 发布:跑酷教学软件 编辑:程序博客网 时间:2024/05/08 01:15
 上一节已经把从网络上取到的json 数据 解析出来,把 title 传递给了 MenuFragment. 下面实现把他们填充上去。
因为首页,新闻中心,娱乐天地等的菜单的内容都不一样,要实现点一下就刷新滑动菜单中的内容,最简单的办法就是每一个都写一个 Fragment 替换上去,但是这样就冗余了,要多写几个类。那怎么封装呢?
 思路:使用3个ListView ,把它们叠加起来,让一个显示,把其它两个ListView  Gone掉。使用什么布局能让它们叠加呢---FrameLayout.
    <FrameLayout        android:layout_width="match_parent"        android:layout_height="match_parent" >        <ListView            android:id="@+id/lv_menu_news_center"            android:layout_width="match_parent"            android:layout_height="match_parent"            android:cacheColorHint="@android:color/transparent"            android:divider="@null"            android:fadingEdge="none"            android:focusable="true"            android:listSelector="@drawable/transparent"            android:scrollbars="none"            android:visibility="visible" >        </ListView>  .....
要用 ListView 显示数据,就要用 BaseAdapter 填充。我们先把上节说的 initMenu()实现:
public void initMenu(List<String> menuNewCenterList) {   /**最好先清空一下  **/menuList.clear();menuList.addAll(menuNewCenterList);if(menuAdaper==null){menuAdaper = new MenuAdapter(ctx,menuList);lv_menu_news_center.setAdapter(menuAdaper);}else{menuAdaper.notifyDataSetChanged(); //数据改变时,刷新一下}menuAdaper.setCurPosition(0);}
这里Adapter 优化一下,这样就不会每次都new 一个出来。
在 BaseAdapter 中定义一个记录当前选中的 Item的方法,然后让选中的变成红色,并变更背景为黑色:

private int curPosition=0;  //当前选中的项//记录选 中的是位置 public void setCurPosition(int position){ curPosition=position;  //选中之后,记得让它刷新 ,不然不会变色 notifyDataSetChanged();   }@Overridepublic View getView(int position, View convertView, ViewGroup parent) {if(convertView==null){convertView=View.inflate(ctx, R.layout.item_menu_layout, null);}TextView textview = (TextView)convertView.findViewById(R.id.tv_menu_item);ImageView imageView=(ImageView)convertView.findViewById(R.id.iv_menu_item);textview.setText(menuList.get(position));/**让选中的为红色,没选中的是白色**/if(curPosition==position){textview.setTextColor(getResources().getColor(R.color.red));imageView.setBackgroundResource(R.drawable.menu_arr_select);//变更背景图片convertView.setBackgroundResource(R.drawable.menu_item_bg_select);}else{textview.setTextColor(getResources().getColor(R.color.white));imageView.setBackgroundResource(R.drawable.menu_arr_normal);convertView.setBackgroundResource(R.drawable.transparent);}return convertView;}
然后,我们再实现点击的效果,并让滑动菜单 退回去:
public void onItemClick(AdapterView<?> parent, View view, int position,long id) {//设置它当前选中哪个itemmenuAdaper.setCurPosition(position);//这个slidingMenu是在BaseFragment中拿到的slidingMenu.toggle();}
最后实现的效果是这样子的:
          
2》 对BaseAdapter 进行封装
使用 BaseAdapter 时,最有用的是getView(),其它3个方法都没什么用但用必须写,可以封装一下。  创建一个类 HMBaseAdapter 继承 BaseAdapter,再封闭上面3个方法。

/** *  Adapter基类  *  */public abstract class MyBaseAdapter<T, Q> extends BaseAdapter {public Context context;public List<T> list;//public Q view;       // 这里不一定是ListView,比如GridView,CustomListViewpublic MyBaseAdapter(Context context, List<T> list, Q view) {this.context = context;this.list = list;this.view = view;}public MyBaseAdapter(Context context, List<T> list) {this.context = context;this.list = list;}@Overridepublic int getCount() {return list.size();}@Overridepublic Object getItem(int position) {return list.get(position);}@Overridepublic long getItemId(int position) {return position;}}
3》 数据缓存
 把下载的数据缓存,这样当没网的时候打开也不是一片空白,提高用户体验。把缓存定义成一个工具类:

public class SharePrefUtil {           private static SharedPreferences sp;           private final static String SP_NAME = "config";           public static void saveString(Context context, String key, String value) {if (sp == null)sp = context.getSharedPreferences(SP_NAME, 0);sp.edit().putString(key, value).commit();}public static void clear(Context context){if (sp == null)sp = context.getSharedPreferences(SP_NAME, 0);sp.edit().clear().commit();}public static String getString(Context context, String key, String defValue) {if (sp == null)sp = context.getSharedPreferences(SP_NAME, 0);return sp.getString(key, defValue);}}
然后 在 processData() 中存入:SharePrefUtil.saveString(ct, HMApi.NEWS_CENTER_CATEGORIES, info.result);在 initData() 中取出来:String result = SharePrefUtil.getString(ct,HMApi.NEWS_CENTER_CATEGORIES, "");缓存的机制,---,开发的过程中,必须先从本地去找数据;若本地没有  再通过去跟服务器交互,从服务器取数据。如果sp 中缓冲的数据太多怎么办?由于 我们的缓存只是为了不显示白屏,改善用户体验,所以只保存第一页的数据。如果缓存太多数据,加载起来就变慢了,不实用。

4》 每点一次“新闻中心”就去取一次数据,这样肯定不好,那怎么让它不老去请求呢?

第一次进来肯定要请求一次,我们就打个标记,请求了就改变标记,第二次点击就不请求了。那在哪打标记呢?先理一下思路,在HomeFragment中点击新闻RadioButton,触发OnCheckedChangeListener(),就会跳到 NewsCenterPage。 在 HomeFragment 的 viewPager.setOnPageChangeListener() 中设置了page.initData(); 只要页面一改变,就会去取数据。所以这个标记要在 HomeFragment 中:public flag=false;if (!flag) {page.initData();}在 NewsCenterPage 的 processData() 方法中,改变标记:if (categories.retcode == 200) {flag=true;  ....}5》 现在框架已经完成了,就要去填充ViewPager 中的 ViewPager 的内容了。进入到“新闻中心”,滑动菜单中的内容就初始为“新闻中心”的滑动菜单,滑动菜单中每个Item 都对应一个Fragment.对应一个page 点击Item 进入不同的内容页.所以我们定义了一些page:
private ArrayList<BasePage> pageList;pageList.clear();BasePage newsPage = new NewsPage(ct, newsCategory);BasePage topicPage = new TopicPage(ct, categorieList.get(1));BasePage picPage = new PicPage(ct, categorieList.get(2));pageList.add(newsPage);pageList.add(topicPage);pageList.add(picPage);switchFragment(MenuFragment.newsCenterPosition); //点击时,选择执行哪一个Fragment
现在在 NewsCenterPage 中,看一下它的布局 news_center_frame.xml:
<?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"    android:background="@color/white"    android:orientation="vertical" >    <include        android:id="@+id/title_bar"        layout="@layout/layout_title_bar" />    <FrameLayout        android:layout_below="@id/title_bar"        android:id="@+id/news_center_fl"        android:layout_width="match_parent"        android:layout_height="match_parent" /></RelativeLayout>
上面是一个 title_bar , 下面是一个 FrameLayout. 这样点击滑动菜单,也把 news_center_fl  清空,再 add 进去:
public void switchFragment(int newsCenterPosition) {BasePage page = pageList.get(newsCenterPosition);switch (newsCenterPosition) {case 0:news_center_fl.removeAllViews();news_center_fl.addView(page.getContentView());break;case 1:news_center_fl.removeAllViews();news_center_fl.addView(page.getContentView());break;case 2:news_center_fl.removeAllViews();news_center_fl.addView(page.getContentView());break;case 3:news_center_fl.removeAllViews();news_center_fl.addView(page.getContentView());break;case 4:news_center_fl.removeAllViews();news_center_fl.addView(page.getContentView());break;}page.initData();}
假如现在点的“新闻”,就会进入 NewsPage ,就会先执行NewsPage 的 initView(布局中加入了一个 ViewPager),再执行
public void initData() {
initIndicator();
}
在这里执行了 initIndicator(); ---是 初始化“指针”的功能。他是一个开源项目--Android-ViewPagerIndicator。因为这个项目特别复杂,有很多样式。所以老师帮我们把新闻样式抽取出来了,封装到 pagerindicator 包下,只需要把整个包和资源文件拷进去就能用了。
怎么用呢?在布局中加入这个就可以了:
   <com.qianlong.android.view.pagerindicator.TabPageIndicator            android:id="@+id/indicator"            style="@style/Theme.PageIndicatorDefaults"            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_weight="1"            android:paddingBottom="2dp" />
还有一个下拉刷新、滚动加载也用得特别多,也是一个开源项目 --- PullToRefresh,老师也帮我们封装到 pullrefreshview 包下。
private void initIndicator() {pages.clear();for(ChildNewsCate cate: category.children){pages.add(new ItemNewsPage(ct, cate.url));}adapter = new NewsPagerAdapter(ct,pages); //为ViewPager 适配pager.removeAllViews();pager.setAdapter(adapter);indicator.setOnPageChangeListener(new OnPageChangeListener() {@Overridepublic void onPageSelected(int arg0) {if(arg0==0){ //第一页才能滑动滑动菜单sm.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);}else{sm.setTouchModeAbove(SlidingMenu.TOUCHMODE_NONE);}ItemNewsPage page = pages.get(arg0);//每个page对应不同的urlif(!page.isLoadSuccess){page.initData();}curIndex = arg0;}@Overridepublic void onPageScrolled(int arg0, float arg1, int arg2) {}@Overridepublic void onPageScrollStateChanged(int arg0) {}});pages.get(0).initData();indicator.setViewPager(pager);indicator.setCurrentItem(curIndex);isLoadSuccess = true;}
ItemNewsPage 就是点进一个新闻的详细页。



0 0
原创粉丝点击