A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 小鲁哥哥 于 2017-5-14 19:57 编辑

【济南中心】Android课程同步笔记智慧北京:Day03(上)

RecyclerView基本使用
第一步:布局中引入RecyclerView
[XML] 纯文本查看 复制代码
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.itheima.test_recyclerview.MainActivity">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/rv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"></android.support.v7.widget.RecyclerView>
</RelativeLayout>

第二步:初始化RecycleView
[Java] 纯文本查看 复制代码
public class MainActivity extends AppCompatActivity {
    private Handler mHandler = new Handler();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        RecyclerView rv = (RecyclerView) findViewById(R.id.rv);
    }

    }

第三步:创建布局管理器
创建布局管理器,并指定是线性,网格,瀑布流形式的
[Java] 纯文本查看 复制代码
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        RecyclerView rv = (RecyclerView) findViewById(R.id.rv);
        //RecyclerView相关联的类:布局管理器(XXXLayoutManger 设置RecyclerView的显示风格:列表、网格瀑布流)、适配器(Adapter)、ViewHolder
        //1 设置布局管理器
        //LinearLayoutManager 线性布局管理器 方向:默认是垂直方向
        LinearLayoutManager lm = new LinearLayoutManager(this);
        lm.setOrientation(LinearLayoutManager.VERTICAL);
        rv.setLayoutManager(lm);

        //网格
//        GridLayoutManager lm = new GridLayoutManager(this,2);
//        lm.setOrientation(GridLayoutManager.HORIZONTAL);
//        rv.setLayoutManager(lm);

        //瀑布流
//        StaggeredGridLayoutManager  lm = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
//        rv.setLayoutManager(lm);

        //2 设置适配器
        rv.setAdapter(new MyAdapter());

    }
第四步创建适配器
[Java] 纯文本查看 复制代码
private class MyAdapter extends RecyclerView.Adapter{

    //创建ViewHolder
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(getApplicationContext()).inflate(item,parent,false);
        return new MyViewHolder(view);
    }

    //对ViewHolder里面的控件进行赋值
    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        MyViewHolder viewHolder = (MyViewHolder) holder;
        viewHolder.setData(position);
    }

    //条目的数量
    @Override
    public int getItemCount() {
        return 60;
    }
}

private class MyViewHolder extends RecyclerView.ViewHolder{
    TextView tv;

    public MyViewHolder(View itemView) {
        super(itemView);
        tv = (TextView) itemView.findViewById(R.id.tv);
    }

    public void setData(final int position) {
        tv.setText("第"+position+"条目的位置");

        //设置条目点击事件
        itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(MainActivity.this, "点击了"+position, Toast.LENGTH_SHORT).show();
            }
        });
    }
}
第五步:给RecyclerView设置适配器
[Java] 纯文本查看 复制代码
rv.setAdapter(new MyAdapter())

创建侧滑菜单的RecyclerView和MenuAdapter
效果图分析:
实现步骤[size=21.3333px]:
第一步:初始化左侧菜单布局
[XML] 纯文本查看 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:background="#000"
              android:orientation="vertical">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv_menu"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="100dp"></android.support.v7.widget.RecyclerView>
</LinearLayout>

第二步:初始化recycleView
MainActivity.java】文件中,添加初始化Menu的RecyclerView
第三步:创建recycleView的适配器
用于初始化view和绑定数据,创建布局文件【item_menu.xml】,动态显示数据
创建Adapter:
[Java] 纯文本查看 复制代码
public class MenuAdapter extends RecyclerView.Adapter {

    private Context context;
    private List<NewsCenterBean.NewsCenterMenuBean> newsCenterMenuBeanList;

    //默认选中的条目下标
    private int selectedPosition;

    public void setNewsCenterMenuBeanList(List<NewsCenterBean.NewsCenterMenuBean> newsCenterMenuBeanList) {
        this.newsCenterMenuBeanList = newsCenterMenuBeanList;
        //刷新显示
        notifyDataSetChanged();
    }

    public MenuAdapter(Context context, List<NewsCenterBean.NewsCenterMenuBean> newsCenterMenuBeanList) {
        this.context = context;
        this.newsCenterMenuBeanList = newsCenterMenuBeanList;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(context).inflate(R.layout.item_menu, parent, false);
        ViewHolder viewHolder = new ViewHolder(view);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
        final NewsCenterBean.NewsCenterMenuBean newsCenterMenuBean = newsCenterMenuBeanList.get(position);
        ViewHolder viewHolder = (ViewHolder) holder;
        viewHolder.tvMenuTitle.setText(newsCenterMenuBean.title);
    }

