android 自定义view实现图形移动

来源:互联网 发布:高桥美玲知乎 编辑:程序博客网 时间:2024/06/05 09:35

 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;

    }

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

 

 

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