04 Gallery 源码-SlotView相册列表中点击单个相册的手势事件

0. 原文拜读

https://blog.csdn.net/lb377463323/article/details/70208825

1. AlbumSetPage 中的 SlotView

package com.android.gallery3d.app;

import com.android.gallery3d.ui.SlotView;


// 显示所有相册缩略图的页面
public class AlbumSetPage extends ActivityState implements OnClickListener,...{

    // SlotView 就是一个相册
    private SlotView mSlotView;

    private void initializeViews() {
        // mActivity -> mFragment
        if (null != mFragment && mFragment.isAdded()) {
            ...
        } else {
            mSelectionManager = new SelectionManager(mActivity, true);
            mSelectionManager.setSelectionListener(this);

            //mConfig是用来设置SlotView的参数,而
            mConfig = Config.AlbumSetPage.get(mActivity);
            mSlotView = new SlotView(mActivity, mConfig.slotViewSpec);

            //mAlbumSetView是mSlotView的渲染器,控制mSlotView的显示
            mAlbumSetView = new AlbumSetSlotRenderer(
                    mActivity, mSelectionManager, mSlotView, mConfig.labelSpec,
                    mConfig.slotViewSpec,
                    mConfig.placeholderColor);

            //将mAlbumSetView设置给mSlotView        
            mSlotView.setSlotRenderer(mAlbumSetView);
            
            //监听SlotView事件,根据手势操作做出相应的响应,这个监听事件原理
            mSlotView.setListener(new SlotView.SimpleListener() {
                ...
            });

            ...
            
            //把这个SlotView作为一个子控件传给GLView,mRootPane是GLView类
            mRootPane.addComponent(mSlotView);
        }
    }
    
}

2. SlotView 的手势事件

2.1 initializeViews 中的注册监听和回调事件
        mSlotView.setListener(new SlotView.SimpleListener() {
            @Override
            public void onDown(int index) {
                AlbumSetPage.this.onDown(index);
            }

            @Override
            public void onUp(boolean followedByLongPress) {
                AlbumSetPage.this.onUp(followedByLongPress);
            }

            // 以单击为例
            @Override
            public void onSingleTapUp(int slotIndex) {
                AlbumSetPage.this.onSingleTapUp(slotIndex);
            }

            @Override
            public void onLongTap(int slotIndex) {
                AlbumSetPage.this.onLongTap(slotIndex);
            }
        });
2.2 手势监听接口
package com.android.gallery3d.ui;

public class SlotView extends GLView {

    public static class SimpleListener implements Listener {
        @Override public void onDown(int index) {}
        @Override public void onUp(boolean followedByLongPress) {}
        @Override public void onSingleTapUp(int index) {}
        @Override public void onLongTap(int index) {}
        @Override public void onScrollPositionChanged(int position, int total) {}
    }

    public interface Listener {
        public void onDown(int index);
        public void onUp(boolean followedByLongPress);
        public void onSingleTapUp(int index);
        public void onLongTap(int index);
        public void onScrollPositionChanged(int position, int total);
    }
}
2.3 手势注册器实例化
package com.android.gallery3d.ui;

public class SlotView extends GLView {
    
    // Android 系统自带的手势检测器
    private final GestureDetector mGestureDetector;

    public SlotView(AbstractGalleryActivity activity, Spec spec) {
        mGestureDetector = new GestureDetector(activity, new MyGestureListener());
        ...
    }
}
2.4 手势事件来源
package com.android.gallery3d.ui;

public class SlotView extends GLView {

