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

http://www.eoeandroid.com/thread-547151-1-1.html

最近公司一个同事让我做一个仿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

merto_menu.gif(459.9 KB, 下载次数: 7)

下载附件保存到相册

2014-9-30 16:40 上传

merto_menu.gif

 

http://pan.baidu.com/s/1dDhCJNb

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值