Android实现卫星菜单(一)自定义属性及重写onMeasure、onLayout方法
2016-06-18 21:45
666 查看
自定义ViewGroup
1.自定义属性
a、attr.xml
b、在布局文件中使用
c、在自定义控件中读取
res的values下新建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>
<attr name="radius" format="dimension"/>
<declare-styleable name="ArcMenu">
<attr name="position"/>
<attr name="radius"/>
</declare-styleable>
</resources>
ArcMenu.java
public class ArcMenu extends ViewGroup {
private static final int POS_LEFT_TOP = 0;
private static final int POS_LEFT_BOTTOM = 1;
private static final int POS_RIGHT_TOP = 2;
private static final int POS_RIGHT_BOTTOM = 3;
private Position mPosition = Position.RIGHT_BOTTOM;
private int mRadius;
// 菜单的状态 打开或关闭
private Status mCurrentStatus = Status.CLOSE;
// 菜单的主按钮
private View mCButton;
private OnMenuItemClickListener mMenuItemClickListener;
public enum Status {
OPEN, CLOSE
}
/**
* 菜单的位置枚举类
*/
public enum Position {
LEFT_TOP, LEFT_BOTTOM, RIGHT_TOP, RIGHT_BOTTOM
}
/**
* 点击子菜单项的回调接口
*/
public interface OnMenuItemClickListener {
void onClick(View view, int pos);
}
public void setOnMenuItemClickListener(OnMenuItemClickListener mMenuItemClickListener) {
this.mMenuItemClickListener = mMenuItemClickListener;
}
public ArcMenu(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ArcMenu(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mRadius = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100,
getResources().getDisplayMetrics());
// 获取自定义属性
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.ArcMenu,
defStyleAttr, 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.i("TAG", "position = " + mPosition + ", radius = " + mRadius);
a.recycle();
}
public ArcMenu(Context context) {
this(context, null);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
}
}
activity_main
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:lin="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.arcmenu.view.ArcMenu
android:layout_width="match_parent"
android:layout_height="match_parent"
lin:position="right_bottom"
lin:radius="100dp">
</com.example.arcmenu.view.ArcMenu>
<com.example.arcmenu.view.ArcMenu
android:layout_width="match_parent"
android:layout_height="match_parent"
lin:position="left_top"
lin:radius="130dp">
</com.example.arcmenu.view.ArcMenu>
</RelativeLayout>
转化成px输出了
https://github.com/daCapricorn/ArcMenu/tree/master/sample/res/drawable 这里有一些图片素材
主按钮由两张图片拼成
activity_main
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:lin="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.arcmenu.view.ArcMenu
android:layout_width="match_parent"
android:layout_height="match_parent"
lin:position="right_bottom"
lin:radius="100dp">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/composer_button">
<ImageView
android:id="@+id/id_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@drawable/composer_icn_plus"/>
</RelativeLayout>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/composer_music"
android:tag="Music"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/composer_place"
android:tag="Place"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/composer_sleep"
android:tag="Sleep"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/composer_thought"
android:tag="Sun"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/composer_with"
android:tag="People"/>
</com.example.arcmenu.view.ArcMenu>
</RelativeLayout>
2.onMeasure
3.onLayout
MainActivity中添加
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int count = getChildCount();
for (int i = 0; i < count; i++) {
// 测量child
measureChild(getChildAt(i), widthMeasureSpec, heightMeasureSpec);
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if (changed) {
layoutCButton();
}
}
/**
* 定位主菜单按钮
*/
private void layoutCButton() {
mCButton = getChildAt(0);
mCButton.setOnClickListener(this);
int l = 0;
int t = 0;
int width = mCButton.getMeasuredWidth();
int height = mCButton.getMeasuredHeight();
switch (mPosition) {
case LEFT_TOP:
l = 0;
t = 0;
break;
case LEFT_BOTTOM:
l = 0;
// 纵轴 控件的高度减去按钮的高度,让其显示在最下面
t = getMeasuredHeight() - height;
break;
case RIGHT_TOP:
l = getMeasuredWidth() - width;
t = 0;
break;
case RIGHT_BOTTOM:
l = getMeasuredWidth() - width;
t = getMeasuredHeight() - height;
break;
}
// 定位
mCButton.layout(l, t, l + width, t + width);
}
效果
1.自定义属性
a、attr.xml
b、在布局文件中使用
c、在自定义控件中读取
res的values下新建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>
<attr name="radius" format="dimension"/>
<declare-styleable name="ArcMenu">
<attr name="position"/>
<attr name="radius"/>
</declare-styleable>
</resources>
ArcMenu.java
public class ArcMenu extends ViewGroup {
private static final int POS_LEFT_TOP = 0;
private static final int POS_LEFT_BOTTOM = 1;
private static final int POS_RIGHT_TOP = 2;
private static final int POS_RIGHT_BOTTOM = 3;
private Position mPosition = Position.RIGHT_BOTTOM;
private int mRadius;
// 菜单的状态 打开或关闭
private Status mCurrentStatus = Status.CLOSE;
// 菜单的主按钮
private View mCButton;
private OnMenuItemClickListener mMenuItemClickListener;
public enum Status {
OPEN, CLOSE
}
/**
* 菜单的位置枚举类
*/
public enum Position {
LEFT_TOP, LEFT_BOTTOM, RIGHT_TOP, RIGHT_BOTTOM
}
/**
* 点击子菜单项的回调接口
*/
public interface OnMenuItemClickListener {
void onClick(View view, int pos);
}
public void setOnMenuItemClickListener(OnMenuItemClickListener mMenuItemClickListener) {
this.mMenuItemClickListener = mMenuItemClickListener;
}
public ArcMenu(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ArcMenu(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mRadius = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100,
getResources().getDisplayMetrics());
// 获取自定义属性
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.ArcMenu,
defStyleAttr, 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.i("TAG", "position = " + mPosition + ", radius = " + mRadius);
a.recycle();
}
public ArcMenu(Context context) {
this(context, null);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
}
}
activity_main
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:lin="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.arcmenu.view.ArcMenu
android:layout_width="match_parent"
android:layout_height="match_parent"
lin:position="right_bottom"
lin:radius="100dp">
</com.example.arcmenu.view.ArcMenu>
<com.example.arcmenu.view.ArcMenu
android:layout_width="match_parent"
android:layout_height="match_parent"
lin:position="left_top"
lin:radius="130dp">
</com.example.arcmenu.view.ArcMenu>
</RelativeLayout>
转化成px输出了
https://github.com/daCapricorn/ArcMenu/tree/master/sample/res/drawable 这里有一些图片素材
主按钮由两张图片拼成
activity_main
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:lin="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.arcmenu.view.ArcMenu
android:layout_width="match_parent"
android:layout_height="match_parent"
lin:position="right_bottom"
lin:radius="100dp">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/composer_button">
<ImageView
android:id="@+id/id_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@drawable/composer_icn_plus"/>
</RelativeLayout>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/composer_music"
android:tag="Music"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/composer_place"
android:tag="Place"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/composer_sleep"
android:tag="Sleep"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/composer_thought"
android:tag="Sun"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/composer_with"
android:tag="People"/>
</com.example.arcmenu.view.ArcMenu>
</RelativeLayout>
2.onMeasure
3.onLayout
MainActivity中添加
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int count = getChildCount();
for (int i = 0; i < count; i++) {
// 测量child
measureChild(getChildAt(i), widthMeasureSpec, heightMeasureSpec);
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if (changed) {
layoutCButton();
}
}
/**
* 定位主菜单按钮
*/
private void layoutCButton() {
mCButton = getChildAt(0);
mCButton.setOnClickListener(this);
int l = 0;
int t = 0;
int width = mCButton.getMeasuredWidth();
int height = mCButton.getMeasuredHeight();
switch (mPosition) {
case LEFT_TOP:
l = 0;
t = 0;
break;
case LEFT_BOTTOM:
l = 0;
// 纵轴 控件的高度减去按钮的高度,让其显示在最下面
t = getMeasuredHeight() - height;
break;
case RIGHT_TOP:
l = getMeasuredWidth() - width;
t = 0;
break;
case RIGHT_BOTTOM:
l = getMeasuredWidth() - width;
t = getMeasuredHeight() - height;
break;
}
// 定位
mCButton.layout(l, t, l + width, t + width);
}
效果
相关文章推荐
- Android 采用get方式提交数据到服务器
- Android创建前台运行的Service
- [Android] LayoutInflater 详解
- 一步步追踪Android输入事件(二)
- Android中ListView的使用(三)----- 提升ListView运行效率
- 解决报错问题 Error inflating class android.support.design.widget.NavigationView
- Android中ListView的使用(二)----- 定制ListView的界面
- 安卓里RecyclerView的拖拽滑动列表
- 仿小米联系人
- android 广播(二)
- android五中方式调用服务service中的方法
- Android Studio
- Android 5.0中设置全屏无标题
- Android 中获取当前的 Activity
- [Android]Android之解析zip
- android实现文件的断点上传
- Android 通过DownloadManager实现自动更新的demo
- Android中ListView的使用(一)----- 简单填充数据
- Android初级教程进程间的通信AIDL
- Android初级教程进程间的通信AIDL