    @Override
    protected boolean onTouch(MotionEvent event) {
        if (mUIListener != null) mUIListener.onUserInteraction();
        mGestureDetector.onTouchEvent(event);
        ....
    }
}
2.5 MyGestureListener()
    private class MyGestureListener implements GestureDetector.OnGestureListener {
        private boolean isDown;

        // We call the listener's onDown() when our onShowPress() is called and
        // call the listener's onUp() when we receive any further event.
        @Override
        public void onShowPress(MotionEvent e) {
            GLRoot root = getGLRoot();
            root.lockRenderThread();
            try {
                if (isDown) return;
                int index = mLayout.getSlotIndexByPosition(e.getX(), e.getY());
                if (index != INDEX_NONE) {
                    isDown = true;
                    mListener.onDown(index);
                }
            } finally {
                root.unlockRenderThread();
            }
        }

        private void cancelDown(boolean byLongPress) {
            if (!isDown) return;
            isDown = false;
            mListener.onUp(byLongPress);
        }

        @Override
        public boolean onDown(MotionEvent e) {
            return false;
        }

        @Override
        public boolean onFling(MotionEvent e1,
                MotionEvent e2, float velocityX, float velocityY) {
            cancelDown(false);
            int scrollLimit = mLayout.getScrollLimit();
            if (scrollLimit == 0) return false;
            float velocity = WIDE ? velocityX : velocityY;
            mScroller.fling((int) -velocity, 0, scrollLimit);
            if (mUIListener != null) mUIListener.onUserInteractionBegin();
            invalidate();
            return true;
        }

        @Override
        public boolean onScroll(MotionEvent e1,
                MotionEvent e2, float distanceX, float distanceY) {
            cancelDown(false);
            float distance = WIDE ? distanceX : distanceY;
            int overDistance = mScroller.startScroll(
                    Math.round(distance), 0, mLayout.getScrollLimit());
            if (mOverscrollEffect == OVERSCROLL_3D && overDistance != 0) {
                mPaper.overScroll(overDistance);
            }
            invalidate();
            return true;
        }

        //点击一次
        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            cancelDown(false);
            if (mDownInScrolling) return true;
            //获取点击的相册索引
            int index = mLayout.getSlotIndexByPosition(e.getX(), e.getY());
            //处理点击事件
            if (index != INDEX_NONE) mListener.onSingleTapUp(index);
            return true;
        }

        @Override
        public void onLongPress(MotionEvent e) {
            cancelDown(true);
            if (mDownInScrolling) return;
            lockRendering();
            try {
                int index = mLayout.getSlotIndexByPosition(e.getX(), e.getY());
                if (index != INDEX_NONE) mListener.onLongTap(index);
            } finally {
                unlockRendering();
            }
        }
    }

3. SlotView 手势回调的处理

  • AlbumSetPage.this.onSingleTapUp(slotIndex)为例
    public void onSingleTapUp(int slotIndex) {
        if (!mIsActive) return;

        if (mSelectionManager.inSelectionMode()) {
            MediaSet targetSet = mAlbumSetDataAdapter.getMediaSet(slotIndex);
            if (targetSet == null) return; // Content is dirty, we shall reload soon
            mSelectionManager.toggle(targetSet.getPath());
            mSlotView.invalidate();
        } else {
            // Show pressed-up animation for the single-tap.
            // 显示动画
            mAlbumSetView.setPressedIndex(slotIndex);
            mAlbumSetView.setPressedUp();
            // 跳转到相册
            mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_PICK_ALBUM, slotIndex, 0),
                    FadeTexture.DURATION);
        }
    }
3.1 mHandler 传递
    mHandler = new SynchronizedHandler(mActivity.getGLRoot()) {
        @Override
        public void handleMessage(Message message) {
            switch (message.what) {
                case MSG_PICK_ALBUM: {
                    pickAlbum(message.arg1);
                    break;
                }
                default:
                    throw new AssertionError(message.what);
            }
        }
    };
3.2 跳转相册
package com.android.gallery3d.ui;

public class SlotView extends GLView {

    private void pickAlbum(int slotIndex) {
        ...

        if (mGetAlbum && targetSet.isLeafAlbum()) {
            ....
        } else if (targetSet.getSubMediaSetCount() > 0) {
            ...
        } else {
            ....
            data.putString(AlbumPage.KEY_MEDIA_PATH, mediaPath);

            //通过StateManager跳转到AlbumPage类中,跟应用的启动流程差不多
            getStateManager().startStateForResult(
                    AlbumPage.class, REQUEST_DO_ANIMATION, data);
        }
    }
}

上述中的页面跳转,即所有相册缩略图到相册的界面切换都是通过StateManager进行管理的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值