android 打造炫酷導航欄(仿UC頭條)

Den39A 8年前發布 | 41K 次閱讀 Android開發 移動開發

來自: http://blog.csdn.net/qq_16064871/article/details/50682388


年后開始上班甚是清閑,所以想搗鼓一些東西。在翻閱大神杰作Android 教你打造炫酷的ViewPagerIndicator 不僅僅是高仿MIUI 的時候看到下面有一條評論說,如果導航欄能滑動就更好了。我就想我可以去改一下就可以。然后又想感覺有點像UC的頭條的界面。于是就往里面加東西,調試寫代碼。弄了兩天有點效果了,寫出來看看了。

項目下載地址:http://download.csdn.net/detail/qq_16064871/9434291

1、先看效果

用咔咔大師錄屏的gif效果,有點失真。



這是第一個版本的效果。因為我不斷往里面加東西,所以有幾個版本了。

2、這個版本基本代碼

實現思路就是自定義繪制了。主要有兩層,第一層是ViewPagerIndicator。主要負責導航欄的三角形指示器的繪制,以及頁面滑動的回調,控制。當然這里需要android.support.v4.view.ViewPager這東西配合使用。

第二層是,導航欄的滑動效果,以及最左、最右有 反彈的效果。這個效果我是從以前一篇博文改動到了這里來。鏈接:android 滾動條下拉反彈的效果(類似微信朋友圈)。這里效果是垂直,改為橫向就行了。還有這兩層同時使用需要處理就是滑動不要沖突就可以了。

xml布局代碼:

<com.ucnew.view.BounceScrollView
            android:id="@+id/id_scrollview"
            android:layout_width="0dp"
            android:layout_height="45dp"
            android:layout_weight="1"
            android:focusableInTouchMode="false"
            android:scrollbars="none" >

            <com.ucnew.view.ViewPagerIndicator
                android:id="@+id/id_indicator"
                android:layout_width="match_parent"
                android:layout_height="45dp"
                android:orientation="horizontal"
                mmsx:item_count="4" >
            </com.ucnew.view.ViewPagerIndicator>
        </com.ucnew.view.BounceScrollView>

3、自定義view的java代碼

ViewPagerIndicator

package com.ucnew.view;

import java.util.List;

import com.ucnew.activity.R;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.CornerPathEffect;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.TextView;

public class ViewPagerIndicator extends LinearLayout
{
    //繪制三角形的畫筆
    private Paint mPaint;
     //path構成一個三角形
    private Path mPath;
    //三角形的寬度
    private int mTriangleWidth;
    // 三角形的高度
    private int mTriangleHeight;
     //三角形的寬度為單個Tab的1/6
    private static final float RADIO_TRIANGEL = 1.0f / 6;
    // 三角形的最大寬度
    private final int DIMENSION_TRIANGEL_WIDTH = (int) (getScreenWidth() / 3 * RADIO_TRIANGEL);
    //初始時,三角形指示器的偏移量
    private int mInitTranslationX;
     // 手指滑動時的偏移量
    private float mTranslationX;
     // tab數量
    private int mTabVisibleCount;
     // tab上的內容
    private List<String> mTabTitles;
     // 與之綁定的ViewPager
    public ViewPager mViewPager;
     // 標題正常時的顏色
    private static final int COLOR_TEXT_NORMAL = 0x77FFFFFF;
     //標題選中時的顏色
    private static final int COLOR_TEXT_HIGHLIGHTCOLOR = 0xFFFFFFFF;

    public ViewPagerIndicator(Context context)
    {
        this(context, null);
    }

    public ViewPagerIndicator(Context context, AttributeSet attrs)
    {
        super(context, attrs);

        // 獲得自定義屬性,tab的數量
        TypedArray a = context.obtainStyledAttributes(attrs,
                R.styleable.ViewPagerIndicator);
        mTabVisibleCount = a.getInt(R.styleable.ViewPagerIndicator_item_count,4);
        if (mTabVisibleCount < 0)
            mTabVisibleCount = 4;
        a.recycle();

        // 初始化畫筆
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setColor(Color.parseColor("#ffffffff"));
        mPaint.setStyle(Style.FILL);
        mPaint.setPathEffect(new CornerPathEffect(3));

    }

