AndroidのScrollViewはドラッグバウンス効果を実現

10105 ワード

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

    }



    /***

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

    }



}