Android自訂Viewgroup切換View帶有吸附效果

來源:互聯網
上載者:User

Android自訂Viewgroup切換View帶有吸附效果

 

1.概述先上

大概就是這個效果,先說說實現思路 1.首先我們要拿到圖片的url(網路)或id、路徑(本地),將View與資料進行綁定,寫我們自己的Adapter 2.自訂Viewgroup將要顯示的view進行布局,以及處理觸摸事件進行邏輯處理 3.寫切換回調
2.實現1)自訂Adapter這裡我下載的網狀圖片,同樣可以將圖片放到res下設定ImageView的內容
public class DragPageViewAdapter {    private static final String TAG = DragPageViewAdapter;    private List mDatas;    private Context mContext;    private LayoutInflater inflater;    /**     * 寬和高     */    int width;    int height;    public DragPageViewAdapter(Context mContext) {        this.mContext = mContext;        inflater = LayoutInflater.from(mContext);        width = (int) (0.8*DragViewActivity.mScreenWidth);//寬是螢幕寬度的0.8        height = (int) (0.8*DragViewActivity.mScreenWidth);    }    public int getCount(){        return mDatas==null?0:mDatas.size();    }    public int getItemId(int position){        return position;    }    public Object getItem(int position){        return mDatas==null?null:mDatas.get(position);    }    public View getView(int position, View convertView, ViewGroup parent){        LogHelper.d(TAG, position : + position);        final ImageView imageView = new ImageView(mContext);        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(width,height);        params.addRule(Gravity.CENTER);        imageView.setLayoutParams(params);        imageView.setBackgroundDrawable(mContext.getResources().getDrawable(R.drawable.gray_border));        ViewHelper.setAlpha(imageView,1.0f);        String url = mDatas.get(position).getPictureUrl();        if (!Utils.stringIsNull(url)){            url = url.substring(0, url.lastIndexOf(.)) + --300x300.png;//            UILHelper.loadImageUrl(url, imageView,0);            UILHelper.loadImageUrl(url, new SimpleImageLoadingListener(){                @Override                public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {                    imageView.setImageBitmap(loadedImage);                }            });        }        convertView = imageView;        convertView.setTag(mDatas.get(position));//        viewHolder.mImageView.setImageResource((Integer) mDatas.get(position));        return convertView;    }    public void setData(List data){        mDatas = data;    }    private class ViewHolder{        ImageView mImageView;    }}

通過此Adapter將所需要的圖片匆網路下載下來,當我們需要的時候ImageView自己去請求下載。並將資料通過setTag的方法與ImageView進行綁定2)自訂Viewgroup直接上代碼,我們要做的事情 a.onMeasure方法測量子自己及子view b.onLayout方法給子view進行布局 c.onTouchEvent處理觸摸事件,up的時候判斷是否切換下一個view,如果不是的話通過屬性動畫將view的狀態恢複 d.綁定切換的回調 e.切換後把當前的View從viewgruop中remove掉,add一個需要載入的view,同時給當前view賦值為切換的view,保證viewgroup中不多於指定的子view個數,保證不OOM
public class DragPageView extends ViewGroup{    private static final String TAG = DragPageView;    /**     * 適配器     */    private DragPageViewAdapter mAdapter;    /**     * view的個數     */    private int ONE_SCREEN_COUNT = 2;    /**     * 螢幕的寬和高     */    private int mScrenWidth;    private int mScreenHeight;    /**     * 子項目的寬 高     */    private int mChildWidth;    private int mChildHeight;    /**     * 當前最後一張圖片的index     */    private int mLastIndex;    /**     * 當前第一張圖片的下標     */    private int mFirstIndex;    /**     * 當前顯示View     */    private View mFirstView;    /**     * 之前觸摸的x y     */    private int mDownX;    private int mDownY;    /**     * 當前觸摸的x y     */    private int mCurX;    private int mCurY;    public static int mDirection = -1;    public static final int DIRECTION_LEFT_TO_RIGHT = 1;    public static final int DIRECTION_RIGHT_TO_LEFT = 2;    /**     * 儲存View與位置的索引值對     */    private Map mViewMap = new HashMap();    /**     * 最大旋轉角度     */    private int ROTATE_DEGREE = 30;    private int CHILD_OFFSET = 10;    /**     * 儲存回調介面     */    private OnImageSavedListener mOnImageSavedListener;    public void setOnImageSavedListener(OnImageSavedListener mOnImageSavedListener) {        this.mOnImageSavedListener = mOnImageSavedListener;    }    public DragPageView(Context context) {        this(context, null);    }    public DragPageView(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public DragPageView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        //獲得螢幕寬和高        WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);        DisplayMetrics metrics = new DisplayMetrics();        windowManager.getDefaultDisplay().getMetrics(metrics);        mScrenWidth = metrics.widthPixels;        mScreenHeight = metrics.heightPixels;    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        /**         * 獲得此ViewGroup上級容器為其推薦的寬和高,以及計算模式         */        int widthMode = MeasureSpec.getMode(widthMeasureSpec);        int heightMode = MeasureSpec.getMode(heightMeasureSpec);        int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);        int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);        // 計算出所有的childView的寬和高        measureChildren(widthMeasureSpec, heightMeasureSpec);        setMeasuredDimension(mScrenWidth, sizeHeight);    }    @Override    protected void onLayout(boolean changed, int l, int t, int r, int b) {        for (int i = 0; i < getChildCount(); i++){            View child = getChildAt(i);            mChildWidth = child.getMeasuredWidth();            mChildHeight = child.getMeasuredHeight();            int left = getWidth()/2-mChildWidth/2;            int top = getHeight()/2- mChildHeight*2/3;            int right = left + mChildWidth;            int bottom = top + mChildHeight;            if (i == 0)                child.layout(left+CHILD_OFFSET, top+CHILD_OFFSET, right+CHILD_OFFSET, bottom+CHILD_OFFSET);            else                child.layout(left, top, right, bottom);        }    }    public void initDatas(DragPageViewAdapter mAdapter){        this.mAdapter = mAdapter;        initView();    }    @TargetApi(Build.VERSION_CODES.HONEYCOMB)    private void initView() {        removeAllViews();        for (int i = 0; i < ONE_SCREEN_COUNT; i++){            View view = mAdapter.getView(i, null, this);            mViewMap.put(i,view);        }        //mViewMap中存放的view倒敘添加到ViewGroup,因為ViewGroup index = 0在最底層        for (int j= ONE_SCREEN_COUNT -1; j>=0;j--){            addView(mViewMap.get(j));            if (j == 0){                mFirstView = mViewMap.get(j);            }        }        mLastIndex = ONE_SCREEN_COUNT -1;        mFirstIndex = mLastIndex - ONE_SCREEN_COUNT-1;    }    @TargetApi(Build.VERSION_CODES.HONEYCOMB)    @Override    public boolean onTouchEvent(MotionEvent event) {        int focusX = (int) event.getX();        int focusY = (int) event.getY();        switch (event.getAction()){            case MotionEvent.ACTION_DOWN:                mDownX = mCurX = focusX;                mDownY = mCurY = focusY;                break;            case MotionEvent.ACTION_MOVE:                final int deltaX = focusX - mCurX;                final int deltaY = focusY-mCurY ;                if (Math.abs(deltaX) > 5 || Math.abs(deltaY)>5){                    if (focusX > mDownX){                        mDirection = DIRECTION_LEFT_TO_RIGHT;                    }else {                        mDirection = DIRECTION_RIGHT_TO_LEFT;                    }                    handlerScroll(deltaX, deltaY);//                mFirstView.setPivotX((float) (mFirstView.getMeasuredWidth()*0.5));//                mFirstView.setPivotY(mFirstView.getMeasuredHeight());                    mFirstView.setRotation(ROTATE_DEGREE*(focusX-mDownX)/mChildWidth);                }                mCurX = focusX;                mCurY = focusY;                break;            case MotionEvent.ACTION_UP:                LogHelper.d(TAG, mPreX :  + mDownX +  mPreY  + mDownY +  mCurX :  + mCurX +  mCurY :  + mCurY);                if (Math.abs(mCurX- mDownX)> mChildWidth/2 && mLastIndex < mAdapter.getCount()){                    loadNextImage();                }else {                    resetView();                }                break;        }        return true;    }    private void resetView() {        PropertyValuesHolder oaX= PropertyValuesHolder.ofFloat(translationX, 0);        PropertyValuesHolder oaY = PropertyValuesHolder.ofFloat(translationY,0);        PropertyValuesHolder rotate = PropertyValuesHolder.ofFloat(rotation,0);        ObjectAnimator.ofPropertyValuesHolder(mFirstView, oaX, oaY, rotate).start();    }    public void loadNextImage() {        ObjectAnimator oaX = null;        ObjectAnimator oaRotate = null;        if (mLastIndex == mAdapter.getCount()) return;        if (mDirection == DIRECTION_LEFT_TO_RIGHT){            oaX = new ObjectAnimator().ofFloat(mFirstView, translationX,800);            oaRotate = new ObjectAnimator().ofFloat(mFirstView, rotation,ROTATE_DEGREE);            //通知回調已儲存的view            if (mOnImageSavedListener != null){                mOnImageSavedListener.onImageSaved(mFirstView);            }        }else {            oaX = new ObjectAnimator().ofFloat(mFirstView, translationX, -800);            oaRotate = new ObjectAnimator().ofFloat(mFirstView, rotation, -ROTATE_DEGREE);            if (mOnImageSavedListener != null){                mOnImageSavedListener.onImageDelete(mFirstView);            }        }        oaX.addListener(new AnimatorListenerAdapter() {            @Override            public void onAnimationEnd(Animator animation) {                //動畫結束後load下一張圖片                mViewMap.remove(mFirstIndex);                //刪除view                removeAllViews();                //擷取下一張圖片                if ((mLastIndex+1)>= mAdapter.getCount()){                    addView(mViewMap.get(mLastIndex));                }else {                    View view = mAdapter.getView(++mLastIndex, null, DragPageView.this);                    mViewMap.put(mLastIndex, view);                    addView(mViewMap.get(mLastIndex));                    addView(mViewMap.get(mLastIndex-1));                    mFirstView = mViewMap.get(mLastIndex-1);                }            }        });        //開啟動畫        oaRotate.start();        oaX.start();    }    @TargetApi(Build.VERSION_CODES.HONEYCOMB)    private void handlerScroll(float distanceX, float distanceY) {        int newLeft = (int) (mFirstView.getLeft()+distanceX);        int newTop = (int) (mFirstView.getTop()+distanceY);        float[] deltaVector = {distanceX, distanceY};        mFirstView.getMatrix().mapVectors(deltaVector);        mFirstView.setTranslationX(mFirstView.getTranslationX() + deltaVector[0]);        mFirstView.setTranslationY(mFirstView.getTranslationY() + deltaVector[1]);    }    public interface OnImageSavedListener{        public void onImageSaved(View view);        public void onImageDelete(View view);    }}
3)Activity負責的事情 a.請求資料初始化Adapter及ViewGroup b.切換回調的響應 c.點擊按鍵切換的事件處理
public class DragViewActivity extends BaseActivity{    private static final String TAG = DragViewActivity;    private DragPageViewAdapter adapter;    private DragPageView mDragView;    private int pageIndex = 1;    private int pageSize = 21;    private int total;    /**     * userId     */    private String userId;    //網路請求的資料    private List lists;    //儲存的view的資訊    private List mSavedView;    private WxCollocationRandomList mViewInfo;    /**     * 螢幕寬和高     */    public static int mScreenWidth;    public static int mScreenHeight;    private TextView mSkip;    private TextView mSave;    private TextView mDone;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.dragview_act);        WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);        DisplayMetrics displayMetrics = new DisplayMetrics();        windowManager.getDefaultDisplay().getMetrics(displayMetrics);        mScreenWidth = displayMetrics.widthPixels;        mScreenHeight = displayMetrics.heightPixels;        userId = SettingsManager.getSettingsManager(this).getUserId();        initView();        httpGetImageInfo(pageIndex);    }    private void httpGetImageInfo(final int pageIndex) {        JSONObject object = new JSONObject();        try {            object.put(pageIndex, pageIndex);            object.put(pageSize, pageSize);        } catch (JSONException e) {            e.printStackTrace();        }        if (pageIndex == 1) {            showProgress(getResources().getString(R.string.app_data_loading));        }        HttpsRequestUtil.doHttpsVolleyPost(this, SOAServices.COLLOCATION_SERVICE,                SOAMethods.RANDOM_COLLOCATION, HttpsRequestUtil.GET, object, new Response.Listener(){                    @Override                    public void onResponse(String response) {                        if (pageIndex ==1){                            closeProgress();                        }                        transformData(response);                    }                }, new Response.ErrorListener(){                    @Override                    public void onErrorResponse(VolleyError error) {                        closeProgress();                    }                });    }    /**     * 請求的資料,進行初始化adapter及Viewgroup的初始化     * @param response     */    private void transformData(String response) {        Gson gson = new Gson();        WxCollocationRandomFilter wxCollocationRandomFilter= gson.fromJson(response, WxCollocationRandomFilter.class);        total = wxCollocationRandomFilter.getTotal();        if (total == 0)return;        lists = wxCollocationRandomFilter.getCollocationRandomLists();        adapter.setData(lists);        mDragView.initDatas(adapter);    }    private void initView() {        mDragView = (DragPageView) findViewById(R.id.dragView);        adapter = new DragPageViewAdapter(this);        mDragView.setOnImageSavedListener(new DragPageView.OnImageSavedListener() {            @Override            public void onImageSaved(View view) {                mViewInfo = (WxCollocationRandomList) view.getTag();                httpSaveFavorite(mViewInfo);            }            @Override            public void onImageDelete(View view) {                mViewInfo = (WxCollocationRandomList) view.getTag();                httpDeleteFavorite(mViewInfo);            }        });        mSkip = (TextView) findViewById(R.id.skip);        mSave = (TextView) findViewById(R.id.save);        mDone = (TextView) findViewById(R.id.done);        mSkip.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                mDragView.mDirection = mDragView.DIRECTION_RIGHT_TO_LEFT;                mDragView.loadNextImage();            }        });        mSave.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                mDragView.mDirection = mDragView.DIRECTION_LEFT_TO_RIGHT;                mDragView.loadNextImage();            }        });        mDone.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                DragViewActivity.this.finish();            }        });    }    /**     * 喜歡     * @param mViewInfo  搭配資訊 sourcE_TYPE 1 商品 2 搭配     */    private void httpSaveFavorite(WxCollocationRandomList mViewInfo) {        JSONObject jsonObject = new JSONObject();        try {            jsonObject.put(sourcE_ID, mViewInfo.getId());            jsonObject.put(userId,userId);            jsonObject.put(creatE_USER, mViewInfo.getCreateUser());            jsonObject.put(sourcE_TYPE, 2);        } catch (JSONException e) {            e.printStackTrace();        }        HttpsRequestUtil.doHttpsVolleyPost(DragViewActivity.this, SOAServices.ORDER_SERVICE, SOAMethods.FAVORITE_ADD,                HttpsRequestUtil.POST, jsonObject, new Response.Listener() {                    @Override                    public void onResponse(String response) {                        LogHelper.d(TAG, SaveFavorite Success!);                    }                }, new Response.ErrorListener() {                    @Override                    public void onErrorResponse(VolleyError error) {                        LogHelper.d(TAG, SaveFavorite Error!);                    }                });    }    /**     * 刪除喜歡     * @param mViewInfo  搭配資訊 sourcE_TYPE 1 商品 2 搭配     */    private void httpDeleteFavorite(WxCollocationRandomList mViewInfo) {        JSONObject jsonObject = new JSONObject();        try {            jsonObject.put(sourcE_ID, mViewInfo.getId());            jsonObject.put(userId,userId);            jsonObject.put(creatE_USER, mViewInfo.getCreateUser());            jsonObject.put(sourcE_TYPE, 2);        } catch (JSONException e) {            e.printStackTrace();        }        HttpsRequestUtil.doHttpsVolleyPost(DragViewActivity.this, SOAServices.ORDER_SERVICE, SOAMethods.FAVORITE_DELETE,                HttpsRequestUtil.POST, jsonObject, new Response.Listener() {                    @Override                    public void onResponse(String response) {                        LogHelper.d(TAG, DeleteFavorite Success!);                    }                }, new Response.ErrorListener() {                    @Override                    public void onErrorResponse(VolleyError error) {                        LogHelper.d(TAG, DeleteFavorite Error!);                    }                });    }}



 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.