我必须做这个布局:
我试图使用RelativeLayout和layout_toRightOf,layout_below等来对齐视图,但我实现的最好是:
这是xml:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" /> <RelativeLayout android:id="@+id/big" android:layout_width="150dp" android:layout_height="150dp" android:background="@drawable/circular" android:layout_margin="10dp" android:layout_centerInParent="true"/> <RelativeLayout android:id="@+id/right" android:layout_width="50dp" android:layout_height="50dp" android:background="@drawable/circular" android:layout_toRightOf="@+id/big" android:layout_centerVertical="true"/> <RelativeLayout android:id="@+id/left" android:layout_width="50dp" android:layout_height="50dp" android:background="@drawable/circular" android:layout_toLeftOf="@+id/big" android:layout_centerVertical="true"/> <RelativeLayout android:id="@+id/top" android:layout_width="50dp" android:layout_height="50dp" android:background="@drawable/circular" android:layout_above="@+id/big" android:layout_centerHorizontal="true"/> <RelativeLayout android:id="@+id/bottom" android:layout_width="50dp" android:layout_height="50dp" android:background="@drawable/circular" android:layout_below="@+id/big" android:layout_centerHorizontal="true"/> <RelativeLayout android:id="@+id/northeast" android:layout_width="50dp" android:layout_height="50dp" android:background="@drawable/circular" android:layout_toRightOf="@+id/big" android:layout_alignTop="@+id/top"/> <RelativeLayout android:id="@+id/northwest" android:layout_width="50dp" android:layout_height="50dp" android:background="@drawable/circular" android:layout_toLeftOf="@+id/big" android:layout_alignTop="@+id/top"/> <RelativeLayout android:id="@+id/southeast" android:layout_width="50dp" android:layout_height="50dp" android:background="@drawable/circular" android:layout_toRightOf="@+id/big" android:layout_below="@+id/big"/> <RelativeLayout android:id="@+id/southwest" android:layout_width="50dp" android:layout_height="50dp" android:background="@drawable/circular" android:layout_toLeftOf="@+id/big" android:layout_below="@+id/big"/> </RelativeLayout>
我试图避免在小圆圈上使用边距,因为与顶部/底部/右/左圆相比,对角圆必须与中心精确对齐.
我怎样才能做到这一点?
解决方法
我告诉你另一种方法.
import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.view.View; public class CircleMenu extends View { private Paint mainPaint; private Paint secondPaint; private Paint textPaint; private int radius_main =130; private int menuRadialButtonsCount =7; private int menuInnerPadding = 40; private int radialCircleRadius = 60; private int textPadding = 25; private double startAngle = - Math.PI/2f;; public CircleMenu(Context context) { super(context); } public CircleMenu(Context context,AttributeSet attrs) { super(context,attrs); } public CircleMenu(Context context,AttributeSet attrs,int defStyleAttr) { super(context,attrs,defStyleAttr); } @Override protected void onFinishInflate() { super.onFinishInflate(); mainPaint = new Paint(); mainPaint.setColor(Color.BLUE); secondPaint = new Paint(); secondPaint.setColor(Color.DKGRAY); textPaint = new Paint(); textPaint.setColor(Color.BLACK); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int centerX = canvas.getWidth()/2 ; int centerY= canvas.getHeight()/2; canvas.drawCircle(centerX,centerY,radius_main,mainPaint); for(int i=0;i<menuRadialButtonsCount;i++){ double angle =0; if(i==0){ angle = startAngle; }else{ angle = startAngle+(i * ((2 * Math.PI) / menuRadialButtonsCount)); } int x = (int) (centerX + Math.cos(angle)*(radius_main+menuInnerPadding+radialCircleRadius)); int y = (int) (centerY + Math.sin(angle)*(radius_main+menuInnerPadding+radialCircleRadius)); canvas.drawCircle(x,y,radialCircleRadius,secondPaint); float tW = textPaint.measureText("Text "+i); canvas.drawText("Text "+i,x-tW/2,y+radialCircleRadius+textPadding,textPaint); } } }
你可以扩展这个类,添加方法来设置资源的dimmensions,控制圆的数量,它们的大小,填充,onTouch,阴影,颜色….
<your.package.CircleMenu android:layout_width="match_parent" android:layout_height="match_parent"/>
更新版本:
import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import java.util.ArrayList; public class CircleMenu extends View { public static interface IMenuListener{ public void onMenuClick(MenuCircle item); } public static class MenuCircle{ private int x,radius; public int id; public String text; } private Paint mainPaint; private Paint secondPaint; private Paint textPaint; private int radius_main =130; private int menuInnerPadding = 40; private int radialCircleRadius = 60; private int textPadding = 25; private double startAngle = - Math.PI/2f; private ArrayList<MenuCircle> elements; private IMenuListener listener; public void setListener(IMenuListener listener){ this.listener = listener; } public void clear(){ elements.clear(); listener=null; } public CircleMenu(Context context) { super(context); init(); } public CircleMenu(Context context,attrs); init(); } public CircleMenu(Context context,defStyleAttr); init(); } private void init(){ elements = new ArrayList<>(); } public void addMenuItem(String text,int id){ MenuCircle item = new MenuCircle(); item.id = id; item.text=text; elements.add(item); } @Override protected void onFinishInflate() { super.onFinishInflate(); mainPaint = new Paint(); mainPaint.setColor(Color.BLUE); secondPaint = new Paint(); secondPaint.setColor(Color.DKGRAY); textPaint = new Paint(); textPaint.setColor(Color.BLACK); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int centerX = canvas.getWidth()/2 ; int centerY= canvas.getHeight()/2; canvas.drawCircle(centerX,mainPaint); for(int i=0;i<elements.size();i++){ double angle =0; if(i==0){ angle = startAngle; }else{ angle = startAngle+(i * ((2 * Math.PI) / elements.size())); } elements.get(i).x = (int) (centerX + Math.cos(angle)*(radius_main+menuInnerPadding+radialCircleRadius)); elements.get(i).y = (int) (centerY + Math.sin(angle)*(radius_main+menuInnerPadding+radialCircleRadius)); canvas.drawCircle( elements.get(i).x,elements.get(i).y,secondPaint); float tW = textPaint.measureText(elements.get(i).text); canvas.drawText(elements.get(i).text,elements.get(i).x-tW/2,elements.get(i).y+radialCircleRadius+textPadding,textPaint); } } @Override public boolean onTouchEvent(MotionEvent event) { if(event.getAction()==MotionEvent.ACTION_DOWN){ for(MenuCircle mc : elements){ double distance = Math.hypot(event.getX()-mc.x,event.getY()-mc.y); if(distance<= radialCircleRadius){ //touched if(listener!=null) listener.onMenuClick(mc); return true; } } } return super.onTouchEvent(event); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); } }
在片段中:
CircleMenu cm = (CircleMenu) view.findViewById(R.id.c_menu); cm.addMenuItem("one",1); cm.addMenuItem("two",2); cm.addMenuItem("three",3); cm.addMenuItem("ten",10); cm.addMenuItem("oh oh",156); cm.addMenuItem("exit",134); cm.setListener(new CircleMenu.IMenuListener() { @Override public void onMenuClick(CircleMenu.MenuCircle item) { Toast.makeText(getActivity(),item.text+" "+item.id,Toast.LENGTH_LONG).show(); } });