    //繪制指示器
    @Override
    protected void dispatchDraw(Canvas canvas)
    {
        canvas.save();
        // 畫筆平移到正確的位置
        canvas.translate(mInitTranslationX + mTranslationX, getHeight() + 1);
        canvas.drawPath(mPath, mPaint);
        canvas.restore();

        super.dispatchDraw(canvas);
    }

     //初始化三角形的寬度
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh)
    {
        super.onSizeChanged(w, h, oldw, oldh);
        mTriangleWidth = (int) (w / mTabVisibleCount * RADIO_TRIANGEL);// 1/6 of
                                                                        // width
        mTriangleWidth = Math.min(DIMENSION_TRIANGEL_WIDTH, mTriangleWidth);

        // 初始化三角形
        initTriangle();

        // 初始時的偏移量
        mInitTranslationX = getScreenWidth() / mTabVisibleCount / 2 - mTriangleWidth / 2;
    }

     //設置可見的tab的數量
    public void setVisibleTabCount(int count)
    {
        this.mTabVisibleCount = count;
    }

    //設置tab的標題內容 可選,生成textview加入布局,靈活處理
    public void setTabItemTitles(List<String> datas)
    {
        // 如果傳入的list有值,則移除布局文件中設置的view
        if (datas != null && datas.size() > 0)
        {
            this.removeAllViews();
            this.mTabTitles = datas;

            for (String title : mTabTitles)
            {
                // 添加view
                addView(generateTextView(title));
            }
            // 設置item的click事件
            setItemClickEvent();
        }

    }

    //根據標題生成我們的TextView
    private TextView generateTextView(String text)
    {
        TextView tv = new TextView(getContext());
        LinearLayout.LayoutParams lp = new LayoutParams(
                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
        lp.width = getScreenWidth() / mTabVisibleCount;
        tv.setGravity(Gravity.CENTER);
        tv.setTextColor(COLOR_TEXT_NORMAL);
        tv.setText(text);
        tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);
        tv.setLayoutParams(lp);
        return tv;
    }

    //對外的ViewPager的回調接口
    public interface PageChangeListener
    {
        public void onPageScrolled(int position, float positionOffset,
                int positionOffsetPixels);

        public void onPageSelected(int position);

        public void onPageScrollStateChanged(int state);
    }

    // 對外的ViewPager的回調接口
    private PageChangeListener onPageChangeListener;

    // 對外的ViewPager的回調接口的設置
    public void setOnPageChangeListener(PageChangeListener pageChangeListener)
    {
        this.onPageChangeListener = pageChangeListener;
    }

    // 設置關聯的ViewPager,以及傳入 BounceScrollView,進行設置滾動
    public void setViewPager(ViewPager mViewPager, final BounceScrollView scrollView, int pos)
    {
        this.mViewPager = mViewPager;

        mViewPager.setOnPageChangeListener(new OnPageChangeListener()
        {
            @Override
            public void onPageSelected(int position)
            {
                // 設置字體顏色高亮
                resetTextViewColor();
                highLightTextView(position);

                // 回調
                if (onPageChangeListener != null)
                {
                    onPageChangeListener.onPageSelected(position);
                }
            }

            @Override
            public void onPageScrolled(int position, float positionOffset,
                    int positionOffsetPixels)
            {
                // 滾動
                scroll(scrollView,position, positionOffset);
                // 回調
                if (onPageChangeListener != null)
                {
                    onPageChangeListener.onPageScrolled(position,
                            positionOffset, positionOffsetPixels);
                }
            }

            @Override
            public void onPageScrollStateChanged(int state)
            {
                // 回調
                if (onPageChangeListener != null)
                {
                    onPageChangeListener.onPageScrollStateChanged(state);
                }

            }
        });
        // 設置當前頁
        mViewPager.setCurrentItem(pos);
        // 高亮
        highLightTextView(pos);
    }

    //高亮文本
    protected void highLightTextView(int position)
    {
        View view = getChildAt(position);
        if (view instanceof TextView)
        {
            ((TextView) view).setTextColor(COLOR_TEXT_HIGHLIGHTCOLOR);
        }

    }

    //重置文本顏色
    private void resetTextViewColor()
    {
        for (int i = 0; i < getChildCount(); i++)
        {
            View view = getChildAt(i);
            if (view instanceof TextView)
            {
                ((TextView) view).setTextColor(COLOR_TEXT_NORMAL);
            }
        }
    }

    // 設置點擊事件
    public void setItemClickEvent()
    {
        int cCount = getChildCount();
        for (int i = 0; i < cCount; i++)
        {
            final int j = i;
            View view = getChildAt(i);
            view.setOnClickListener(new OnClickListener()
            {
                @Override
                public void onClick(View v)
                {
                    mViewPager.setCurrentItem(j);
                }
            });
        }
    }

    // 初始化三角形指示器
    private void initTriangle()
    {
        mPath = new Path();

        mTriangleHeight = (int) (mTriangleWidth / 2 / Math.sqrt(2));
        mPath.moveTo(0, 0);
        mPath.lineTo(mTriangleWidth, 0);
        mPath.lineTo(mTriangleWidth / 2, -mTriangleHeight);
        mPath.close();
    }

    //指示器跟隨手指滾動,以及容器滾動
    public void scroll(BounceScrollView scrollView,int position, float offset)
    {
        // 不斷改變偏移量,invalidate
        mTranslationX = getScreenWidth() / mTabVisibleCount * (position + offset);

        int tabWidth = getScreenWidth() / mTabVisibleCount;

        // 容器滾動,當移動到倒數最后一個的時候,開始滾動
        if (offset > 0 && position >= (mTabVisibleCount - 1) && getChildCount() > mTabVisibleCount)
        {

            if (mTabVisibleCount != 1)
            {
                //下面注釋掉,是滾動ViewPagerIndicator這個LinearLayout
//              this.scrollTo((position - (mTabVisibleCount - 1)) * tabWidth + (int) (tabWidth * offset), 0);
                //只滾動滾動條,禁止滾動lineayout
                scrollView.setScrolledTo((position - (mTabVisibleCount - 1)) * tabWidth + (int) (tabWidth * offset), 0);
            } else
            // 為count為1時 的特殊處理
            {
                this.scrollTo(position * tabWidth + (int) (tabWidth * offset), 0);
//              scrollView.setScrolledTo(position * tabWidth + (int) (tabWidth * offset), 0);
            }
        }
        //處理特殊情況
        else if (offset > 0 && position <= mTabVisibleCount - 1) {
            scrollView.setScrolledTo(0, 0);
        }

        invalidate();
    }

    //設置布局中view的一些必要屬性;如果設置了setTabTitles,布局中view則無效
    @Override
    protected void onFinishInflate()
    {
        super.onFinishInflate();

        int cCount = getChildCount();

        if (cCount == 0)
            return;

        for (int i = 0; i < cCount; i++)
        {
            View view = getChildAt(i);
            LinearLayout.LayoutParams lp = (LayoutParams) view
                    .getLayoutParams();
            lp.weight = 0;
            lp.width = getScreenWidth() / mTabVisibleCount;
            view.setLayoutParams(lp);
        }
        // 設置點擊事件
        setItemClickEvent();

    }

    //獲得屏幕的寬度
    public int getScreenWidth()
    {
        WindowManager wm = (WindowManager) getContext().getSystemService(
                Context.WINDOW_SERVICE);
        DisplayMetrics outMetrics = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(outMetrics);
        return outMetrics.widthPixels ;
    }

}