    @Override
    public int getItemCount() {
        return newsCenterMenuBeanList != null ? newsCenterMenuBeanList.size() : 0;
    }

    static class ViewHolder extends RecyclerView.ViewHolder{
        @BindView(R.id.iv_arrow)
        ImageView ivArrow;
        @BindView(R.id.tv_menu_title)
        TextView tvMenuTitle;

        ViewHolder(View view) {
            super(view);
            ButterKnife.bind(this, view);
        }
    }
}
第五步:绑定RecycleView:

[Java] 纯文本查看 复制代码
menuAdapter=new MenuAdapter(this,null);
rvMenu.setAdapter(menuAdapter);

侧滑菜单条目点击效果分析:

实现步骤
第一步:首先给RecyclerView的每个条目添加点击事件
[Java] 纯文本查看 复制代码
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {

    ViewHolder viewHolder = (ViewHolder) holder;

    //选中


    //处理条目点击事件
    viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
        //条目点击事件
        @Override
        public void onClick(View v) {
            //判断是否点击的同一个条目,不是刷新界面
            if(selectedPosition != position){
                selectedPosition = position;
                //刷新界面
                notifyDataSetChanged();
            }
    });
}
注意这里通过selectedPosition记录了点击item的索引这样就可以防止用户
多次点击同一个条目多次刷新的效果
第二步:根据selectedPosition当前是否被选中处理条目样式
[Java] 纯文本查看 复制代码
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
    final NewsCenterBean.NewsCenterMenuBean newsCenterMenuBean = newsCenterMenuBeanList.get(position);
    ViewHolder viewHolder = (ViewHolder) holder;
    viewHolder.tvMenuTitle.setText(newsCenterMenuBean.title);

    //选中
    if(selectedPosition == position){
        viewHolder.ivArrow.setImageResource(R.drawable.menu_arr_select);
        viewHolder.tvMenuTitle.setTextColor(Color.RED);
    }else{//未选中
        viewHolder.ivArrow.setImageResource(R.drawable.menu_arr_normal);
        viewHolder.tvMenuTitle.setTextColor(Color.WHITE);
    }

    //处理条目点击事件
    viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
        //条目点击事件
        @Override
        public void onClick(View v) {
            //判断是否点击的同一个条目,不是刷新界面
            if(selectedPosition != position){
                selectedPosition = position;
                //刷新界面
                notifyDataSetChanged();

        }
    });
}
点击侧滑菜单条目修改tab页面的标题
效果分析:
通过视图分析
第一步:在【MainActivity.java】中创建获取被选中的Fragment的方法
第二步:在MenuApdater获取选中的Fragment
[Java] 纯文本查看 复制代码
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
    final NewsCenterBean.NewsCenterMenuBean newsCenterMenuBean = newsCenterMenuBeanList.get(position);
    ViewHolder viewHolder = (ViewHolder) holder;
    viewHolder.tvMenuTitle.setText(newsCenterMenuBean.title);

    //选中
    if(selectedPosition == position){
        viewHolder.ivArrow.setImageResource(R.drawable.menu_arr_select);
        viewHolder.tvMenuTitle.setTextColor(Color.RED);
    }else{//未选中
        viewHolder.ivArrow.setImageResource(R.drawable.menu_arr_normal);
        viewHolder.tvMenuTitle.setTextColor(Color.WHITE);
    }

    //处理条目点击事件
    viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
        //条目点击事件
        @Override
        public void onClick(View v) {
            //判断是否点击的同一个条目,不是刷新界面
            if(selectedPosition != position){
                selectedPosition = position;
                //刷新界面
                notifyDataSetChanged();
                //修改对应tab页面的标题
                BaseFragment baseFragment = ((MainActivity)context).getCurrentTabFragment();
                baseFragment.setTitle(newsCenterMenuBean.title);
            }

            //关闭侧滑菜单
            ((MainActivity)context).slidingMenu.toggle();
        }
    });
}
第三步:修改选中的Fragment中的标题内容
[HTML] 纯文本查看 复制代码
  //修改对应tab页面的标题
                BaseFragment baseFragment = ((MainActivity)context).getCurrentTabFragment();
                baseFragment.setTitle(newsCenterMenuBean.title);
            }
