Android 自定义摇杆控件(使用图片)

效果图

1.找两张图片

 1)Joystick背景图片circle_1.png

 

2)Joystick图片circle_2.png

 

2.在layout中创建布局文件 imagejoystick.xml

内容为:

<?xml version="1.0"encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
             
android:orientation="vertical"
             
android:layout_width="match_parent"
             
android:layout_height="match_parent"
             
>

    <FrameLayout
           
android:layout_width="match_parent"
           
android:layout_height="match_parent"
           
>
        <ImageView
               
android:layout_width="wrap_content"
               
android:layout_height="wrap_content"
               
android:id="@+id/ivBackground"
                
android:layout_gravity="center"
               
android:src="@drawable/circle_1"/>
        <ImageView
               
android:layout_width="100dp"
               
android:layout_height="100dp"
               
android:id="@+id/ivJoystick"
                
android:src="@drawable/circle_2"
               
android:visibility="visible"
       
/>
    </FrameLayout>

 

效果如图:

 

3.在value文件夹中添加sttrs.xml文件,添加控件属性,内容为

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="JoystickView">//可以是自定义控件名也可以是其它的
        <attr name="backgroundDiameter" format="dimension"/>
        <attr name="joystickDiameter" format="dimension"/>
    </declare-styleable>
</resources>

format: reference 资源ID

            color   颜色

            boolean  布尔变量

           dimension 尺寸值

           float     浮点值

           integer       整形值

           string 字符串

            fraction 百分比

       enum枚举值

            flag  位或运算

          

4.在工程目录下添加自定义控件文件JoystickView

 

//JoystickView
package com.innovpower.uav.CustomView;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;

import com.innovpower.uav.R;

/**
 * Created by ${chenxi} on 2015/12/8.
 */
public class JoystickView extends LinearLayout {
    private View inflate;
    private int backgroundDiameter;
    private int joystickDiameter;
    private FrameLayout.LayoutParams layoutParams;
    private ImageView ivJoystick;
    private ImageView ivBackground;
    private JoyStickListener listener = null; // 事件回调接口

    public JoystickView(Context context) {
        super(context);
        inflate = LayoutInflater.from(context).inflate(R.layout.imagejoystick, this, true);
        ivJoystick = (ImageView) inflate.findViewById(R.id.ivJoystick);
        ivBackground = (ImageView) inflate.findViewById(R.id.ivBackground);

    }

    public JoystickView(Context context, AttributeSet attrs) {
        super(context, attrs);
        inflate = LayoutInflater.from(context).inflate(R.layout.imagejoystick, this, true);
        ivJoystick = (ImageView) inflate.findViewById(R.id.ivJoystick);
        ivBackground = (ImageView) inflate.findViewById(R.id.ivBackground);

        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.JoystickView); //与属性名称一致
        backgroundDiameter = (int) array.getDimension(R.styleable.JoystickView_backgroundDiameter, 40);//第一个是传递参数,第二个是默认值
        joystickDiameter = (int) array.getDimension(R.styleable.JoystickView_joystickDiameter, 40);



    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        initBackground(0, 0);
        layoutParams = (FrameLayout.LayoutParams) ivJoystick
                .getLayoutParams();
        layoutParams.height = joystickDiameter;
        layoutParams.width = joystickDiameter;
        ivJoystick.setLayoutParams(layoutParams);
        ivJoystick.setVisibility(INVISIBLE);
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int xOrigin = getWidth() / 2 - joystickDiameter / 2;
        int yOrigin = getHeight() / 2 - joystickDiameter / 2;
        int x_touch = (int) event.getX() - joystickDiameter / 2;
        int y_touch = (int) event.getY() - joystickDiameter / 2;
        int limit = backgroundDiameter / 2 - joystickDiameter / 2;

        if (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_MOVE) {
            ivJoystick.setVisibility(VISIBLE);
            //得到摇杆与触屏点所形成的角度
            double tempRad = getRad(xOrigin, yOrigin, x_touch, y_touch);
            if (Math.sqrt(Math.pow((xOrigin - x_touch), 2) + Math.pow((yOrigin - y_touch), 2)) >= limit) {
                //保证内部小圆运动的长度限制
                getXY(xOrigin, yOrigin, limit, tempRad);
            } else {//如果小球中心点小于活动区域则随着用户触屏点移动即可
                Stickmove(x_touch, y_touch);
            }
            if (listener!=null)
                listener.onSteeringWheelChanged(radToAngle(tempRad));
        } else if (event.getAction() == MotionEvent.ACTION_UP) {
            //当释放按键时摇杆要恢复摇杆的位置为初始位置
            Stickmove(xOrigin, yOrigin);
            ivJoystick.setVisibility(INVISIBLE);
        }