BounceScrollView

package com.ucnew.view;

import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.TranslateAnimation;
import android.widget.HorizontalScrollView;

/**
 * ScrollView反彈效果的實現
 */
public class BounceScrollView extends HorizontalScrollView {
    // 孩子View
    private View inner;
    // 點擊時x坐標
    private float x;
    // 矩形(這里只是個形式,只是用于判斷是否需要動畫
    private Rect normal = new Rect();
    // 是否開始計算
    private boolean isCount = false;
    private RotatImageView  mRotatImageView;

    public BounceScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    /***
     * 根據 XML 生成視圖工作完成.該函數在生成視圖的最后調用,在所有子視圖添加完之后. 即使子類覆蓋了 onFinishInflate
     * 方法,也應該調用父類的方法,使該方法得以執行.
     */
    @Override
    protected void onFinishInflate() {
        if (getChildCount() > 0) {
            inner = getChildAt(0);
        }
    }

    //手動需要設置滾動位置
    public void setScrolledTo(int position, float positionOffset) {
        this.scrollTo(position,(int) positionOffset);
    }

     //監聽touch
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (inner != null) {
            commOnTouchEvent(ev);
        }

        return super.onTouchEvent(ev);
    }

    //觸摸事件
    public void commOnTouchEvent(MotionEvent ev) {
        int action = ev.getAction();
        switch (action) {
        case MotionEvent.ACTION_DOWN:
            break;
        case MotionEvent.ACTION_UP:
            // 手指松開.
            if (isNeedAnimation()) {
                animation();
                isCount = false;
            }
            break;
        /***
         * 排除出第一次移動計算,因為第一次無法得知y坐標, 在MotionEvent.ACTION_DOWN中獲取不到,
         * 因為此時是MyScrollView的touch事件傳遞到到了LIstView的孩子item上面.所以從第二次計算開始.
         * 然而我們也要進行初始化,就是第一次移動的時候讓滑動距離歸0. 之后記錄準確了就正常執行.
         */
        case MotionEvent.ACTION_MOVE:
            final float preX = x;// 按下時的y坐標
            float nowX = ev.getX();// 時時y坐標
            int deltaX = (int) (preX - nowX);// 滑動距離
            if (!isCount) {
                deltaX = 0; // 在這里要歸0.
            }

            x = nowX;
            // 當滾動到最上或者最下時就不會再滾動,這時移動布局
            if (isNeedMove()) {
                // 初始化頭部矩形
                if (normal.isEmpty()) {
                    // 保存正常的布局位置
                    normal.set(inner.getLeft(), inner.getTop(),
                            inner.getRight(), inner.getBottom());
                }
                // 移動布局
                inner.layout(inner.getLeft() - deltaX / 4, inner.getTop(),
                        inner.getRight()  - deltaX / 4, inner.getBottom());

                //圖片加號旋轉,如果不需要這個直接刪了就行
                if (mRotatImageView != null) {
                    mRotatImageView.setRotationLeft();
                }
            }
            isCount = true;
            break;

        default:
            break;
        }
    }

    //回縮動畫
    public void animation() {
        // 開啟移動動畫
        TranslateAnimation ta = new TranslateAnimation(0, 0, inner.getTop(),
                normal.top);
        ta.setDuration(200);
        inner.startAnimation(ta);
        // 設置回到正常的布局位置
        inner.layout(normal.left, normal.top, normal.right, normal.bottom);
        normal.setEmpty();

    }

    //設置圖片加號旋轉
    public void setRotatImageView(RotatImageView rotatImageView){
        this.mRotatImageView = rotatImageView;
    }

    // 是否需要開啟動畫
    public boolean isNeedAnimation() {
        return !normal.isEmpty();
    }

    /***
     * 是否需要移動布局 inner.getMeasuredHeight():獲取的是控件的總高度
     * getHeight():獲取的是屏幕的高度
     */
    public boolean isNeedMove() {
        int offset = inner.getMeasuredWidth() - getWidth();
        int scrollX = getScrollX();

        // 0是頂部反彈
        //是底部反彈加上    
        if (scrollX == 0  || scrollX == offset) {
            return true;
        }
        return false;
    }

}

