編輯:關於Android編程
最近幫朋友做了一個動畫菜單,感覺有一定的實用價值,就在此給大家分享一下,先看看效果:源碼下載地址在末尾
實現思路:
從圖中可以看出,這三個(或更多,需要自己再實現)菜單是圍繞著中心點旋轉的,旋轉分為2層,背景旋轉和菜單旋轉,背景旋轉可以直接用旋轉動畫來實現;菜單的旋轉是在以中心點為圓心的圓環上,所以這裡用了根據旋轉角度求此點在直角坐標系中的坐標點的函數(x =r * cos(rotation* 3.14 / 180) 和y =r * sin(rotation* 3.14 / 180)),然後根據獲取到的點的位置來設置菜單的位置就能實現這種效果。由此可見 數學是很重要的 哈哈~~
有了思路我們就能用代碼來實現了:
1、首先自定義View繼承相對布局並重寫構造函數
/** * Created by ywl on 2016/8/7. */ public class CircleMenuLayout extends RelativeLayout { public CircleMenuLayout(Context context) { this(context, null); } public CircleMenuLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } /** * 初始化布局 把旋轉背景和中心點添加進去 * @param context * @param attrs * @param defStyleAttr */ public CircleMenuLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); this.context = context; layoutInflater = LayoutInflater.from(context); menuitems = new ArrayList構造函數中添加中心定位點和旋轉背景圖片,並設置合適的大小。(); centerview = new View(context);//中心點 centerview.setId(ID_CENTER_VIEW); LayoutParams lp = new LayoutParams(0, 0); lp.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE); addView(centerview, lp); //添加中心的 用於旋轉定位 progressBar = new ProgressBar(context);//旋轉的背景 LayoutParams lp2 = new LayoutParams(dip2px(context, 90), dip2px(context, 90)); lp2.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE); addView(progressBar, lp2); progressBar.setIndeterminateDrawable(context.getResources().getDrawable(R.mipmap.icon_circle_menu)); } }
2、根據傳入的圖片數組和菜單名字數組,生成菜單原始位置效果。
/** * 菜單的數量 和 半徑 名字 和圖片 這裡只為3個菜單做了適配 * @param size * @param center_distance */ public void initMenuItem(int size, int center_distance, String[] titles, int[] imgs) { radus = 360f / size; int width = dip2px(context, 50); //菜單寬度 int height = dip2px(context, 50);//菜單高度 for(int i = 0; i < size; i++) //循環添加布局 { int top = 0; int left = 0; top = -(int)(Math.sin(radus * i * 3.1415f / 180) * center_distance); //r * cos(ao * 3.14 /180 ) left = -(int)(Math.cos(radus * i * 3.1415f / 180) * center_distance); //計算位置點 LayoutParams lp = new LayoutParams(dip2px(context, 50), dip2px(context, 50)); View view = layoutInflater.inflate(R.layout.item_circle_menu, this, false); view.setTag(i); TextView tvname = (TextView) view.findViewById(R.id.tv_name); ImageView ivimg = (ImageView) view.findViewById(R.id.img); tvname.setText(titles[i]); ivimg.setImageResource(imgs[i]); view.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) {//根據點擊的區域 旋轉菜單 if(!isrun) { tag = (int) v.getTag(); currentPosition = tag; if(tag == 0) { finishdus = -360; } else if(tag == 1) { finishdus = -120; } else if(tag == 2) { finishdus = -240; } LayoutParams lp = (LayoutParams) v.getLayoutParams(); int l = lp.leftMargin; int t = lp.topMargin; if (t > -dip2px(context, 5) && l > -dip2px(context, 5)) { oldradus = 120f; isright = false; } else if (t > -dip2px(context, 5) && l < -dip2px(context, 5)) { oldradus = 120f; isright = true; } else if (t < -dip2px(context, 5)) { oldradus = 0f; } sub = 0; circleMenu(8, dip2px(context, 45), oldradus, isright); } } }); lp.addRule(RelativeLayout.BELOW, centerview.getId()); lp.addRule(RelativeLayout.RIGHT_OF, centerview.getId()); lp.setMargins(-width / 2 + top, -height / 2 + left, 0, 0); addView(view, lp); menuitems.add(view); } handler.postDelayed(runnable, 0); }
根據菜單的數量循環計算每個菜單的位置,然後在相應的位置添加相應的菜單就可以實現菜單的初始化了。這裡為每個菜單添加了點擊事件,但是只適配了3個菜單的情況,至於其他數量的菜單,可以自己來改或者寫一個通用的方法來計算點擊位置。
3、背景旋轉動畫:
/** * 根據度數來旋轉菜單 菜單中心都在一個圓上面 采用圓周運動來旋轉 * @param offserradius * @param center_distance * @param d * @param right */ public void circleMenu(float offserradius, int center_distance, float d, boolean right) { if(oldradus != 0) { progressBar.clearAnimation(); if(isright) { mRotateUpAnim = new RotateAnimation(bgdus, bgdus + 120, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); bgdus += 120; } else { mRotateUpAnim = new RotateAnimation(bgdus, bgdus - 120, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); bgdus -= 120; } lir = new LinearInterpolator(); mRotateUpAnim.setDuration(350); mRotateUpAnim.setFillAfter(true); mRotateUpAnim.setInterpolator(lir); // mRotateUpAnim.setRepeatCount(Animation.INFINITE); progressBar.startAnimation(mRotateUpAnim); } circleMenuItem(offserradius, center_distance, d, right); }這個比較簡單,就是根據旋轉的角度,啟用旋轉動畫。
4、旋轉菜單:
/** * 菜單旋轉 * @param offserradius * @param center_distance * @param d * @param right */ public void circleMenuItem(float offserradius, int center_distance, float d, boolean right) { sub += offserradius; if(sub > d) { if(onMenuItemSelectedListener != null) { onMenuItemSelectedListener.onMenuItemOnclick(tag); } isrun = false; return; } if(right) { offsetradus -= offserradius; } else { offsetradus += offserradius; } int size = menuitems.size(); int width = dip2px(context, 50); int height = dip2px(context, 50); for(int i = 0; i < size; i++) { if(Math.abs(sub - d) <= 8) { offsetradus = finishdus; } LayoutParams lp = (LayoutParams) menuitems.get(i).getLayoutParams(); float ds = radus * i + offsetradus; int top = -(int)(Math.sin(ds * 3.1415f / 180) * center_distance); //r * cos(ao * 3.14 /180 ) int left = -(int)(Math.cos(ds * 3.1415f / 180) * center_distance); lp.setMargins(-width / 2 + top, -height / 2 + left, 0, 0); menuitems.get(i).requestLayout(); } if(sub <= d) { isrun = true; offsetradus = offsetradus % 360; handler.postDelayed(runnable, 5); } else { if(onMenuItemSelectedListener != null) { onMenuItemSelectedListener.onMenuItemOnclick(tag); } isrun = false; } }這裡旋轉是根據初始化時每個菜單所在的位置來求的旋轉角度,然後啟動handler來動遞加或遞減角度來求響應的位置,就實現了動畫效果。
5、手動設置菜單項(有局限,沒有通用性):
/** * 設置旋轉到哪個菜單項 * @param tag */ public void setCurrentTag(int tag) { if(currentPosition == tag) { return; } if(tag == 0) { finishdus = -360; } else if(tag == 1) { finishdus = -120; } else if(tag == 2) { finishdus = -240; } if(currentPosition == 0) //當前是0 { if(tag == 1) { oldradus = 120f; isright = true; } else if(tag == 2) { oldradus = 120f; isright = false; } } else if(currentPosition == 1) { if(tag == 2) { oldradus = 120f; isright = true; } else if(tag == 0) { oldradus = 120f; isright = false; } } else if(currentPosition == 2) { if(tag == 0) { oldradus = 120f; isright = true; } else if(tag == 1) { oldradus = 120f; isright = false; } } currentPosition = tag; this.tag = tag; sub = 0; circleMenu(8, dip2px(context, 45), oldradus, isright); }
這樣就可以實現旋轉效果了。
6、調用方法:
(1)布局文件:
(2)菜單布局文件:
(3)Activity中調用
cmlmenu = (CircleMenuLayout) findViewById(R.id.cml_menu); btn = (Button) findViewById(R.id.btn); cmlmenu.initDatas(titles, imgs); cmlmenu.setOnMenuItemSelectedListener(new CircleMenuLayout.OnMenuItemSelectedListener() { @Override public void onMenuItemOnclick(int code) { if(code == 0)// { Toast.makeText(MainActivity.this, "支付寶", Toast.LENGTH_SHORT).show(); } else if(code == 1) { Toast.makeText(MainActivity.this, "銀聯", Toast.LENGTH_SHORT).show(); } else if(code == 2) { Toast.makeText(MainActivity.this, "微信", Toast.LENGTH_SHORT).show(); } } });OK,就完成了三個菜單旋轉效果(注:這裡僅僅是為了3個菜單而設計的,其他個數的自己還需要精簡或更改一些代碼,相信自己改出來的會更有收獲的~~)。
AndroidCircleMenu" target="_blank">Github:CircleMenu
目前幾乎所有的APP在用戶注冊時都會有設置頭像的需求,大致分為三種情況:(1)通過獲取本地相冊的圖片,經過裁剪後作為頭像。(2)通過啟動手機相機,現拍圖片然後裁剪作為頭像
剛剛接手一個備份系統浏覽器書簽的模塊,現在把代碼貼出來,另外有幾點疑問請路過的大神指教 1、根據官方api應該是有以下幾個字段是可以獲取的 但是除了
概述:Android事件構成:在Android中,事件主要包括點按、長按、拖拽、滑動等,點按又包括單擊和雙擊,另外還包括單指操作和多指操作。所有這些都構成了Android
前言:因為找了N多網上的資源都沒有好的解決方案,別人都是只給思路沒給具體源碼,真TMD糾結,干嘛求別人,自己動手才是真,最痛恨那些所謂大牛的作風,給了點點代碼就讓別人去想