        return true;
    }
    private double radToAngle(double rad){
        return (180*rad)/Math.PI;
    }
    private void initBackground(int x, int y) {//将背景圆移动到中心
        FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) ivBackground
                .getLayoutParams();
        layoutParams.leftMargin = x;
        layoutParams.topMargin = y;
        layoutParams.width = backgroundDiameter;
        layoutParams.height = backgroundDiameter;
        ivBackground.setLayoutParams(layoutParams);
    }

    private void Stickmove(int x, int y) {
        layoutParams.leftMargin = x;
        layoutParams.topMargin = y;
        ivJoystick.setLayoutParams(layoutParams);
    }

    /***
     * 得到两点之间的弧度
     */
    private double getRad(float px1, float py1, float px2, float py2) {
        //得到两点X的距离
        float x = px2 - px1;
        //得到两点Y的距离
        float y = py1 - py2;
        //算出斜边长
        float xie = (float) Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
        //得到这个角度的余弦值(通过三角函数中的定理 :邻边/斜边=角度余弦值)
        float cosAngle = x / xie;
        //通过反余弦定理获取到其角度的弧度
        float rad = (float) Math.acos(cosAngle);
        //注意:当触屏的位置Y坐标<摇杆的Y坐标我们要取反值-0~-180
        if (py2 < py1) {
            rad = -rad;
        }


        return rad;
    }

    //函数:getXY
    //功能:限制joystick移动范围不得大于R
    //参数:centerX,centerY圆心的x,y
    //     rad触点与圆心形成的直线与水平线之间的夹角
    private void getXY(float centerX, float centerY, float R, double rad) {
        int x, y;
        //获取圆周运动的X坐标
        x = (int) ((float) (R * Math.cos(rad)) + centerX);
        //获取圆周运动的Y坐标
        y = (int) ((float) (R * Math.sin(rad)) + centerY);
        Stickmove(x, y);
/*        if (listener!=null)
        listener.onSteeringWheelChanged(x,y);*/
    }

    // 设置回调接口
    public void setJoystickListener(JoyStickListener rockerListener)
    {
        listener = rockerListener;
    }
    // 回调接口
    public interface JoyStickListener
    {
        void onSteeringWheelChanged(double angle);
    }

}

 

5.在布局中调用控件

 

<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:tools="http://schemas.android.com/tools"

    xmlns:my_attrs="http://schemas.android.com/apk/res-auto"

eclipse/IDEA : xmlns:custom="http://schemas.android.com/apk/res/com.XXX"

   android:layout_width="match_parent"

   android:layout_height="match_parent"

   android:paddingLeft="@dimen/activity_horizontal_margin"

   android:paddingRight="@dimen/activity_horizontal_margin"

   android:paddingTop="@dimen/activity_vertical_margin"

   android:paddingBottom="@dimen/activity_vertical_margin"

    tools:context=".MainActivity">

 

    <TextViewandroid:text="@string/hello_world"android:layout_width="wrap_content"

       android:layout_height="wrap_content" />

 

   <com.demo.chenxi.joystickdemo.CustomView.JoystickView

        android:layout_width="300dp"

        android:layout_height="300dp"

       my_attrs:backgroundDiameter="200dp"

       my_attrs:joystickDiameter="100dp"

        >

 

       </com.demo.chenxi.joystickdemo.CustomView.JoystickView>

</RelativeLayout>

6.在mainacitivity中调用控件事件

publicclass MainActivity extends Activity {

    private JoystickView joystick;

    @Override

    protected void onCreate(BundlesavedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        joystick=(JoystickView)findViewById(R.id.myJoystick);

        joystick.setJoystickListener(newJoystickView.JoyStickListener() {

            @Override

            public voidonSteeringWheelChanged(int angle) {

                Log.i("chenxi","angle:" + angle);

            }

        });

    }

工程下载地址:

http://download.csdn.net/detail/cx415462822/9660342

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值