都有很詳細的注釋,以及測試需要說明。

那么就直接看下一個版本。

4、看下一個版本效果


多了一個圖標,這個圖標可以用來監聽,等等。

我后面搗鼓加了一個旋轉動畫,動畫效果可能不是很好。但也可以看看。

5、xml代碼

有一些自定義屬性以及效果的代碼就不貼,感興趣下載源碼。看不懂的,看我前幾篇文章,自定義控件使用。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:mmsx="http://schemas.android.com/apk/res/com.ucnew.activity"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffffffff"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#8000bf5f" >

        <com.ucnew.view.BounceScrollView
            android:id="@+id/id_scrollview"
            android:layout_width="0dp"
            android:layout_height="45dp"
            android:layout_weight="1"
            android:focusableInTouchMode="false"
            android:scrollbars="none" >

            <com.ucnew.view.ViewPagerIndicator
                android:id="@+id/id_indicator"
                android:layout_width="match_parent"
                android:layout_height="45dp"
                android:orientation="horizontal"
                mmsx:item_count="4" >
            </com.ucnew.view.ViewPagerIndicator>
        </com.ucnew.view.BounceScrollView>

        <com.ucnew.view.RotatImageView
            android:id="@+id/id_rotat_imageView"
            android:layout_width="50dp"
            android:layout_height="wrap_content"
            android:paddingLeft="30dp"
            android:layout_gravity="center"
            mmsx:src="@drawable/add" >
        </com.ucnew.view.RotatImageView>
    </LinearLayout>

    <android.support.v4.view.ViewPager
        android:id="@+id/id_vp"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" >
    </android.support.v4.view.ViewPager>

