大佬教程收集整理的这篇文章主要介绍了Adapter模式实战之重构鸿洋集团的Android圆形菜单建行,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
@H_450_0@记得那是2014年的第一场雪,比以往时候来得稍晚一些。小民的同事洋叔是一位资深的研发人员,擅长写UI特效,在开发领域知名度颇高。最近洋叔刚发布了一个效果不错的圆形菜单,这个菜单的每个Item环形排布,并且可以转动。小民决定仿照洋叔的效果实现一遍,但是对于小民这个阶段来说只要实现环形布局就不错了,转动部分作为下个版本功能,就当作自定义view的练习了。 @H_450_0@在google了自定义view相关的知识点之后,小民就写好了这个圆形菜单布局视图,我们一步一步来讲解,代码如下:
// 圆形菜单 public class CircleMenuLayout extends ViewGroup { // 圆形直径 privatE int mRadius; // 该容器内child item的默认尺寸 private static final float RAdio_DEFAULT_CHILD_DIMENSION = 1 / 4f; // 该容器的内边距,无视padding属性,如需边距请用该变量 private static final float RAdio_PADDING_LAYOUT = 1 / 12f; // 该容器的内边距,无视padding属性,如需边距请用该变量 private float mPadding; // 布局时的开始角度 private double mStartAngle = 0; // 菜单项的文本 private String[] mItemTexts; // 菜单项的图标 privatE int[] mItemImgs; // 菜单的个数 privatE int mMenuItemCount; // 菜单布局资源id privatE int mMenuItemLayoutId = R.layout.circle_menu_item; // MenuItem的点击事件接口 private OnItemClickListener mOnMenuItemClickListener; public CircleMenuLayout(Context context,AttributeSet attrs) { super(context,attrs); // 无视padding setPadding(0,0); } // 设置菜单条目的图标和文本 public void setMenuItemIconsAndTexts(int[] images,String[] texts) { if (images == null && texts == null) { throw new IllegalArgumentexception("菜单项文本和图片至少设置其一"); } mItemImgs = images; mItemTexts = texts; // 初始化mMenuCount mMenuItemCount = images == null ? texts.length : images.length; if (images != null && texts != null) { mMenuItemCount = Math.min(images.length,texts.length); } // 构建菜单项 buildMenuItems(); } // 构建菜单项 private void buildMenuItems() { // 根据用户设置的参数,初始化menu item for (int i = 0; i < mMenuItemCount; i++) { View itemView = inflateMenuView(i); // 初始化菜单项 initMenuItem(itemView,i); // 添加view到容器中 addView(itemView); } } private View inflateMenuView(final int childIndeX) { LayoutInflater mInflater = LayoutInflater.from(getContext()); View itemView = mInflater.inflate(mMenuItemLayoutId,this,falsE); itemView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (mOnMenuItemClickListener != null) { mOnMenuItemClicklistener.onClick(v,childIndeX); } } }); return itemView; } private void initMenuItem(View itemView,int childIndeX) { ImageView iv = (ImageView) itemView .findViewById(R.id.id_circle_menu_item_imagE); TextView tv = (TextView) itemView .findViewById(R.id.id_circle_menu_item_text); iv.setVisibility(View.VISIBLE); iv.setImageresource(mItemImgs[childIndex]); tv.setVisibility(View.VISIBLE); tv.setText(mItemTexts[childIndex]); } // 设置MenuItem的布局文件,必须在setMenuItemIconsAndTexts之前调用 public void setMenuItemLayoutId(int mMenuItemLayoutId) { this.mMenuItemLayoutId = mMenuItemLayoutId; } // 设置MenuItem的点击事件接口 public void setOnItemClickListener(OnItemClickListener listener) { this.mOnMenuItemClickListener = listener; } // 代码省略 }
//设置布局的宽高,并策略menu item宽高 @Override protected void onMeasure(int widthMeasureSpec,int heightMeasureSpeC) { // 丈量自身尺寸 measureMyself(widthMeasureSpec,heightMeasureSpec); // 丈量菜单项尺寸 measureChildViews(); } private void measureMyself(int widthMeasureSpec,int heightMeasureSpeC) { int resWidth = 0; int resHeight = 0; // 根据传入的参数,分别获取测量模式和测量值 int width = MeasureSpec.getSize(widthMeasureSpec); int widthMode = MeasureSpec.getMode(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); // 如果宽或者高的测量模式非精确值 if (widthMode != MeasureSpec.EXACTLY || heightMode != MeasureSpec.EXACTLY) { // 主要设置为背景图的高度 resWidth = getSuggestedMinimumWidth(); // 如果未设置背景图片,则设置为屏幕宽高的默认值 resWidth = resWidth == 0 ? getDefaultWidth() : resWidth; resHeight = getSuggestedMinimumHeight(); // 如果未设置背景图片,则设置为屏幕宽高的默认值 resHeight = resHeight == 0 ? getDefaultWidth() : resHeight; } else { // 如果都设置为精确值,则直接取小值; resWidth = resHeight = Math.min(width,height); } setMeasuredDimension(resWidth,resHeight); } private void measureChildViews() { // 获得半径 mRadius = Math.max(getMeasuredWidth(),getMeasuredHeight()); // menu item数量 final int count = getChildCount(); // menu item尺寸 int childSize = (int) (mRadius * RAdio_DEFAULT_CHILD_DIMENSION); // menu item测量模式 int childMode = MeasureSpec.EXACTLY; // 迭代测量 for (int i = 0; i < count; i++) { final View child = getChildAt(i); if (child.getVisibility() == GONE) { conTinue; } // 计算menu item的尺寸;以及和设置好的模式,去对item进行测量 int makeMeasureSpec = -1; makeMeasureSpec = MeasureSpec.makeMeasureSpec(childSize,childModE); child.measure(makeMeasureSpec,makeMeasureSpec); } mPadding = RAdio_PADDING_LAYOUT * mRadius; }
// 布局menu item的位置 @Override protected void onLayout(Boolean changed,int l,int t,int r,int b) { final int childCount = getChildCount(); int left,top; // menu item 的尺寸 int itemWidth = (int) (mRadius * RAdio_DEFAULT_CHILD_DIMENSION); // 根据menu item的个数,计算item的布局占用的角度 float angleDelay = 360 / childCount; // 遍历所有菜单项设置它们的位置 for (int i = 0; i < childCount; i++) { final View child = getChildAt(i); if (child.getVisibility() == GONE) { conTinue; } // 菜单项的起始角度 mStartAngle %= 360; // 计算,中心点到menu item中心的距离 float distanceFromCenter = mRadius / 2f - itemWidth / 2 - mPadding; // distanceFromCenter cosa 即menu item中心点的left坐标 left = mRadius / 2 + (int)R_963_11845@ath.round(distanceFromCenter * Math.cos(Math.toradians(mStartAnglE)) * - 1 / 2f * itemWidth); // distanceFromCenter sina 即menu item的纵坐标 top = mRadius / 2 + (int) Math.round(distanceFromCenter * Math.sin( Math.toradians(mStartAnglE) ) * - 1 / 2f * itemWidth); // 布局child view child.layout(left,top,left + itemWidth,top + itemWidth); // 叠加尺寸 mStartAngle += angleDelay; } }
<LinearLayout xmlns:android="http://scheR_963_11845@as.android.com/apk/res/android" xmlns:tools="http://scheR_963_11845@as.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:BACkground="@drawable/bg" android:gravity="center" android:orientation="horizontal" > <com.dp.widgets.CircleMenuLayout xmlns:android="http://scheR_963_11845@as.android.com/apk/res/android" android:id="@+id/id_menulayout" android:layout_width="wrap_content" android:layout_height="wrap_content" android:BACkground="@drawable/circle_bg" /> </LinearLayout>
public class MainActivity extends Activity { private CircleMenuLayout mCircleMenuLayout; // 菜单标题 private String[] mItemTexts = new String[] { "安全中心 ","特色服务","投资理财","转账汇款","我的账户","信用卡" }; // 菜单图标 PrivatE int[] mItemImgs = new int[] { R.drawable.home_mbank_1_normal,R.drawable.home_mbank_2_normal,R.drawable.home_mbank_3_normal,R.drawable.home_mbank_4_normal,R.drawable.home_mbank_5_normal,R.drawable.home_mbank_6_normal }; @Override protected void onCreate(Bundle savedInstanceStatE) { super.onCreate(savedInstanceStatE); setContentView(R.layout.activity_main); // 初始化圆形菜单 mCircleMenuLayout = (CircleMenuLayout) findViewById(R.id.id_menulayout); // 设置菜单数据项 mCircleMenuLayout.setMenuItemIconsAndTexts(mItemImgs,mItemTexts); // 设置菜单项点击事件 mCircleMenuLayout.setOnItemClickListener(new OnItemClickListener() { @Override public void onClick(View view,int pos) { Toast.makeText(MainActivity.this,mItemTexts[pos],Toast.LENGTH_SHORT).show(); } }); } }
// 圆形菜单 public class CircleMenuLayout extends ViewGroup { // 字段省略 // 设置Adapter public void setAdapter(listadapter mAdapter) { this.mAdapter = mAdapter; } // 构建菜单项 private void buildMenuItems() { // 根据用户设置的参数,初始化menu item for (int i = 0; i < mAdapter.getCount(); i++) { final View itemView = mAdapter.getView(i,null,this); final int position = i; itemView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (mOnMenuItemClickListener != null) { mOnMenuItemClicklistener.onClick(itemView,position); } } }); // 添加view到容器中 addView(itemView); } } @Override protected void onAttachedToWindow() { if (mAdapter != null) { buildMenuItems(); } super.onAttachedToWindow(); } // 丈量、布局代码省略 }
static class MenuItem { public int imagEID; public String title; public MenuItem(String title,int resId) { this.title = title; imagEID = resId; } }
static class CircleMenuAdapter extends BaseAdapter { List<MenuItem> mMenuItems; public CircleMenuAdapter(List<MenuItem> menuItems) { mMenuItems = menuItems; } // 加载菜单项布局,并且初始化每个菜单 @Override public View getView(final int position,View convertView,ViewGroup parent) { LayoutInflater mInflater = LayoutInflater.from(parent.getContext()); View itemView = mInflater.inflate(R.layout.circle_menu_item,parent,falsE); initMenuItem(itemView,position); return itemView; } // 初始化菜单项 private void initMenuItem(View itemView,int position) { // 获取数据项 final MenuItem item = getItem(position); ImageView iv = (ImageView) itemView .findViewById(R.id.id_circle_menu_item_imagE); TextView tv = (TextView) itemView .findViewById(R.id.id_circle_menu_item_text); // 数据绑定 iv.setImageresource(item.imagEID); tv.setText(item.title); } // 省略获取item count等代码 }
public class MainActivity extends Activity { private ListView mListView; List<MenuItem> mMenuItems = new ArrayList<MenuItem>(); @Override protected void onCreate(Bundle savedInstanceStatE) { super.onCreate(savedInstanceStatE); setContentView(R.layout.activity_main); // 模拟数据 mockR_963_11845@enuItems(); mListView = (ListView) findViewById(R.id.id_menulayout); // 设置适配器 mListView.setAdapter(new CircleMenuAdapter(mMenuItems)); // 设置点击事件 mListView.setOnItemClickListener(new OnItemClickListener(){ @Override public void onItemClick(AdapterView<?> parent,View view,int position,long id) { Toast.makeText(MainActivity.this,mMenuItems.get(position).title,Toast.LENGTH_SHORT).show(); } }); }
以上是大佬教程为你收集整理的Adapter模式实战之重构鸿洋集团的Android圆形菜单建行全部内容,希望文章能够帮你解决Adapter模式实战之重构鸿洋集团的Android圆形菜单建行所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。