[Android实例] 仿Win8磁铁效果,能够拖动改变Merto位置
2016-01-04 18:03
633 查看
该篇文章从eoeAndroid搬迁过来的,原文地址:[Android实例] 仿Win8磁铁效果,能够拖动改变Merto位置
最近公司一个同事让我做一个仿win8的效果,希望能够在固定的界面布局下进行拖动改变各个模块的位置,同时根据菜单内容数量不同展示相对应的Merto数量,就这样,我做了个Demo,可能有些粗糙,但是初步的功能都满足了,现在就把它贡献给大家,代码中不太规范的地方敬请见谅
由于有不同的模块,每个模块展示出图标和文字内容,所以我自定义一个MertoItemView进行绘制图标和文字
主要的绘制代码为:
自定义监听事件:
在activity中,我做的拖动原理是,底层的布局为FrameLayout,将固定的13个MertoItemView列举在FrameLayout布局中,当点击某个MertoItemView时,将该MertoItemView隐藏,然后new一个MertoItemView放入到FrameLayout中的相同位置上,然后计算拖动的坐标位置进行移动新new的MertoItemView,在代码中进行计算当前拖动到的位置,将当前为的MertoItemView内容赋值给点击的那个MertoItemView,然后隐藏当前的MertoItemView,显示点击的那个MertoItemView,具体的不太好描述,在这里把主要的代码粘贴出来:
还有一点代码就不在这儿一一粘贴上去了,至此,奉上gif图片和Demo
下载地址:项目代码
最近公司一个同事让我做一个仿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
下载地址:项目代码
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories