这段时间公司没有什么事情做,又不想荒废大好时光,所以琢磨着学点东西。博客上有好多讲解RecyclerView的,跟着学了很多基础知识,但是又觉得掌握的不是太熟练,所以想着做些东西。关于今日头条学习的文章不在少数,不过我主要是想学习其中实现的功能,所以还是自己动手,丰衣足食。
首先要实现的是滑动的标题栏,本文使用RecyclerView来实现。
不知道为什么我的V7包中没有RecyclerView,所以在网上下载的jar包。
实现的效果如下(不知道如何上传录屏视频只能截图了 ):
目前的布局文件为layout_main.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.xuhui.mynews.MainActivity" >
<RelativeLayout
android:id="@+id/id_title_lay"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/color_bg_title"
android:gravity="center_vertical"
android:layout_alignParentTop="true"
>
<android.support.v7.widget.RecyclerView
android:id="@+id/id_recyclerview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toLeftOf="@+id/id_add_cate"
/>
<TextView
android:id="@+id/id_add_cate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/title_add_channel_selector"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
/>
</RelativeLayout>
<android.support.v4.view.ViewPager
android:id="@+id/id_news_pager"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_below="@+id/id_title_lay"
/>
</RelativeLayout>
ViewPager用于点击标题时显示对应的界面。
在对应的MainActivity中,由于要用到ViewPager+Fragment,所以Activity需要继承FragmentActivity:
public class MainActivity extends FragmentActivity implements OnPageChangeListener, OnClickListener {
private RecyclerView recyclerView;
private List<Channel> titleList=new ArrayList<Channel>();
private TitleAdapter channelAdapter=null;
private ViewPager pager;
private List<NewsFragment> fragmentList=new ArrayList<NewsFragment>();
private LinearLayout addChannelBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView=(RecyclerView) findViewById(R.id.id_recyclerview);
pager=(ViewPager) findViewById(R.id.id_news_pager);
MyLayoutManager layoutManager=new MyLayoutManager(this);
layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setHasFixedSize(true);//设置RecyclerView大小固定,可提高性能
initData();//初始化标题栏与ViewPager的数据
NewsAdapter newsAdapter=new NewsAdapter(getSupportFragmentManager(), fragmentList);
pager.setAdapter(newsAdapter);
pager.setOnPageChangeListener(this);
channelAdapter=new TitleAdapter(this, titleList);
recyclerView.setAdapter(channelAdapter);
channelAdapter.setItemClickListener(new OnRecyclerViewItemClickListener() {
//RecyclerView的点击事件,点击item项时选中对应的ViewPager页
@Override
public void onRecyclerViewItemClick(View view, Channel data,int position) {
TextView text=(TextView) view.findViewById(R.id.id_title);
pager.setCurrentItem(position,false);
}
});
}
private void initData(){//初始化标题的名称
titleList.add(new Channel("1", "推荐"));
titleList.add(new Channel("2", "社会"));
titleList.add(new Channel("3", "苏州"));
titleList.add(new Channel("4", "娱乐"));
titleList.add(new Channel("5", "视频"));
titleList.add(new Channel("6", "财经"));
titleList.add(new Channel("7", "科技"));
titleList.add(new Channel("8", "搞笑"));
titleList.add(new Channel("9", "军事"));
titleList.add(new Channel("10", "汽车"));
for(int i=0;i<titleList.size();i++){//主要用来测试,所以Fragment用的是同一个
NewsFragment fragment=new NewsFragment();
Bundle args=new Bundle();
args.putString("text", titleList.get(i).getName());
fragment.setArguments(args);//为fragment设置参数,在Fragment界面中获取
fragmentList.add(fragment);
}
}
@Override
public void onPageScrollStateChanged(int arg0) {
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
@Override
public void onPageSelected(int arg0) {
recyclerView.scrollToPosition(arg0);//滑动ViewPager时滑动RecyclerView到对应的item项
Iterator<Map.Entry<Integer, View>> iterator=channelAdapter.viewMap.entrySet().iterator();
while(iterator.hasNext()){//遍历已加载的item项,将其设置为未选中的状态
Map.Entry<Integer, View> entry=iterator.next();
View text=entry.getValue();
text.setSelected(false);
}
channelAdapter.selectTab(arg0);//选中RecyclerView对应的item项
}
注意:RecyclerView高度设置为wrapcontent时,仍占据整个屏幕,解决方案:重写其对应的LinearLayoutManager的onMeasure方法
如下:
public class MyLayoutManager extends LinearLayoutManager {
public MyLayoutManager(Context context) {
super(context);
}
@Override
public void onMeasure(Recycler recycler, State state, int widthSpec,
int heightSpec) {
View view = recycler.getViewForPosition(0);
if(view != null){
measureChild(view, widthSpec, heightSpec);
int measuredWidth = MeasureSpec.getSize(widthSpec);
int measuredHeight = view.getMeasuredHeight();
setMeasuredDimension(measuredWidth, measuredHeight);
}
}
}
(1)关于RecyclerView的使用,
使用RecyclerView,其对应的Adapter必须要继承RecyclerView.Adapter
public class TitleAdapter extends RecyclerView.Adapter<TitleAdapter.ViewHolder>{
private List<Channel> titleList;
private LayoutInflater inflater;
private OnRecyclerViewItemClickListener itemClickListner;
private int selectedId=0;
public Map<Integer,View> viewMap=new HashMap<Integer,View>();
public TitleAdapter(Context context,List<Channel> titleList){
inflater=LayoutInflater.from(context);
this.titleList=titleList;
}
//自定义点击Item项时的监听器,并在Activity中实现
public interface OnRecyclerViewItemClickListener{
void onRecyclerViewItemClick(View view,Channel data,int position);
}
public void setItemClickListener(OnRecyclerViewItemClickListener itemClickListner){
this.itemClickListner=itemClickListner;
}
//设置当前选择的item项
public void selectTab(int id){
this.selectedId=id;
notifyDataSetChanged();
}
@Override
public int getItemCount() {
return titleList==null?0:titleList.size();
}
//创建新的View
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int arg1) {
View view=inflater.inflate(R.layout.layout_title_item, null);
ViewHolder holder=new ViewHolder(view);
// view.setOnClickListener(new MyClickListener(arg1));
return holder;
}
//View创建成功后,将数据与View进行绑定
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.title.setText(titleList.get(position).getName());
holder.itemView.setTag(titleList.get(position));
holder.itemView.setOnClickListener(new MyClickListener(position));
viewMap.put(position, holder.itemView);
if(selectedId==position){
viewMap.get(position).setSelected(true);
}
}
public void addItem(Channel data,int position){
titleList.add(position, data);
notifyItemInserted(position);
}
public void delItem(Channel data){
int index=titleList.indexOf(data);
titleList.remove(index);
notifyItemRemoved(index);
}
//自定义holder,需继承RecyclerView默认的ViewHolder类
public class ViewHolder extends RecyclerView.ViewHolder{
public TextView title;
public ViewHolder(View view) {
super(view);
title=(TextView) view.findViewById(R.id.id_title);
}
}
private class MyClickListener implements OnClickListener{
private int position;
public MyClickListener(int position){
this.position=position;
}
@Override
public void onClick(View v) {
if(itemClickListner!=null){
itemClickListner.onRecyclerViewItemClick(v, (Channel)v.getTag(),position);
}
}
}
}
(2)由于ViewPager是与Fragment一起使用的,所以其Adapter继承FragmentPagerAdapter 类:
public class NewsAdapter extends FragmentPagerAdapter {
//ViewPager对应的Fragment列表
private List<NewsFragment> fragmentList;
public NewsAdapter(FragmentManager fm,List<NewsFragment> fragmentList) {
super(fm);
this.fragmentList=fragmentList;
}
@Override
public Fragment getItem(int arg0) {
return fragmentList.get(arg0);
}
@Override
public int getCount() {
return fragmentList==null?0:fragmentList.size();
}
}