该篇文章从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
下载地址:项目代码