Android APP常见首页效果的实现

总结一下最近做的一个项目首页,也是众多APP常见的首页效果:自动滚动的头图&ListView展示具体信息,效果大概类似于知乎日报的首页
Android APP常见首页效果的实现_第1张图片

写了一个简单的demo,没有仔细去设计布局,仅实现了类似的效果,并加上了google提倡的material design的下拉刷新风格,项目用到了以下几个著名的开源库:
1,图片加载库:imageloader
2,头图的小圆点:androidViewPagerIndicatorlibrary
3,下拉刷新控件:ultra-pullToRefreshlistview

【实现】
思路:总布局是一个ptr-listview,头图通过listview的setHeader设置,如果有分页加载,则加载更多的view通过listview的setFooter实现。头图是一个viewpager,自动滚动通过一个无限循环的handler实现。

【实现效果】
Android APP常见首页效果的实现_第2张图片

【代码结构】
Android APP常见首页效果的实现_第3张图片

【核心代码】
-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手机屏幕的尺寸大小不一,所以一般的写法是获取屏幕宽度,然后按照比例设置对应的高度,如下:
Android APP常见首页效果的实现_第4张图片

头图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,通过这样实现一个无限循环的动作
Android APP常见首页效果的实现_第5张图片

头图的viewpager作为header设置进listview
Android APP常见首页效果的实现_第6张图片

下拉刷新获取网络数据的方法在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;
    }
}

你可能感兴趣的:(Android,技术细节)