点击侧滑菜单关闭tab页面
实现步骤
第一步:关闭侧滑菜单
[Java] 纯文本查看 复制代码
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
    final NewsCenterBean.NewsCenterMenuBean newsCenterMenuBean = newsCenterMenuBeanList.get(position);
    ViewHolder viewHolder = (ViewHolder) holder;
    viewHolder.tvMenuTitle.setText(newsCenterMenuBean.title);

    //选中
    if(selectedPosition == position){
        viewHolder.ivArrow.setImageResource(R.drawable.menu_arr_select);
        viewHolder.tvMenuTitle.setTextColor(Color.RED);
    }else{//未选中
        viewHolder.ivArrow.setImageResource(R.drawable.menu_arr_normal);
        viewHolder.tvMenuTitle.setTextColor(Color.WHITE);
    }

    //处理条目点击事件
    viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
        //条目点击事件
        @Override
        public void onClick(View v) {
            //判断是否点击的同一个条目,不是刷新界面
            if(selectedPosition != position){
                selectedPosition = position;
                //刷新界面
                notifyDataSetChanged();
                //修改对应tab页面的标题
                BaseFragment baseFragment = ((MainActivity)context).getCurrentTabFragment();
                baseFragment.setTitle(newsCenterMenuBean.title);
            }

            //关闭侧滑菜单
            ((MainActivity)context).slidingMenu.toggle();
        }
    });
}
加载新闻中心的内容页面
其实包含两部内容:
上部分:ViewPagerIndicator + ImageButton
下部分:ViewPager
实现步骤
界面分析:
首先在NewsCenterFragment获取数据的processData方法中,
初始化界面并将添加到FremenLayout中。
第一步:创建布局文件
[Java] 纯文本查看 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <com.viewpagerindicator.TabPageIndicator
            android:id="@+id/tabPagerIndicator"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"></com.viewpagerindicator.TabPageIndicator>

        <ImageButton
            android:id="@+id/ib_next"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:background="#fff"
            android:padding="5dp"
            android:src="@drawable/news_cate_arr"/>
    </RelativeLayout>

    <android.support.v4.view.ViewPager
        android:id="@+id/vp_newscenter_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></android.support.v4.view.ViewPager>

</LinearLayout>
第二步:加载布局并添加到容器中
[Java] 纯文本查看 复制代码
public View createContent() {
    View view = LayoutInflater.from(getContext()).inflate(
            R.layout.newscenter_content,(ViewGroup) getView(),
            false);
    return view;
}[/align]@Override
    public void loadNetData() {
        final String url = Constant.NEWSCENTER_URL;
        OkHttpUtils.get()
                .url(url)
                .build()
                .execute(new StringCallback() {
                    @Override
                    public void onError(Call call, Exception e, int id) {
                        MyToast.show(getActivity(), "获取新闻中心数据失败");
                    }
                    @Override
                    public void onResponse(String response, int id) {
                        MyLogger.i(TAG,response);
                        //把response  == json 转换成对应的数据模型
                        processData(response);
                    }
                });
    }

    //把Json格式的字符串转换成对应的模型对象
    public void processData(String json){
        Gson gson = new Gson();
        newsCenterBean = gson.fromJson(json, NewsCenterBean.class);
        //把数据传递给MainActivity
        ((MainActivity)getActivity()).setNewsCenterMenuBeanList(newsCenterBean.data);

        //创建布局
        View view = createContent();
        //加载布局
        addView(view);
    }
[align=left]}
初始化新闻中心ViewPager
在显示视图到到新闻中心界面时并没有成功而是出现的错误
出现错误的原因
TabViewPagerIndicator的使用必须要结合ViewPager
因此这里报异常为
接下来我们初始化新闻中心的ViewPager并和TabViewPagerIndicator进行联合使用
图示分析
第一步:初始化控件

第二步:初始化Viewpager
[Java] 纯文本查看 复制代码
public class NewsCenterTabVPAdapter extends PagerAdapter {
    private List<View> views;
    private List<NewsCenterBean.NewsCenterNewsTabBean> tabBeanList;

    public NewsCenterTabVPAdapter(List<View> views,List<NewsCenterBean.NewsCenterNewsTabBean> tabBeanList) {
        this.views = views;
        this.tabBeanList = tabBeanList;
    }

    @Override
    public int getCount() {
        return views != null?views.size():0;
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == object;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        View view = views.get(position);
        container.addView(view);
        return view;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView((View) object);
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return tabBeanList.get(position).title;
    }
}

在【NewsCenterFragment.java】文件中的initViewPage方法中 给ViewPager设置Adapter
第三步:TabPagerIndicator和ViewPager进行联合
第四步:配置TabPagerIndicator主题样式:
初始化TabPagerIndicator控件时,需要使用TabPagerIndicator的主题样式,因此这里我们打开清单文件找到MainActivity,添加主题

