android 自定义view实现图形移动

--(自定义view及属性

转载说明出处:http://blog.csdn.net/liyulei316686082/article/details/7204191

首先,先了解一下需求。有一个看起来类似立体的图,图上有个点。我们要让这个点这个图上移动。

那么我们应该什么做呢?

看题目也应该明白了。

这个简化的例子只通触摸屏幕来移动的,如果想通过按键或button来控制,很简单,只需onTouchEvent()函数的实现即可。

步骤一、新建工程。new一个我们自定义的View类:(class MyPictureView extends View)

以下是这个类的构造方法:

public MyPictureView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;

T ypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.EQSoundEffect);

final int N = a.getIndexCount();
for (int i = 0; i < N; i++) {
int attr = a.getIndex(i);
switch (attr) {
case R.styleable.EQSoundEffect_pointx:
bmp_x = a.getDimension(R.styleable.EQSoundEffect_pointx, 0);
break;
case R.styleable.EQSoundEffect_pointy:
bmp_y = a.getDimension(R.styleable.EQSoundEffect_pointy, 0);
break;
case R.styleable.EQSoundEffect_displaycoordinates:
mDrawFrlr = a.getDrawable(attr);
System.out.println("mDrawFrlr:" + mDrawFrlr);
mFrlrBg = ((BitmapDrawable) mDrawFrlr).getBitmap();
break;
case R.styleable.EQSoundEffect_dispalypoint:
mDrawPoint = a.getDrawable(attr);
System.out.println("mDrawPoint:" + mDrawPoint);
mPoint = ((BitmapDrawable) mDrawPoint).getBitmap();
break;

}
}

mPaint = new Paint();
mPaint.setColor(Color.BLUE);// 设置画笔颜色
}

这里分析以下这个方法的作用:

1、简单是说它只有一个作用,就是从xml布局文件中拿到我们自定义的属性。

两张图片:一张是坐标图也就是点的背景图。另一张就是移动点图片了。

两个点的原始坐标。(switch 中)

2、有了坐标图和点坐标,那么我们还把它们画出来,所以当然要设置画笔了。

步骤二、画出我们的view,这就要重写onDraw (MyPictureView 中)

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);

try {
if (canvas != null) {
// 背景图
canvas.drawBitmap(mFrlrBg, 0, 0, mPaint);
// 移动点
canvas.drawBitmap(mPoint, bmp_x, bmp_y, mPaint);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
}
// canvas.drawText("Liyulei", bmp_x + 2, bmp_y + 10, mPaint);

}

到这里,就能够显示我们自定义的View了。

步骤三、让移动点图片移动。大家很可能想到了,就是不断的重绘我们的view,也就是onDraw方法。

因为我们画点时用的是这个方法:canvas.drawBitmap(mPoint, bmp_x, bmp_y, mPaint);

只要改变坐标(bmp_x,bmp_y)。移动动点就画不同的地方了。

那么什么时候让它移动呢。当然是我们触摸屏幕时,获取x、y坐标。并调用this.invalidate();重绘我们的View。

这样不就可以移动了么。

public boolean onTouchEvent(MotionEvent event) {
bmp_x = event.getX();
bmp_y = event.getY();

this.invalidate();
return super.onTouchEvent(event);
}

扩展补充:

1、

为什么要自定义属性,及细体什么实现?

如果我自定义的这个view类定义在其他的包。引用的是当前包的资源图片。如果我们在MyPictureView 所在的包中引用资源,而且又把MyPictureView 所在的包

生成一个lib库。其它引用这个包时,就不能获取到图片。

这是我遇到的问题。那么我们通过自定义属性就能通过xml文件,随意更改图片。

细体实现:创建values/attrs.xml文件:

<?xml version="1.0" encoding="utf-8"?>

<resources>
<declare-styleable name="EQSoundEffect">
<attr name="displaycoordinates" format="reference"/>
<attr name="dispalypoint" format="reference"/>
<attr name="pointx" format="dimension"/>
<attr name="pointy" format="dimension"/>
</declare-styleable>
</resources>

描述我们要自定义的属性。让typedArray a = context.obtainStyledAttributes(attrs,R.styleable.EQSoundEffect);

能认出我们自定义的属性。如果我这xml给这些属性赋了值。那么typedArray a就能获取得到。

如何这xml里赋值?

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:foryou="http://schemas.android.com/apk/res/com.tokenwireless.tricycle.skindefault"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<com.liyulei.MyPictureView

android:id="@+id/fge_eq_seat_frlr"
android:layout_width="322dip"
android:layout_height="307dip"
android:layout_marginLeft="449dip"
android:layout_marginTop="77dip"
foryou:pointx="149dip"
foryou:pointy="113dip"
foryou:displaycoordinates="@drawable/fge_eq_seat_frlr"
foryou:dispalypoint="@drawable/fge_eq_seat_point"
/>

</RelativeLayout>

要注意的是这两个:

有了这个:

xmlns:foryou="http://schemas.android.com/apk/res/com.tokenwireless.tricycle.skindefault"

才能用我自己起的名:

foryou:pointx="149dip"
foryou:pointy="113dip"
foryou:displaycoordinates="@drawable/fge_eq_seat_frlr"
foryou:dispalypoint="@drawable/fge_eq_seat_point"

扩展补充:

2、想要让别人知道我们自定义的view发生了移动呢?

这里我们要参照:OnClickListener

到View源码看看它是什么做:

1>View中有个成员变量: protected OnClickListener mOnClickListener;

2> public interface OnClickListener {
/**
* Called when a view has been clicked.
*
* @param v The view that was clicked.
*/
void onClick(View v);
}

这View又声明了这个接口。

3>当我们setOnClickListener(listener)时,我们click就会调用我们实现的onClick(View v);

那么我们也可以这样做:

1,在MyPictureView声明一个接口:

public interface MyOnTouchListener {
void myOnTouchListener (int x, int y);
}
2.添加成员变量MyOnTouchListener mMyOnTouchListener = null;

3.在onTouchEvent时去调用MyOnTouchListener 的myOnTouchListener

if (myOnTouchListener != null){

myOnTouchListener .myOnTouchListener(x,y);

}

4.提供一个函数setMyOnTouchListener

public void setMyOnTouchListener(MyOnTouchListener l){

myOnTouchListener = l;

}

这样我们就实现了自己的一个监听器了。

这个就是就实现后的结果:


更多相关文章

  1. android关于内存溢出的异常
  2. Android属性动画之ObjectAnimator使用
  3. 【推荐收藏】2017年最新的分类Android项目源码免费一次性打包下
  4. TextView 的一些常见属性
  5. FrameLayout的android:layout_height属性设置为dimen文件中的参
  6. Android如何获取视频首帧图片
  7. android广告自动滚动并用picasso实现图片加载
  8. android百度地图自定义marker,使用网络图片
  9. Android(安卓)带进度的圆形进度条

随机推荐

  1. css基础知识-伪类选择器
  2. 散列-分离链接法(数据结构与算法分析-C语
  3. 常用的几种大数据架构剖析
  4. JavaScript基础
  5. 初识javascript与作用域
  6. phpv18-开发环境-20211220
  7. 函数类型和数据类型
  8. 函数类型和数据类型
  9. JS数据类型与函数
  10. rem+vw 布局的原理与 rem 的设置技巧