本文实例实现一个仿网易新闻的页面,上面是轮播的图片,下面是 RecyclerView 显示新闻列表,具体内容如下
错误方法
<?xml version=\"1.0\" encoding=\"utf-8\"?> <LinearLayout ...> <ViewPager ... /> <android.support.v7.widget.RecyclerView .../> </LinearLayout>
这样布局 ViewPager 在 RecyclerView 的上面,如果不做特殊处理,当下滑 RecyclerView 加载更多内容的时候,ViewPager会固定不动。
正确的效果是下滑加载更多的时候,ViewPager 会滑出页面,释放空间供其他内容展示。
一、解决思路
方法有两种
总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:orientation=\"vertical\"> <android.support.v7.widget.RecyclerView android:id=\"@+id/rcv_article_latest\" android:layout_width=\"match_parent\" android:layout_height=\"0dp\" android:layout_weight=\"1\" /> </LinearLayout>
很简单,一个RecyclerView就行了
头部 ViewPager 的viewholder_article_header.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:orientation=\"vertical\"> <!--ViewPager 热门文章图片展示--> <FrameLayout android:layout_width=\"match_parent\" android:layout_height=\"200dp\" android:background=\"@color/gray_light\"> <android.support.v4.view.ViewPager android:id=\"@+id/vp_hottest\" android:layout_width=\"match_parent\" android:layout_height=\"match_parent\" android:background=\"@color/colorPrimary\" /> <LinearLayout android:id=\"@+id/ll_hottest_indicator\" android:layout_width=\"wrap_content\" android:layout_height=\"20dp\" android:layout_gravity=\"bottom|right\" android:layout_marginBottom=\"5dp\" android:layout_marginRight=\"10dp\" android:layout_marginTop=\"5dp\" android:gravity=\"center\" android:orientation=\"horizontal\" /> </FrameLayout> </LinearLayout>
FrameLayout里面的ViewPager和LinearLayout是覆盖显示的,实现在图片的下方有个小圆点标记滑动到了第一张图片。
新闻项 viewholder_article_item.xml 布局
<android.support.v7.widget.CardView
xmlns:android=\"http://schemas.android.com/apk/res/android\"
xmlns:app=\"http://schemas.android.com/apk/res-auto\"
xmlns:fresco=\"http://schemas.android.com/apk/res-auto\"
android:id=\"@+id/cv_item\"
android:layout_width=\"match_parent\"
android:layout_height=\"wrap_content\"
app:cardCornerRadius=\"5dp\"
app:cardElevation=\"5dp\"
app:contentPadding=\"2dp\">
<LinearLayout
android:layout_width=\"match_parent\"
android:layout_height=\"wrap_content\"
android:orientation=\"horizontal\">
<com.facebook.drawee.view.SimpleDraweeView
android:id=\"@+id/rcv_article_photo\"
android:layout_width=\"100dp\"
android:layout_height=\"100dp\"
fresco:actualImageScaleType=\"centerInside\"
fresco:roundAsCircle=\"true\"
fresco:roundingBorderColor=\"@color/lightslategray\"
fresco:roundingBorderWidth=\"1dp\" />
<LinearLayout
android:layout_width=\"0dp\"
android:layout_height=\"match_parent\"
android:layout_weight=\"1\"
android:orientation=\"vertical\">
<TextView
android:id=\"@+id/rcv_article_title\"
android:layout_width=\"wrap_content\"
android:layout_height=\"wrap_content\"
android:layout_marginLeft=\"10dp\"
android:layout_marginTop=\"2dp\"
android:gravity=\"center\"
android:text=\"关于举办《经典音乐作品欣赏与人文审美》讲座的通知\"
android:textColor=\"@color/primary_text\" />
<!-- 新闻 发布时间 来源 阅读次数-->
<LinearLayout
android:layout_width=\"match_parent\"
android:layout_height=\"wrap_content\"
android:layout_marginTop=\"5dp\"
android:gravity=\"center\"
android:orientation=\"horizontal\">
<TextView
android:id=\"@+id/rcv_article_date\"
android:layout_width=\"wrap_content\"
android:layout_height=\"wrap_content\"
android:layout_marginLeft=\"10dp\"
android:layout_marginRight=\"2dp\"
android:text=\"2015-01-09\" />
<TextView
android:id=\"@+id/rcv_article_source\"
android:layout_width=\"wrap_content\"
android:layout_height=\"wrap_content\"
android:layout_marginLeft=\"2dp\"
android:layout_marginRight=\"2dp\"
android:text=\"科学研究院\" />
<TextView
android:id=\"@+id/rcv_article_readtimes\"
android:layout_width=\"wrap_content\"
android:layout_height=\"wrap_content\"
android:layout_marginLeft=\"2dp\"
android:layout_marginRight=\"2dp\"
android:text=\"1129次\" />
</LinearLayout>
<TextView
android:id=\"@+id/rcv_article_preview\"
android:layout_width=\"wrap_content\"
android:layout_height=\"0dp\"
android:layout_weight=\"1\"
android:layout_marginLeft=\"10dp\"
android:layout_marginTop=\"5dp\"
android:ellipsize=\"end\"
android:maxLines=\"2\"
android:text=\"讲座主要内容:以中、西方音乐历史中经典音乐作品为基础,通过作曲家及作品创作背景、相关音乐文化史知识及音乐欣赏常识...\" />
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
这篇文章 Android Material Design学习之RecyclerView代替 ListView sscc实现了不加 ViewPager,利用 RecyclerView 展示新闻列表的功能。
RecyclerView 的适配器
/**
* 新闻列表的适配器
* 01-14 头部是 ViewPager,下面是列表新闻
* Created by tomchen on 1/11/16.
*/
public class ArticleAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int TYPE_HEADER = 0;
private static final int TYPE_ITEM = 1;
//头部固定为 张图片
private static final int NUM_IMAGE = 4;
//Handler 用到的参数值
private static final int UPTATE_VIEWPAGER = 0;
//新闻列表
private List<ItemArticle> articleList;
//设置当前 第几个图片 被选中
private int currentIndex = 0;
//context
private Context context;
private LayoutInflater mLayoutInflater;
private ImageView[] mCircleImages;//底部只是当前页面的小圆点
public ArticleAdapter(Context context, List<ItemArticle> articleList) {
this.context = context;
//头部viewpager图片固定是7张,剩下的是列表的数据
this.articleList = articleList;
mLayoutInflater = LayoutInflater.from(context);
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//理论上应该把最可能返回的 TYPE 放在前面
View view = null;
if (viewType == TYPE_ITEM) {
view = mLayoutInflater.inflate(
R.layout.viewholder_article_item, parent, false);
return new ItemArticleViewHolder(view);
}
//头部返回 ViewPager 实现的轮播图片
if (viewType == TYPE_HEADER) {
view = mLayoutInflater.inflate(
R.layout.viewholder_article_header, parent, false);
return new HeaderArticleViewHolder(view);
}
return null;
// //可以抛出异常,没有对应的View类型
// throw new RuntimeException(\"there is no type that matches the type \" + viewType + \" + make sure your using types correctly\");
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof ItemArticleViewHolder) {
//转型
ItemArticleViewHolder newHolder = (ItemArticleViewHolder) holder;
//注意RecyclerView第0项是 ViewPager 占据了0 1 2 3图片
//那么下面的列表展示是 RecyclerView 的第1项,从第4项开始
ItemArticle article = articleList.get(position + NUM_IMAGE - 1);
newHolder.rcvArticlePhoto.setImageURI(Uri.parse(article.getImageUrl()));
newHolder.rcvArticleTitle.setText(article.getTitle());
newHolder.rcvArticleDate.setText(article.getPublishDate());
newHolder.rcvArticleSource.setText(article.getSource());
//注意这个阅读次数是 int 类型,需要转化为 String 类型
newHolder.rcvArticleReadtimes.setText(article.getReadTimes() + \"次\");
newHolder.rcvArticlePreview.setText(article.getPreview());
} else if (holder instanceof HeaderArticleViewHolder) {
HeaderArticleViewHolder newHolder = (HeaderArticleViewHolder) holder;
List<ItemArticle> headers = articleList.subList(0, NUM_IMAGE );
HeaderImageAdapter imageAdapter = new HeaderImageAdapter(context, headers);
setUpViewPager(newHolder.vpHottest, newHolder.llHottestIndicator, headers);
}
}
private void setUpViewPager(final ViewPager vp, LinearLayout llBottom, final List<ItemArticle> headerArticles) {
HeaderImageAdapter imageAdapter = new HeaderImageAdapter(context, headerArticles);
//??这儿有些疑惑,Adapter 里面嵌套设置 Adapter 是否优雅?
vp.setAdapter(imageAdapter);
final Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case UPTATE_VIEWPAGER:
if (msg.arg1 != 0) {
vp.setCurrentItem(msg.arg1);
} else {
//false 当从末页调到首页是,不显示翻页动画效果,
vp.setCurrentItem(msg.arg1, false);
}
break;
}
}
};
//下面是设置动画切换的样式
vp.setPageTransformer(true, new RotateUpTransformer());
//创建底部指示位置的导航栏
final ImageView[] mCircleImages = new ImageView[headerArticles.size()];
for (int i = 0; i < mCircleImages.length; i++) {
ImageView imageView = new ImageView(context);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(10, 10);
params.setMargins(5, 0, 5, 0);
imageView.setLayoutParams(params);
if (i == 0) {
imageView.setBackgroundResource(R.drawable.indicator_select);
} else {
imageView.setBackgroundResource(R.drawable.indicator_not_select);
}
mCircleImages[i] = imageView;
//把指示作用的原点图片加入底部的视图中
llBottom.addView(mCircleImages[i]);
}
vp.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
//图片左右滑动时候,将当前页的圆点图片设为选中状态
@Override
public void onPageSelected(int position) {
// 一定几个图片,几个圆点,但注意是从0开始的
int total = mCircleImages.length;
for (int j = 0; j < total; j++) {
if (j == position) {
mCircleImages[j].setBackgroundResource(R.drawable.indicator_select);
} else {
mCircleImages[j].setBackgroundResource(R.drawable.indicator_not_select);
}
}
//设置全局变量,currentIndex为选中图标的 index
currentIndex = position;
}
@Override
public void onPageScrolled(int i, float v, int i1) {
}
@Override
public void onPageScrollStateChanged(int state) {
//实现切换到末尾后返回到第一张
switch (state) {
// 手势滑动
case ViewPager.SCROLL_STATE_DRAGGING:
break;
// 界面切换中
case ViewPager.SCROLL_STATE_SETTLING:
break;
case ViewPager.SCROLL_STATE_IDLE:// 滑动结束,即切换完毕或者加载完毕
// 当前为最后一张,此时从右向左滑,则切换到第一张
if (vp.getCurrentItem() == vp.getAdapter()
.getCount() - 1) {
vp.setCurrentItem(0, false);
}
// 当前为第一张,此时从左向右滑,则切换到最后一张
else if (vp.getCurrentItem() == 0) {
vp.setCurrentItem(vp.getAdapter()
.getCount() - 1, false);
}
break;
default:
break;
}
}
});
//设置自动轮播图片,5s后执行,周期是5s
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
Message message = new Message();
message.what = UPTATE_VIEWPAGER;
if (currentIndex == headerArticles.size() - 1) {
currentIndex = -1;
}
message.arg1 = currentIndex + 1;
mHandler.sendMessage(message);
}
}, 6000, 6000);
}
@Override
public int getItemCount() {
//因为多了一个头部,所以是+1,但是头部 ViewPager 占了7个
//所以实际是少了6个
return articleList.size() + 1 - NUM_IMAGE;
}
@Override
public int getItemViewType(int position) {
if (position == 0)
return TYPE_HEADER;
else
return TYPE_ITEM;
}
class HeaderArticleViewHolder extends RecyclerView.ViewHolder {
//轮播的最热新闻图片
@InjectView(R.id.vp_hottest)
ViewPager vpHottest;
//轮播图片下面的小圆点
@InjectView(R.id.ll_hottest_indicator)
LinearLayout llHottestIndicator;
//学院广播信息
@InjectView(R.id.tv_college_broadcast)
TextView tvCollegeBroadcast;
public HeaderArticleViewHolder(View itemView) {
super(itemView);
ButterKnife.inject(this, itemView);
}
}
class ItemArticleViewHolder extends RecyclerView.ViewHolder {
@InjectView(R.id.rcv_article_photo)
SimpleDraweeView rcvArticlePhoto;
@InjectView(R.id.rcv_article_title)
TextView rcvArticleTitle;
@InjectView(R.id.rcv_article_date)
TextView rcvArticleDate;
@InjectView(R.id.rcv_article_source)
TextView rcvArticleSource;
@InjectView(R.id.rcv_article_readtimes)
TextView rcvArticleReadtimes;
@InjectView(R.id.rcv_article_preview)
TextView rcvArticlePreview;
public ItemArticleViewHolder(View itemView) {
super(itemView);
ButterKnife.inject(this, itemView);
}
}
}
ItemArticleViewHolder是列表展示的新闻项的 ViewHolder,对应了上面的 viewholder_article_item.xml。
HeaderArticleViewHolder 是头部 ViewPager 的 ViewHolder, 对应viewholder_article_header.xml
Note
二、疑惑及后续计划
除了将 ViewPager 作为 RecyclerView 第一项,还有一张方法就是利用ScrollView,大家可以进行研究。
以上就是本文的全部内容,希望对大家的学习有所帮助。
本文地址:https://www.stayed.cn/item/17214
转载请注明出处。
本站部分内容来源于网络,如侵犯到您的权益,请 联系我