Я могу объяснить шаги для легкого создания контекстного меню: -
Первый демонстрационный проект клона из этого Github Repo и следуйте приведенным ниже шагам.
Вы можете найти, CircleDragкласс используется для перетаскивания круга реализации.Этот класс содержит логику для взаимодействия с элементами меню и возврата обратного вызова в MainActivity с помощью интерфейса OnViewCrossed для перерисовки элементов меню.
Проверка MainActivity.java Сначала мы инициализируем класс CircleDrag.
private void initCircleDrag(){
final int radius = (int) getResources().getDimension(R.dimen._80sdp);
final CircleDrag circleDrag = new CircleDrag(this);
circleDrag.init(viewCircle, this, radius, indicatorViewList);}
Метод ниже используется для создания динамических пунктов меню.Просто передайте имя и значок пункта меню.
public void createMenuItem(String text, @DrawableRes int drawableId) {
textViewList.add(createTextView(relativeParent, text));
menuItemViewList.add(createMenuItem(rlCenterView, drawableId));
indicatorViewList.add(createMenuItem(rlCenterView, R.drawable.trans_circle));
DOTS_COUNT = textViewList.size();
}
Приведенный ниже метод используется для перемещения макета меню в положение касания.
public void setMenuItemsPosition(View parentView, View menuLayoutView, float x, float y) {
//p for parent
float pl, pr, pb, pt;
//c for child
float cl, cr, cb, ct;
int[] v1_coords = new int[2];
parentView.getLocationOnScreen(v1_coords);
pl = 0;
pr = parentView.getWidth();
pt = 0;
pb = parentView.getHeight();
cl = menuLayoutView.getX();
ct = menuLayoutView.getY();
cr = menuLayoutView.getWidth() + cl;
cb = menuLayoutView.getHeight() + ct;
if (cl < pl) {
if (ct < pt && cl < pl) {
setMenusPosition(Angle.LEFT_TOP);
} else if (cb > pb && cl < pl) {
setMenusPosition(Angle.LEFT_BOTTOM);
} else {
setMenusPosition(Angle.LEFT);
}
} else if (cr > pr) {
if (ct < pt && cr > pr) {
setMenusPosition(Angle.RIGHT_TOP);
} else if (cb > pb && cr > pr) {
setMenusPosition(Angle.RIGHT_BOTTOM);
} else {
setMenusPosition(Angle.RIGHT);
}
} else if (ct < pt) {
setMenusPosition(Angle.TOP);
} else if (cb > pb) {
setMenusPosition(Angle.BOTTOM);
} else {
setMenusPosition(Angle.CENTER);
}
}
Приведенный ниже метод используется для рисования круга пунктов меню наугол.Если касание пользователя в центральных пунктах меню происходит в круглой форме, если касание пользователя происходит по сторонам, то элементы меню рисуются в половине круга, а если пользователь касается любого угла экрана, то элементы меню рисуются в четвертой части круга.
private void setMenusPosition(Angle angle);
Ниже слушатель используется для показа контекстного меню при длительном нажатии.
relativeParent.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
return false;
}
});
final GestureDetector gestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
public void onLongPress(MotionEvent e) {
Log.e("GestureDetector", "Longpress detected");
if (setVisible) {
rlMenuView.setVisibility(View.VISIBLE);
rlTouchLayout.setBackgroundResource(R.color.menu_background);
isLongPressDetected = true;
}
}
});
Ниже слушатель используется для обнаружения касания и рисования пунктов меню вокруг точки касания.
relativeParent.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getX() >= getResources().getDimension(R.dimen._10sdp) && event.getX() <= relativeParent.getWidth() - getResources().getDimension(R.dimen._10sdp) &&
event.getY() >= getResources().getDimension(R.dimen._10sdp) && event.getY() <= relativeParent.getHeight() - getResources().getDimension(R.dimen._10sdp)) {
setVisible = true;
//pass touch event
viewCircle.dispatchTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
lastSelectedPosition = -1;
float centerX = event.getX() - rlMenuView.getWidth() / 2;
float centerY = event.getY() - rlMenuView.getHeight() / 2;
rlMenuView.setX(centerX);
rlMenuView.setY(centerY);
setMenuItemsPosition(relativeParent, rlMenuView, centerX, centerY);
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
if (lastSelectedPosition != -1) {
onMenuSelected(lastSelectedPosition, textViewList.get(lastSelectedPosition).getText().toString());
} else {
onNoMenuSelected();
}
setVisible = false;
setMenusPosition(Angle.CENTER);
rlMenuView.setVisibility(View.INVISIBLE);
rlTouchLayout.setBackgroundResource(R.color.tranparent);
hideTextViews();
break;
}
} else {
if (event.getAction() == MotionEvent.ACTION_UP) {
onNoMenuSelected();
setVisible = false;
setMenusPosition(Angle.CENTER);
rlMenuView.setVisibility(View.INVISIBLE);
rlTouchLayout.setBackgroundResource(R.color.tranparent);
hideTextViews();
}
}
return false;
}
});
Метод ниже используется для перерисовки пунктов меню и текста меню, когда элемент выбран или не выбран.
@Override
public void OnViewTouched(int flag) {
Log.d(TAG, "onSelect: ");
lastSelectedPosition = -1;
for (int i = 0; i < DOTS_COUNT; i++) {
if (flag == indicatorViewList.get(i).getId()) {
lastSelectedPosition = i;
if ((int) pos_center_view[0] > (int) indicatorViewList.get(i).getX()
&& (pos_center_view[0] - indicatorViewList.get(i).getX() > 4)) {
menuItemViewList.get(i).setX(indicatorViewList.get(i).getX() - getResources().getDimension(R.dimen._6sdp));
} else if ((int) pos_center_view[0] < (int) indicatorViewList.get(i).getX()
&& (indicatorViewList.get(i).getX() - pos_center_view[0] > 4)) {
menuItemViewList.get(i).setX(indicatorViewList.get(i).getX() + getResources().getDimension(R.dimen._6sdp));
} else {
menuItemViewList.get(i).setX(indicatorViewList.get(i).getX());
}
if ((int) pos_center_view[1] > (int) indicatorViewList.get(i).getY()
&& (pos_center_view[1] - indicatorViewList.get(i).getY() > 4)) {
menuItemViewList.get(i).setY(indicatorViewList.get(i).getY() - getResources().getDimension(R.dimen._6sdp));
} else if ((int) pos_center_view[1] < (int) indicatorViewList.get(i).getY()
&& (indicatorViewList.get(i).getY() - pos_center_view[1] > 4)) {
menuItemViewList.get(i).setY(indicatorViewList.get(i).getY() + getResources().getDimension(R.dimen._6sdp));
} else {
menuItemViewList.get(i).setY(indicatorViewList.get(i).getY());
}
textViewList.get(i).setVisibility(View.VISIBLE);
} else {
menuItemViewList.get(i).setX(indicatorViewList.get(i).getX());
menuItemViewList.get(i).setY(indicatorViewList.get(i).getY());
textViewList.get(i).setVisibility(View.INVISIBLE);
}
}
}
Ниже методы вызываются, когда элемент меню выбран или ничего не выбрано.
@Override
public void onMenuSelected(int position, String selectedText) {
tvResult.setText(String.format("Selected Item : %s", selectedText));
}
@Override
public void onNoMenuSelected() {
// TODO when no menu selected.....
tvResult.setText(String.format("Selected Item : %s", "None"));
}
Вот ссылка на GitHub для этой полной демонстрации.