[Android实例] 仿Win8磁铁效果,能够拖动改变Merto位置

该篇文章从eoeAndroid搬迁过来的,原文地址:[Android实例] 仿Win8磁铁效果,能够拖动改变Merto位置

最近公司一个同事让我做一个仿win8的效果,希望能够在固定的界面布局下进行拖动改变各个模块的位置,同时根据菜单内容数量不同展示相对应的Merto数量,就这样,我做了个Demo,可能有些粗糙,但是初步的功能都满足了,现在就把它贡献给大家,代码中不太规范的地方敬请见谅

由于有不同的模块,每个模块展示出图标和文字内容,所以我自定义一个MertoItemView进行绘制图标和文字

主要的绘制代码为:

@SuppressLint("DrawAllocation")
    @Override
    protected void onDraw(Canvas canvas) {
        // TODO Auto-generated method stub
        super.onDraw(canvas);
        int width = getWidth();
        int height = getHeight();
        TextPaint textPaint = new TextPaint();
        textPaint.setColor(textColor);
        textPaint.setTextSize(textSize);
        textPaint.setTypeface(Typeface.DEFAULT_BOLD);
        textPaint.setAntiAlias(true);
        StaticLayout layout = null;
        layout = new StaticLayout(text, textPaint, width - 10,
                Alignment.ALIGN_CENTER, 1.0F, 0.0F, true);
        if (icon != null) {
            Paint paint = new Paint();
            float iconWidth = 0;
            float iconHeight = 0;
            if (width > height - layout.getHeight()) {
                iconHeight = (height - layout.getHeight() - 5) / 2;
                iconWidth = iconHeight;
            } else {
                iconWidth = width / 2;
                iconHeight = iconWidth;
            }
            float iconX = (width - iconWidth) / 2;
            float iconY = (height - layout.getHeight() - iconHeight) / 2;
            Rect iconRect = new Rect((int) iconX, (int) iconY,
                    (int) (iconX + iconWidth), (int) (iconY + iconHeight));
            canvas.translate(0, 0);
            canvas.drawBitmap(((BitmapDrawable) icon).getBitmap(), null,
                    iconRect, paint);
            paint.reset();
        }
        canvas.translate((width - layout.getWidth()) / 2,
                height - layout.getHeight() - 10);
        layout.draw(canvas);
        textPaint.reset();
    }

自定义监听事件:

public interface OnMertoItemViewListener {

        public void onClick(MertoItemView v);

        public boolean onMove(MertoItemView v, MotionEvent e1, MotionEvent e2);

        public void onLongClick(MertoItemView v);

        public void onUp(MertoItemView v);

    }

在activity中,我做的拖动原理是,底层的布局为FrameLayout,将固定的13个MertoItemView列举在FrameLayout布局中,当点击某个MertoItemView时,将该MertoItemView隐藏,然后new一个MertoItemView放入到FrameLayout中的相同位置上,然后计算拖动的坐标位置进行移动新new的MertoItemView,在代码中进行计算当前拖动到的位置,将当前为的MertoItemView内容赋值给点击的那个MertoItemView,然后隐藏当前的MertoItemView,显示点击的那个MertoItemView,具体的不太好描述,在这里把主要的代码粘贴出来:

private OnMertoItemViewListener onMertoItemViewListener = new OnMertoItemViewListener() {

        @Override
        public void onClick(MertoItemView v) {
            // TODO Auto-generated method stub
            Toast.makeText(MertoActivity.this,
                    mertoBeans.get((Integer) v.getTag()).getName(),
                    Toast.LENGTH_SHORT).show();
        }

        @Override
        public boolean onMove(MertoItemView v, MotionEvent e1, MotionEvent e2) {
            // TODO Auto-generated method stub
            if (!isMove) {
                return false;
            }
            int[] moveLocation = new int[2];
            v.getLocationOnScreen(moveLocation);
            if (moveView == null) {
                tag = (Integer) v.getTag();
                startBeans = new ArrayList<MertoBean>(mertoBeans);
                moveView = new MertoItemView(MertoActivity.this);
                moveView.setIcon(v.getIcon());
                moveView.setText(v.getText());
                moveView.setTextColor(v.getTextColor());
                moveView.setTextSize(v.getTextSize());
                FrameLayout.LayoutParams moveParams = new FrameLayout.LayoutParams(
                        v.getWidth(), v.getHeight());
                moveParams.setMargins((int) (e1.getRawX() - e1.getX()),
                        (int) (e1.getRawY() - e1.getY()), 0, 0);
                moveParams.gravity = Gravity.TOP | Gravity.LEFT;
                moveView.setLayoutParams(moveParams);
                moveView.setBackgroundDrawable(v.getBackground());
                mertoContent.addView(moveView);
                moveView.getBackground().setAlpha(200);
            }
            setParams(
                    (int) (e1.getRawX() - e1.getX() + e2.getRawX() - e1
                            .getRawX()),
                    (int) (e1.getRawY() - e1.getY() + e2.getRawY() - e1
                            .getRawY()) - addBt.getHeight() - 40);
            changeData((int) e2.getRawX(), (int) e2.getRawY());
            return true;
        }

        @Override
        public void onLongClick(MertoItemView v) {
            // TODO Auto-generated method stub
            vibrator.vibrate(100);
            isMove = true;
        }

        @Override
        public void onUp(MertoItemView v) {
            // TODO Auto-generated method stub
            v.setVisibility(View.VISIBLE);
            if (isMove) {
                mertoContent.removeView(moveView);
                moveView = null;
                positionView.setVisibility(View.VISIBLE);
                tag = -1;
                moveTag = -1;
                setView();
                isMove = false;
            }
        }
    };

    private void setParams(int left, int top) {
        FrameLayout.LayoutParams moveParams = (LayoutParams) moveView
                .getLayoutParams();
        moveParams.setMargins(left, top, 0, 0);
        moveView.setLayoutParams(moveParams);
    }

    private void changeData(int x, int y) {
        if (positionView != null) {
            positionView.setVisibility(View.VISIBLE);
        }
        changeTag(x, y);
        if (tag != -1 && moveTag != -1) {
            mertoBeans = new ArrayList<MertoBean>(startBeans);
            if (mertoBeans.size() < 5) {
                MertoBean mertoBean = new MertoBean(mertoBeans.get(tag));
                mertoBeans.set(tag, mertoBeans.get(moveTag));
                mertoBeans.set(moveTag, mertoBean);
            } else {
                MertoBean mertoBean = new MertoBean(mertoBeans.get(tag - 1));
                mertoBeans.set(tag - 1, mertoBeans.get(moveTag - 1));
                mertoBeans.set(moveTag - 1, mertoBean);
            }
            setView();
            positionView.setVisibility(View.INVISIBLE);
        }
    }

    private void changeTag(int x, int y) {
        moveTag = -1;
        for (int i = 0; i < mertoItemViews.size(); i++) {
            int[] location = new int[2];
            mertoItemViews.get(i).getLocationOnScreen(location);
            if (x > location[0]
                    && x < location[0] + mertoItemViews.get(i).getWidth()
                    && y > location[1]
                    && y < location[1] + mertoItemViews.get(i).getHeight()
                    && mertoItemViews.get(i).getVisibility() == View.VISIBLE) {
                moveTag = i;
                positionView = mertoItemViews.get(i);
                return;
            } else {
                moveTag = tag;
                positionView = mertoItemViews.get(tag);
            }
        }
    }

还有一点代码就不在这儿一一粘贴上去了,至此,奉上gif图片和Demo
这里写图片描述

下载地址:项目代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值