</LinearLayout>

6、增加以及這里主要主要需要改的代碼。

ViewPagerIndicator類的這個函數

//獲得屏幕的寬度
    public int getScreenWidth()
    {
        WindowManager wm = (WindowManager) getContext().getSystemService(
                Context.WINDOW_SERVICE);
        DisplayMetrics outMetrics = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(outMetrics);
        //獲取是整個屏幕的寬度,我試過自定義寬度測量寬度,不行。因為本身還沒內容,是后面添加的。所以需要后面加東西
        //需要這里減去寬度就行。其中這里減去120就是60dp的寬度
        return outMetrics.widthPixels -100;
    }

還有一個圖片的旋轉類RotatImageView

package com.ucnew.view;

import com.ucnew.activity.R;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

public class RotatImageView extends View {
    private Paint paint = null; // 畫筆
    private Bitmap mbitmap = null; // 圖片位圖
    private Bitmap bitmapDisplay = null;
    private Matrix matrix = null;
    private int mWidth = 0; // 圖片的寬度
    private int mHeight = 0; // 圖片的高度
    private float fAngle = 180.0f; // 圖片旋轉
    private PaintFlagsDrawFilter mDrawFilter; 

    public RotatImageView(Context context) {
        super(context);
    }

    public RotatImageView(Context context, AttributeSet attrs)
    {
        this(context, attrs, 0);
    }

    /**
     * 初始化一些自定義的參數
     * 
     * @param context
     * @param attrs
     * @param defStyle
     */
    public RotatImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

        TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
                R.styleable.RotatImageView, defStyle, 0);

        int n = a.getIndexCount();
        for (int i = 0; i < n; i++) {
            int attr = a.getIndex(i);
            switch (attr) {
            // 原始圖片,在布局里面獲取
            case R.styleable.RotatImageView_src:
                mbitmap = BitmapFactory.decodeResource(getResources(),a.getResourceId(attr, 0));
                bitmapDisplay = mbitmap;
                break;
            }
        }
        a.recycle();

        mDrawFilter = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG);
        paint = new Paint();
        paint.setFlags(Paint.ANTI_ALIAS_FLAG);

        matrix = new Matrix();
    }

    /**
     * 計算控件的高度和寬度
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        // 設置寬度
        int specMode = MeasureSpec.getMode(widthMeasureSpec);
        int specSize = MeasureSpec.getSize(widthMeasureSpec);

        //match_parent或者設置的精確值獲取
        //MeasureSpec.EXACTLY
        if (specMode == MeasureSpec.EXACTLY)
        {
            mWidth = specSize;
        } 
        else
        {
            // 由圖片決定的寬
            //getPaddingLeft(),getPaddingRight()這兩個值是控件屬性的向內偏移的距離值,所以的一起計算
            //區別于layout_marginLeft,兩個控件的左間距值設置
            int desireByImg = getPaddingLeft() + getPaddingRight()
                    + mbitmap.getWidth();

            // wrap_content
            if (specMode == MeasureSpec.AT_MOST)
            {
                //所以最小的值,寬度的話是左右內偏移距離之和
                mWidth = Math.min(desireByImg, specSize);
            } else

                mWidth = desireByImg;
        }

        // 設置高度,部分解釋同上
        specMode = MeasureSpec.getMode(heightMeasureSpec);
        specSize = MeasureSpec.getSize(heightMeasureSpec);

        //match_parent或者設置的精確值獲取
        //MeasureSpec.EXACTLY
        if (specMode == MeasureSpec.EXACTLY)
        {
            mHeight = specSize;
        } else
        {
            int desire = getPaddingTop() + getPaddingBottom()
                    + mbitmap.getHeight();

            // wrap_content
            if (specMode == MeasureSpec.AT_MOST)
            {
                mHeight = Math.min(desire, specSize);
            } else
                mHeight = desire;
        }

        //計算好的寬度以及高度是值,設置進去
        setMeasuredDimension(mWidth, mHeight);
    }

    // 向左旋轉
    public void setRotationLeft() {
        fAngle = fAngle - 20;
        setAngle();
    }

    // 向右旋轉
    public void setRotationRight() {
        fAngle = fAngle + 20;
        setAngle();
    }

    private boolean isRoate = false;
    // 設置旋轉比例
    private void setAngle() {
        Log.i("Show", String.valueOf(fAngle));
        isRoate = true;
        //設置圖片的旋轉中心,即繞(X,Y)這點進行中心旋轉 要旋轉的角度
        matrix.preRotate(fAngle, (float)mbitmap.getWidth()/2, (float)mbitmap.getHeight()/2); 
        invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        //消除鋸齒, 圖片旋轉后的鋸齒消除不成功,實在不行圖片邊緣加一些白色像素點
        canvas.setDrawFilter(mDrawFilter); 
        if (isRoate) {
            canvas.drawBitmap(bitmapDisplay, matrix, paint);
            isRoate = false;
        }else {
            canvas.drawBitmap(bitmapDisplay, 0, 0, paint);  
        }
    }
}

activity調用以及初始化這些自定義控件

package com.ucnew.activity;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.ucnew.activity.R;
import com.ucnew.fragment.VpSimpleFragment;
import com.ucnew.view.BounceScrollView;
import com.ucnew.view.RotatImageView;
import com.ucnew.view.ViewPagerIndicator;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.Window;

public class MainActivity extends FragmentActivity
{
    private List<Fragment> mTabContents = new ArrayList<Fragment>();
    private FragmentPagerAdapter mAdapter;
    private ViewPager mViewPager;
    private List<String> mDatas = Arrays.asList("頁面1", "頁面2", "頁面3", "頁面4",
            "頁面5", "頁面6", "頁面7", "頁面8", "頁面9");

    private ViewPagerIndicator mIndicator;
    private BounceScrollView mScrollView;
    private RotatImageView mRotatImageView;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.vp_indicator);

        initView();
        initDatas();
        //設置Tab上的標題
        mIndicator.setTabItemTitles(mDatas);
        mViewPager.setAdapter(mAdapter);
        //設置關聯的ViewPager
        mIndicator.setViewPager(mViewPager,mScrollView,0);
        //設置關聯的圖片旋轉,根據需要設置,效果不是很好
        mScrollView.setRotatImageView(mRotatImageView);
    }

    private void initDatas()
    {

        for (String data : mDatas)
        {
            VpSimpleFragment fragment = VpSimpleFragment.newInstance(data);
            mTabContents.add(fragment);
        }

        mAdapter = new FragmentPagerAdapter(getSupportFragmentManager())
        {
            @Override
            public int getCount()
            {
                return mTabContents.size();
            }

            @Override
            public Fragment getItem(int position)
            {
                return mTabContents.get(position);
            }
        };
    }

    private void initView()
    {
        mScrollView = (BounceScrollView) findViewById(R.id.id_scrollview);
        mViewPager = (ViewPager) findViewById(R.id.id_vp);
        mIndicator = (ViewPagerIndicator) findViewById(R.id.id_indicator);
        mRotatImageView = (RotatImageView)findViewById(R.id.id_rotat_imageView);

    }


}

還有部分代碼沒貼。自已下載查看吧。


7、最后效果圖


錄屏不是很清晰,來一張截圖,夠清晰的



項目下載地址:http://download.csdn.net/detail/qq_16064871/9434291

用到知識

Android 教你打造炫酷的ViewPagerIndicator 不僅僅是高仿MIUI

android 滾動條下拉反彈的效果(類似微信朋友圈)

 

android 自定義控件以及自定義view學習(隨機驗證碼生成)


 

android 自定義控件屬性(TypedArray以及attrs解釋)


 

android 自定義圖片合集(自定義控件)


 本文由用戶 Den39A 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!