アップルの弾性レイアウトを模倣する

16481 ワード

Android開発では、IOSアプリケーションとandroidアプリケーションの体験が一致することがしばしば要求されるため、androidで開発する場合、多くのコントロールは開発者が自分で定義する必要があります.以下では、アップルを模した弾性スライドScrollViewを共有します.BounceScrollViewソース:
package com.joke.widget;



import android.content.Context;

import android.graphics.Rect;

import android.os.Build;

import android.util.AttributeSet;

import android.view.MotionEvent;

import android.view.View;

import android.view.animation.TranslateAnimation;

import android.widget.ScrollView;



/**

 * ScrollView       

 */

public class BounceScrollView extends ScrollView {

    private View inner;//   View



    private float y;//    y  



    private Rect normal = new Rect();//   (       ,            .)



    private boolean isCount = false;//       



    public BounceScrollView(Context context, AttributeSet attrs) {

        super(context, attrs);

        //                      

        if (Build.VERSION.SDK_INT >= 9) {

            this.setOverScrollMode(View.OVER_SCROLL_NEVER);

        }

    }



    /***

     *    XML         .             ,           .         onFinishInflate

     *   ,          ,        .

     */

    @Override

    protected void onFinishInflate() {

        if (getChildCount() > 0) {

            inner = getChildAt(0);

        }

    }



    /***

     *   touch

     */

    @Override

    public boolean onTouchEvent(MotionEvent ev) {

        if (inner != null) {

            commOnTouchEvent(ev);

        }



        return super.onTouchEvent(ev);

    }



    /***

     *     

     * 

     * @param 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 preY = y;//     y  

            float nowY = ev.getY();//   y  

            int deltaY = (int) (preY - nowY);//     

            if (!isCount) {

                deltaY = 0; //      0.

            }



            y = nowY;

            //

            if (isNeedMove()) {

                //        

                if (normal.isEmpty()) {

                    //          

                    normal.set(inner.getLeft(), inner.getTop(), inner.getRight(), inner.getBottom());

                }

                // Log.e("jj", "  :" + inner.getLeft() + "," + inner.getTop()

                // + "," + inner.getRight() + "," + inner.getBottom());

                //     

                inner.layout(inner.getLeft(), inner.getTop() - deltaY / 2, inner.getRight(), inner.getBottom() - deltaY / 2);

            }

            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);



        // Log.e("jj", "  :" + normal.left + "," + normal.top + "," +

        // normal.right

        // + "," + normal.bottom);



        normal.setEmpty();



    }



    //         

    public boolean isNeedAnimation() {

        return !normal.isEmpty();

    }



    /***

     *          inner.getMeasuredHeight():          

     * 

     * getHeight():         

     * 

     * @return

     */

    public boolean isNeedMove() {

        int offset = inner.getMeasuredHeight() - getHeight();

        int scrollY = getScrollY();

        // Log.e("jj", "scrolly=" + scrollY);

        // 0   ,       

        if (scrollY == 0 || scrollY == offset) {

            return true;

        }

        return false;

    }



}

使用説明:1、直接BounceScrollViewを*に置く.Widgetパッケージの2、レイアウトファイルで直接BounceScrollViewを使って他のレイアウトを包む
<com.joke.widget.BounceScrollView 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"

    android:fadeScrollbars="false"

    android:fadingEdge="none"

    android:fadingEdgeLength="0dip"

    tools:context=".MainActivity" >



    <!-- android:background="@drawable/coversation_bg" -->



    <LinearLayout

        android:layout_width="match_parent"

        android:layout_height="match_parent"

        android:background="#FF0000"

        android:orientation="vertical" >



        ...

    

    </LinearLayout>



</com.joke.widget.BounceView>

注意すべきは、BounceScrollViewは直接ScrollViewから継承されているので、BounceScrollViewもScrollViewの約束に従う必要があります.内部にはサブViewが1つしか許可されていないので、他のレイアウトはView Groupを使用して包む必要があります.また、BounceScrollViewにバックグラウンドを付けて、android:background="@drawable/coversation_bg"を使用することもできます.たとえば、coversation_bg.xmlは画像の重ね合わせ効果も実現できます
<?xml version="1.0" encoding="utf-8"?>

<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >



    <item>

        <bitmap

            android:src="@drawable/cover_default_bg"

            android:tileMode="repeat" />

    </item>

    <item android:top="10.0dip">

        <bitmap

            android:gravity="top|center"

            android:src="@drawable/conversation_bg_logo" />

    </item>



</layer-list>