修改TabPagerIndicatorLibrary里面的样式
第一步:分析
TabPageIndicator 的效果是由这个主题来控制的
android:theme="@style/Theme.PageIndicatorDefaults“
因此,需要修改开源框架的主题
修改内容:
背景样式
文字的颜色
tab选择的图片状态选择器
第二步:修改背景样式
打开主题PageIndicatorDefaults文件查看:
背景样式修改:打开vpi_tab_indicator文件进行修改
选中状态为红色默认状态为白色
由于默认的背景样式是白色的。因此定义白色图片:打开【white_bg.xml】修改颜色为白色
被选中之后带有红色下划线的图片drawble目下添加以下图片
然后对vpi_tab_indicator文件进行修改
[XML] 纯文本查看 复制代码
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- Non focused states 默认状态: 白色, 选中状态:红色-->
    <item android:state_focused="false" android:state_selected="false" android:state_pressed="false" android:drawable="@drawable/white_bg" />
    <item android:state_focused="false" android:state_selected="true"  android:state_pressed="false" android:drawable="@drawable/news_tab_item_bg_select" />

    <!-- Focused states 获取焦点状态-->
    <item android:state_focused="true" android:state_selected="false" android:state_pressed="false" android:drawable="@drawable/news_tab_item_bg_select" />
    <item android:state_focused="true" android:state_selected="true"  android:state_pressed="false" android:drawable="@drawable/news_tab_item_bg_select" />

    <!-- Pressed 按下状态-->
    <!--    Non focused states -->
    <item android:state_focused="false" android:state_selected="false" android:state_pressed="true" android:drawable="@drawable/news_tab_item_bg_select" />
    <item android:state_focused="false" android:state_selected="true"  android:state_pressed="true" android:drawable="@drawable/news_tab_item_bg_select" />

    <!--    Focused states -->
    <item android:state_focused="true" android:state_selected="false" android:state_pressed="true" android:drawable="@drawable/news_tab_item_bg_select" />
    <item android:state_focused="true" android:state_selected="true"  android:state_pressed="true" android:drawable="@drawable/news_tab_item_bg_select" />
</selector>
第二步:文字样式的修改
找到TextAppearance.TabPageIndicator主题,打开,如果图所示:
打开上面标注的vpi_dark_theme文件对文字样式进行修改

点击按钮切换到一下个页面

第一步:给按钮添加点击事件
[Java] 纯文本查看 复制代码
 //点击箭头,切换到下一页
    ibNext.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            //获取ViewPager当前显示页面的下标
            int currentItem = vpNewsCenterContent.getCurrentItem();

            if(currentItem != newsCenterBean.data.get(0).children.size() - 1){
                vpNewsCenterContent.setCurrentItem(currentItem+1);
            }


        }
    });
新闻中心子tab页面数据加载

接下来的操作,就是下图中标注绿色部分的界面了,也就是处理新闻中心子tab页面NewsCenterContentTabPager页面。

实现步骤
第一步:加载数据
NewsCenterTabVPAdapter的instantiateItem方法中,调用NewsCenterContentTabPager中的loadNetData方法
第二步:获取数据
在NewsCenterContentTabPager中的loadNetData方法中请求数据:

把新闻中心子tab加载的json数据转换成对应的模型
第一步:数据格式
第二步:定义数据模型
[Java] 纯文本查看 复制代码
/**
 * Created by Apple on 2016/9/27.
 * 新闻中心子tab的数据模型
 */
public class NewsCenterTabBean {
    public NewsCenterDataBean data;
    public int retcode;

    public class NewsCenterDataBean {
        public String countcommenturl;
        public String more;
        public List<NewsBean> news;
        public String title;
        public List<TopicBean> topic;
        public List<TopNewsBean> topnews;
    }

    //轮播图
    public class TopNewsBean{
        public boolean comment;
        public String commentlist;
        public String commenturl;
        public String  id;
        public String pubdate;
        public String title;
        public String topimage;
        public String type;
        public String url;
    }

    public class TopicBean{
        public String description;
        public String id;
        public String listimage;
        public String sort;
        public String title;
        public String url;
    }

    //新闻列表数据模型
    public class NewsBean{
        public String comment;
        public String commentlist;
        public String commenturl;
        public String id;
        public String listimage;
        public String pubdate;
        public String title;
        public String type;
        public String url;
    }
}
第三步:解析数据

加载轮播图的图片
实现步骤
第一步:加载轮播图
在【NewsCenterContentTabPager】文件中 processData方法中,添加 bindDataToView方法,进行初始化轮播图

轮播图文字的改变

实现这样的效果,需要给ViewPager添加滑动监听。
[Java] 纯文本查看 复制代码
addOnPageChangeListener(this)
        onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
onPageSelected(int position) 
onPageScrollStateChanged(int state)
实现步骤第一步:设置轮播图的文字显示

第二步:给轮播图设置滑动监听

第三步:页面被选中监听

        



1 个回复

倒序浏览
多谢分享
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马