触控知识的简单实践

来源:互联网 发布:c语言行列互换 编辑:程序博客网 时间:2024/05/14 15:27

关于自定义控件知识点,目前还在进一步钻研中,现在先挂上这两天自己整的自定义View的简单应用。

案例:

   实现自定义控件内部触摸使得控件更随移动而移动
   控件外部的自定义空间rawx和rawy内部的触摸则使得控件小球不移动
  实现类似电脑触摸板两个焦点触摸的缩小放大



public class MainActivity extends Activity {
    

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

}



这里注意:主布局中加载的应该是自定义的控件如:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_marginLeft="@dimen/activity_horizontal_margin"
    android:layout_marginRight="@dimen/activity_vertical_margin"
    android:layout_marginTop="@dimen/werty"
    android:layout_marginBottom="@dimen/wertyio"
    android:id="@+id/container"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">
    
   <com.bwei.text_view.Cview.MyView
       android:id="@+id/view"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:background="#808080" />
    
</RelativeLayout>


那么根据自定义的控件属性就有了com.bwei.text_view.Cview下的类MyView:


package com.bwei.text_view.Cview;


import android.content.Context;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.Paint;

import android.util.AttributeSet;

import android.view.MotionEvent;

import android.widget.ImageView;

import android.widget.Toast;


/**

 * 自定义图片界面类对象 // 如果获取当前屏幕尺寸宽高可以直接通过event.getX()和event.getY()方法

 * @author hl

 */

public class MyView extends ImageView {

    private Paint p;

    private float rawy = 100; // 圆心横坐标

    private float rawx = 100; // 圆心纵坐标

    private float rawz = 90; // 半径


    public MyView(Context context, AttributeSet attrs, int defStyle) {

        super(context, attrs, defStyle);


    }


    public MyView(Context context, AttributeSet attrs) {

        super(context, attrs);

        // TODO Auto-generated constructor stub

    }


    public MyView(Context context) {

        super(context);

    }

    

    

    /**

     * 自定义View需要最少覆写onMeasure()和onDraw()两个方法

      *  在绘制控件方法ondraw()里,需要使用画笔类Paint和方法画布Canvas两个类对象

     */

    @Override

    protected void onDraw(Canvas canvas) {

        // TODO Auto-generated method stub

        super.onDraw(canvas);


        p = new Paint();

        p.setColor(Color.RED);

        canvas.drawCircle(rawx, rawy, rawz, p);


    }


    @Override

    public boolean onTouchEvent(MotionEvent event) {


        switch (event.getAction()) {

        case MotionEvent.ACTION_DOWN:

            Toast.makeText(getContext(), "已触摸", Toast.LENGTH_SHORT).show();

            invalidate();

            break;


        case MotionEvent.ACTION_UP:

            Toast.makeText(getContext(), "松开触摸", Toast.LENGTH_SHORT).show();

            invalidate();

            break;


        case MotionEvent.ACTION_MOVE:

            // 两点间距-->圆心距离触摸点的间距

            double sqrt = Math.sqrt((event.getX() - rawx)

                    * (event.getX() - rawx) + (event.getY() - rawy)

                    * (event.getY() - rawy));


            // 做球控件内部手指移动控件跟随移动的逻辑判断并加载动画

            if (sqrt <= rawz) {

                rawz=(float) sqrt;

                rawx = event.getX();

                rawy = event.getY();


                // 加载移动或者触摸的动画

//                Animation loadAnimation = AnimationUtils.loadAnimation( getContext(), R.anim.dh);

//                findViewById(R.id.view).startAnimation(loadAnimation);

                invalidate();

            }else{

                rawz=(float) sqrt;

                rawx = event.getX();

                rawy = event.getY();

            }

            


        }

        return true;


    }

    

    /**

     * onMeasure(),自定义控件所处视图大小将在这里最终确定,

     * 也就是说measure只是对onMeasure的一个包装,

     * 子类可以覆写onMeasure()方法实现自己的计算视图大小的方式

     * 并通过setMeasuredDimension(width, height)保存计算结果。

     */

    @Override

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        // TODO Auto-generated method stub

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);


        // 该方法测量的是自定义的控件所在的界面的尺寸,这里默认充满界面

        setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);

    }


}


以上使用的动画加载使用的是控制层与自定义文件中补间动画交互数据的方式,只需要在res文件下自定义一个文件anim,里面新建一个dh.xml,具体的动画内容很简单,网上到处都是,这里给出一个简单的模板:

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

<set  xmlns:android="http://schemas.android.com/apk/res/android">

    <alpha

        android:fromAlpha="0.1"

        android:toAlpha="1.0"

        android:fillAfter="true"

        android:duration="1000"

        android:repeatCount="1"

        android:repeatMode="reverse"

        />

    <rotate

        android:fromDegrees="0"

        android:toDegrees="3600"

        android:pivotX="50%"

        android:pivotY="50%"

        android:duration="1000"

        android:repeatCount="1"

        android:repeatMode="reverse"

        />

</set>



在使用自定义View绘制简单控件时,一定要注意三个构造函数内部的联系和传参,在加触摸事件时,里面的逻辑代码涉及到数学的知识,所以,还有一些数学运算在里头。以上图示就是就一个简单的自定义控件图片随手指触摸移动而移动,并且可以实现放大和缩小的效果。

如果在自定义控件时,涉及到控件属性时还要利用系统里的配置文件Values文件下的dimens文件中的引用,这个类似主布局中android:layout_marginLeft="@dimen/activity_horizontal_margin" 的引用,但是在应用过后,个人觉得还是不以交互的方式来设置属性,还是直接在自定义控件类MyView中的构造函数中设置更好,因为三个构造函数中正好就有传参AttributeSet attrs的构造函数,只需要在该方法中进行属性设置就可,不必通过系统配置文件来引用。


自定义控件远非以上案例那样简单,如果是复杂的布局和控件,还需要更加深入的钻研,很多方法都涉及到阅读底层代码,这就很考验阅读底层代码的能力了。


















1 0