总结一下最近做的一个项目首页,也是众多APP常见的首页效果:自动滚动的头图&ListView展示具体信息,效果大概类似于知乎日报的首页
写了一个简单的demo,没有仔细去设计布局,仅实现了类似的效果,并加上了google提倡的material design的下拉刷新风格,项目用到了以下几个著名的开源库:
1,图片加载库:imageloader
2,头图的小圆点:androidViewPagerIndicatorlibrary
3,下拉刷新控件:ultra-pullToRefreshlistview
【实现】
思路:总布局是一个ptr-listview,头图通过listview的setHeader设置,如果有分页加载,则加载更多的view通过listview的setFooter实现。头图是一个viewpager,自动滚动通过一个无限循环的handler实现。
【核心代码】
-1:主Activity
package com.baozou.headerviewtest;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.util.DisplayMetrics;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ListView;
import android.widget.RelativeLayout;
import com.viewpagerindicator.CirclePageIndicator;
import java.util.ArrayList;
import java.util.List;
import in.srain.cube.views.ptr.PtrFrameLayout;
import in.srain.cube.views.ptr.PtrHandler;
import in.srain.cube.views.ptr.header.MaterialHeader;
public class MainActivity extends AppCompatActivity {
private HeaderPagerAdapter headerPagerAdapter;
private ViewPager viewPager;
List newsList = new ArrayList();
private GestureDetector mTapGestureDetector;
public static final int MSG_PAGER = 0x01;
public static final long TICK = 5000;
private final PagerTimerHandler mPagerTimerHandler = new PagerTimerHandler();
private CirclePageIndicator mTopPageIndicator;
//下拉刷新组件
private PtrFrameLayout mPtrFrameLayout;
private NewsAdapter newsAdapter;
private ListView mListView;
//头部view
private View mHeaderView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ptr_listview);
setNews();
setView();
}
private void setNews() {
for (int i = 0; i < 3; i++) {
News news = new News();
news.setTitle("第" + i + "个");
news.setUrl("http://img5.duitang.com/uploads/blog/201407/17/20140717113117_mUssJ.thumb.jpeg");
newsList.add(news);
}
}
/**
* 初始化下拉刷新相关的
*/
private void initPtrViews() {
// header
final MaterialHeader header = new MaterialHeader(this);
int[] colors = getResources().getIntArray(R.array.google_colors);
header.setColorSchemeColors(colors);
header.setLayoutParams(new PtrFrameLayout.LayoutParams(-1, -2));
header.setPadding(0, DisplayUtils.dpToPixel(this, 15), 0, DisplayUtils.dpToPixel(this, 10));
header.setPtrFrameLayout(mPtrFrameLayout);
mPtrFrameLayout.setLoadingMinTime(1000);
mPtrFrameLayout.setPinContent(true);
mPtrFrameLayout.setDurationToCloseHeader(100);
mPtrFrameLayout.setHeaderView(header);
mPtrFrameLayout.addPtrUIHandler(header);
mPtrFrameLayout.setPtrHandler(new PtrHandler() {
@Override
public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) {
return true;
}
@Override
public void onRefreshBegin(PtrFrameLayout frame) {
//刷新操作
}
});
mPtrFrameLayout.getContentView().setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
return false;
}
});
}
private void setView() {
//获得头部view
mHeaderView = LayoutInflater.from(this).inflate(R.layout.activity_main, null);
viewPager = (ViewPager) mHeaderView.findViewById(R.id.viewpager);
//适配不同手机,头图按照不同手机宽度适配
DisplayMetrics metrices = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrices);
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) this.viewPager.getLayoutParams();
params.height = metrices.widthPixels * 3 / 5;
params.width = metrices.widthPixels;
this.viewPager.setLayoutParams(params);
headerPagerAdapter = new HeaderPagerAdapter(this);
headerPagerAdapter.setHeadNews(newsList);
viewPager.setAdapter(headerPagerAdapter);
//头图的小圆点通过库实现
this.mTopPageIndicator = (CirclePageIndicator) mHeaderView.findViewById(R.id.indicator);
this.mTopPageIndicator.setViewPager(viewPager);
//手势适配器
this.mTapGestureDetector = new GestureDetector(this, new TapGestureListener());
viewPager.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return mTapGestureDetector.onTouchEvent(event);
}
});
//自动滚动的头图
if (!mPagerTimerHandler.hasMessages(MSG_PAGER)) {
mPagerTimerHandler.sendEmptyMessage(MSG_PAGER);
}
/** 下拉刷新 **/
mPtrFrameLayout = (PtrFrameLayout) findViewById(R.id.ptr_frame);
initPtrViews();
this.newsAdapter = new NewsAdapter(this);
newsAdapter.setNews(newsList);
this.mListView = (ListView) findViewById(R.id.list);
this.mListView.addHeaderView(mHeaderView);
this.mListView.setAdapter(newsAdapter);
}
private class TapGestureListener extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
//头图点击事件
Intent intent = new Intent(MainActivity.this, NewsActivity.class);
MainActivity.this.startActivity(intent);
return false;
}
@Override
public boolean onScroll(MotionEvent pE1, MotionEvent pE2, float pDistanceX, float pDistanceY) {
return super.onScroll(pE1, pE2, pDistanceX, pDistanceY);
}
@Override
public boolean onFling(MotionEvent pE1, MotionEvent pE2, float pVelocityX, float pVelocityY) {
return super.onFling(pE1, pE2, pVelocityX, pVelocityY);
}
}
//自动滚动的头图
private class PagerTimerHandler extends Handler {
@Override
public void handleMessage(Message msg) {
if (msg.what == MSG_PAGER) {
if (newsList != null && newsList.size() > 0) {
int totalItem = newsList.size();
int currentItem = viewPager.getCurrentItem();
int setCurrentItem = (currentItem + 1) % totalItem;
viewPager.setCurrentItem(setCurrentItem);
}
mPagerTimerHandler.sendEmptyMessageDelayed(MSG_PAGER, TICK);
} else {
super.handleMessage(msg);
}
}
}
}
在主页activity通过inflate获得头图的布局,继而获得头图的内容:viewpager等组件,并对其进行初始化操作。
这里需要注意的是:从网络获取的头图的图片比例是事先定义好的,由于Android手机屏幕的尺寸大小不一,所以一般的写法是获取屏幕宽度,然后按照比例设置对应的高度,如下:
头图View的布局:activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="220dp"
android:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center">android.support.v4.view.ViewPager>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="86dp"
android:layout_alignParentBottom="true"
android:background="@drawable/main_header_bg"
android:orientation="horizontal"
android:paddingTop="10dp">
<ImageView
android:id="@+id/main_heard_tag"
android:layout_width="35dp"
android:layout_height="23dp"
android:layout_marginLeft="5dp"
android:visibility="gone" />
<TextView
android:id="@+id/mian_heard_desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="25dp"
android:clickable="false"
android:focusable="false"
android:maxLines="2"
android:paddingLeft="16sp"
android:paddingRight="16sp"
android:text="测试测试测试"
android:textColor="#FFFFFF"
android:textIsSelectable="false"
android:textSize="19sp" />
<TextView
android:id="@+id/mian_heard_per"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:clickable="false"
android:focusable="false"
android:singleLine="true"
android:text="哈哈"
android:textColor="#FeFeFe"
android:textIsSelectable="false"
android:textSize="19sp" />
<com.viewpagerindicator.CirclePageIndicator
android:id="@+id/indicator"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="8dp"
android:background="#00000000"
app:fillColor="#FFFFFFFF"
app:pageColor="#66FFFFFF"
app:radius="3dp"
app:strokeColor="#00FFFFFF"
app:strokeWidth="1dp" />
RelativeLayout>
RelativeLayout>
LinearLayout>
头图的自动滚动,通过一个无限发消息的Handler来实现:
1)在oncreate方法中,发送一个msg:
2)Handler处理消息后,隔5秒再发送一个msg,通过这样实现一个无限循环的动作
头图的viewpager作为header设置进listview
下拉刷新获取网络数据的方法在onRefreshBegin方法中实现:
mPtrFrameLayout.setPtrHandler(new PtrHandler() {
@Override
public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) {
return true;
}
@Override
public void onRefreshBegin(PtrFrameLayout frame) {
//刷新操作
}
});
最后附上其余类的代码:
package com.baozou.headerviewtest;
import android.content.Context;
/**
* Created by jiangyu on 2015/10/31.
*/
public class DisplayUtils
{
public static int pixelToDp(final Context pContext, final int pPixels)
{
final float density = pContext.getResources().getDisplayMetrics().density;
return (int) ((pPixels / density) + 0.5);
}
public static int dpToPixel(final Context pContext, final int pDp)
{
final float density = pContext.getResources().getDisplayMetrics().density;
return (int) ((pDp * density) + 0.5f);
}
}
package com.baozou.headerviewtest;
import android.app.Activity;
import android.support.v4.view.PagerAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import java.util.ArrayList;
import java.util.List;
/**
* Created by jiangyu on 2015/10/29.
*/
public class HeaderPagerAdapter extends PagerAdapter {
private List headNews;
private ImageLoader mImageLoader;
private DisplayImageOptions mImageOptions;
private LayoutInflater inflater;
public HeaderPagerAdapter(Activity activity) {
super();
headNews = new ArrayList();
mImageLoader = ImageLoader.getInstance();
mImageLoader.init(ImageLoaderConfiguration.createDefault(activity));
mImageOptions = new DisplayImageOptions.Builder()
.cacheOnDisc()
.build();
inflater = LayoutInflater.from(activity);
}
public void setHeadNews(List news){
this.headNews = news;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
News topStory = headNews.get(position);
View view = inflater.inflate(R.layout.activity_main_header_topstory_pager, null);
ImageView topStoryImageView = (ImageView)view.findViewById(R.id.topstory_image);
topStoryImageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
// this.mImageLoader.displayImage(topStory.getUrl(), topStoryImageView, this.mImageOptions);
container.addView(view);
return view;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
@Override
public int getCount() {
return headNews.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view==object;
}
}
package com.baozou.headerviewtest;
/**
* Created by jiangyu on 2015/10/29.
*/
public class News {
String url;
String title;
public String getUrl() {
return url;
}
public String getTitle() {
return title;
}
public void setUrl(String url) {
this.url = url;
}
public void setTitle(String title) {
this.title = title;
}
}
package com.baozou.headerviewtest;
import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import java.util.List;
/**
* Created by jiangyu on 2015/10/31.
*/
public class NewsAdapter extends BaseAdapter {
private Activity activity;
private List news;
private LayoutInflater mInflater;
private ImageLoader mImageLoader;
private DisplayImageOptions mImageOptions;
public NewsAdapter(Activity activity) {
this.activity = activity;
this.mInflater = LayoutInflater.from(activity);
mImageLoader = ImageLoader.getInstance();
mImageLoader.init(ImageLoaderConfiguration.createDefault(activity));
mImageOptions = new DisplayImageOptions.Builder()
.cacheOnDisc()
.build();
}
public void setNews(List news) {
this.news = news;
}
@Override
public int getCount() {
return news.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = null;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.listview_item, parent, false);
viewHolder = new ViewHolder();
viewHolder.image = (ImageView)convertView.findViewById(R.id.item_pic);
viewHolder.title = (TextView)convertView.findViewById(R.id.item_title);
convertView.setTag(viewHolder);
}else{
viewHolder = (ViewHolder) convertView.getTag();
}
News news1 = this.news.get(position);
this.mImageLoader.displayImage(news1.getUrl(), viewHolder.image, this.mImageOptions);
viewHolder.title.setText(news1.getTitle());
return convertView;
}
private static class ViewHolder {
public ImageView image;
public TextView title;
}
}