本帖最后由 小鲁哥哥 于 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) 实现步骤第一步:设置轮播图的文字显示
第二步:给轮播图设置滑动监听
第三步:页面被选中监听
|