Android自定义View之高仿卫星发散控件

来源:互联网 发布:梦幻西游手游秒抢软件 编辑:程序博客网 时间:2024/04/29 00:08

Android自定义View之高仿卫星发散控件

自定义viewGroup
本次主要以卫星控件为例
1、先在属性文件里面设置(attr.xml 在布局文件中使用、在自定义控件中进行读取)
   attr.xml 文件中设置要要自定义控件的属性
    <?xml version="1.0" encoding="utf-8"?>
<resources>
    <attr name="position">
        <enum name="left_top" value="0" />
        <enum name="left_bottom" value="1" />
        <enum name="right_top" value="2" />
        <enum name="right_bottom" value="3" />
    </attr>
    //格式尺寸,一般用dimension,以为半径大小一般都会用dp
    <attr name="radius" format="dimension" />
// 自定义view属性的使用,因为在这里我们得先创建一个自定义view,在文件中创建。。ArcMenu这个类,把名称添加到那么那里
    <declare-styleable name="ArcMenu">
        <attr name="position" />
        <attr name="radius" />
    </declare-styleable>
</resources>

    创建属性文件成功后:


2、在布局文件中引用控件
 <com.imooc.arcmenu.view.ArcMenu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:hyman="http://schemas.android.com/apk/res/com.imooc.arcmenu"
    android:id="@+id/id_menu"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginBottom="25dp"
    hyman:position="left_bottom"
    hyman:radius="140dp" >
    </com.imooc.arcmenu.view.ArcMenu>
    在这里可以直接使用属性文件中写下的属性例如   
    hyman:position="left_bottom"
    hyman:radius="140dp"
    也就是说hyman这个名字写成什么,在下面调用的时候就是直接用hyman进行属性的调用。。。。。。。。。。。。
    ********************特别注意点:   xmlns:hyman="http://schemas.android.com/apk/res/com.imooc.arcmenu"双引号里面的参数是你的自定义View所在的权限文件包路径
    当view从XML布局中创建了之后,XML标签中所有的属性都从资源包中读取出来并作为一个AttributeSet传递给view的构造函数
在布局中调用自定义view,用它的属性的时候,我们要添加命名空间  xmlns:hyman="http://schemas.android.com/apk/res/com.imooc.arcmenu",,,,hyman这个是命名空间的名字

3、自定义view的代码编写。

      3.1首先继承viewgroup,实现里面的方法onLayout,

      3.2重写它所有的构造方法,一个参数的,两个参数的,三个参数的,第一嗲用第二个,第二个调用第三个,第三个直接写。
                         // 为了防止我们的自定义view类被new出来,所以我们把构造方法都写出来
      3.3考虑有哪些成员变量,需要考虑那个按钮有点击和关闭,用到一个枚举类,还有那个按钮的点击事件。
                    /**
                    * 菜单的状态,点击和没点击状态下也用枚举类型
                    * 
                     */
                     public enum Status {
                     OPEN, CLOSE
                                                    }
                    /**
                    * 菜单的位置枚举类型4个值和我们xml文件中设置的4个值类似
                    * 
                    * @param context
                    */
                      public enum Position {
                      LEFT_TOP, LEFT_BOTTOM, RIGHT_TOP, RIGHT_BOTTOM
                      }
     3.4回调接口,用户对那个按钮设置回调事件。想想button就懂了
   // 接口回调重新复习一遍,点击子菜单项的回调接口
                           public interface OnMenuItemClickListener {
                            void onClick(View view, int pos);
                            }
                           // 这里我们可以想到一个button点击事件的时候setOnclickListener就是一个回调事件
                           public void setOnMenuItemClickListener(
                             OnMenuItemClickListener mMenuItemClickListener) {
                              this.mMenuItemClickListener = mMenuItemClickListener;
                              }
      3.4完事之后可以考虑在构造函数中添加初始化变量的值。自定义属性值的获取
                      // 自定义控件需要用到的类,给半径设置一个默认的值
                      mRadius = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                      100, getResources().getDisplayMetrics());
                     // 获取自定义属性的值
                     TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
                     R.styleable.ArcMenu, defStyle, 0);
                     // 获取位置属性
                     int pos = a.getInt(R.styleable.ArcMenu_position, POS_RIGHT_BOTTOM);
                     switch (pos) {
                             case POS_LEFT_TOP:
                             mPosition = Position.LEFT_TOP;
                     break;
                             case POS_LEFT_BOTTOM:
                             mPosition = Position.LEFT_BOTTOM;
                     break;
                             case POS_RIGHT_TOP:
                             mPosition = Position.RIGHT_TOP;
                     break;
                             case POS_RIGHT_BOTTOM:
                             mPosition = Position.RIGHT_BOTTOM;
                     break;
                                            }
                      mRadius = (int) a.getDimension(R.styleable.ArcMenu_radius, TypedValue
                      .applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100,
                      getResources().getDisplayMetrics()));

                      Log.e("TAG", "position = " + mPosition + " , radius =  " + mRadius);
                      a.recycle();

4、viewGroup一个测量模式,为我们的子view提供测量模式和他的测量值。onMeasure方法


         // 该方法是对子view测量的一个过程,这是测量所有view的值,getChildCount()获取view的总数量
                protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
                           int count = getChildCount();
                           for (int i = 0; i < count; i++) {
                              // 测量child,遍历里面的所有子view
                             measureChild(getChildAt(i), widthMeasureSpec, heightMeasureSpec);
                                                                       }
                            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
                                                                                                                                        }
   首先才布局中添加主按钮,按个中心加号,主按钮是我们那个com.imooc.arcmenu.view.ArcMenu布局里面的第一个控件,所以就是child(0)
5、对子view完成测量后执行Onlayout方法,这个方法完成以后才会在布局显示出来这个控件。
                   为子view设置layout布局,
                   Onlayout方法就是定位的方法,定位刚才那些测量好的view
2 0