我制作了一个名为Activity
的{{1}},我想添加一个水平Accounts
。这可能看起来像剪切,复制和粘贴选项。有没有办法在列表项上添加这个水平自定义菜单ContextMenu
?
这是我到目前为止所得到的。
onLongClick
目前的UI看起来像这样。
答案 0 :(得分:4)
我认为你需要的是PopupWindow
。它更容易实现,并具有自定义布局设置选项。 PopupWindow
可以根据需要设置在自定义位置,并且实现您正在考虑的示例复制/粘贴UI的想法也可以通过PopupWindow
的实现来提供。
如果您希望使用PopupWindow
实现您的情况而不是使用上下文菜单实现它,我发现this answer非常有用。
在上面提到的并且提供了相似的答案中,PopupWindow
只有TextView
。您可以实现任何自定义/复杂UI,而不是像其中显示的那样简单TextView
。
我希望有所帮助。
更新
正如评论中所述,获取PopupWindow
位置的位置也可以动态设置。我指的是另一个链接,因此您也可以从那里检查实现。
Here's the implementation在列表中使用PopupWindow
。
答案 1 :(得分:4)
只需通过 QuickAction 库即可实现。
https://github.com/piruin/quickaction
https://github.com/lorensiuswlt/NewQuickAction
希望这会对你有所帮助!!
答案 2 :(得分:0)
我使用Dialog来实现这一目标,仍在寻找标准方法。请发布更好的方法。
Test.java
public void showOptionMenu(View view) {
int x1 = (int) view.getX();
int y1 = (int) view.getY();
LayoutInflater inflater = LayoutInflater.from(MainActivity.this);
View v = inflater.inflate(R.layout.popup_window , null);
Dialog dialog = new Dialog(MainActivity.this);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
WindowManager.LayoutParams wmlp = dialog.getWindow().getAttributes();
wmlp.gravity = Gravity.TOP | Gravity.LEFT;
wmlp.x = x1; //x position
wmlp.y = y1; //y position
dialog.setContentView(v);
dialog.show();
}
<强> activity_main.xml中强>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.shiva.testacitivity.MainActivity">
<Button
android:text="Show Options"
android:onClick="showOptionMenu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"/>
</LinearLayout>
<强> popup_windows.xml 强>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:background="#ECEFF1"
android:padding="5dp"
android:gravity="center"
android:orientation="horizontal">
<TextView
android:id="@+id/edit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/edit"
android:layout_gravity="center"
android:gravity="center"
android:textColor="#000"
android:text="Edit" />
<View
android:layout_width="1dp"
android:layout_height="match_parent"/>
<TextView
android:id="@+id/delete"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:drawableLeft="@drawable/delete"
android:text="Delete"
android:textColor="#000" />
</LinearLayout>
结果
答案 3 :(得分:0)
所以,几年前我写了下面的代码。您需要首先创建两个类PopUp
,其次是TringleView
。
弹出窗口: - 创建对话框并打开到您的视图附近(您想要的位置) 打开对话框)。 您可以更改弹出式bg颜色。
TringleView: - 制作tringle视图,或者你可以说尖箭头。你可以改变尖头箭头bg颜色。
View contentView = ((FragmentActivity)v.getContext()).getLayoutInflater().inflate(R.layout.edit_delete_layout,getAttachedRecyclerView(),false);
// this view denote where you click or you want to open dialog near
PopUp.showPopupOnView(((FragmentActivity) v.getContext()).getSupportFragmentManager(),contentView,view,false);
<强> PopUp.class 强>
public class PopUp extends DialogFragment {
protected int targetX;
protected int targetY;
protected int targetWidth;
protected int targetHeight;
protected Bitmap targetViewImage;
protected View contentView;
private SmartWorksPopUpViewHolder fragmentViewHolder;
private static int bgDrawable = R.drawable.round_corner_white_bg;
protected static int ONE_DIP;
private static int arrowBgColor = R.color.border_color;
private static int arrowWidthMultiple = 25;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (ONE_DIP == 0) {
ONE_DIP = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 1, getResources()
.getDisplayMetrics());
}
setStyle(DialogFragment.STYLE_NO_TITLE, android.R.style.Theme_Translucent);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
AbsoluteLayout parent = new AbsoluteLayout(getActivity());
parent.setId(R.id.parentLayout);
return parent;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
this.fragmentViewHolder = createViewHolder(view);
bindView(fragmentViewHolder);
}
protected SmartWorksPopUpViewHolder createViewHolder(
View fragmentView) {
return new SmartWorksPopUpViewHolder(fragmentView, contentView);
}
private void bindView(SmartWorksPopUpViewHolder vh) {
if (fragmentViewHolder != null) {
setupTargetDummyView(vh);
boolean showOnTop = shouldShowOnTop();
setupArrow(vh, showOnTop);
setupContent(vh, showOnTop);
}
}
protected void setupContent(SmartWorksPopUpViewHolder vh, boolean showOnTop) {
final int y;
AbsoluteLayout.LayoutParams arrowParams = (android.widget.AbsoluteLayout.LayoutParams) vh.arrow
.getLayoutParams();
int measureHeight = View.MeasureSpec.makeMeasureSpec(
ViewGroup.LayoutParams.WRAP_CONTENT, View.MeasureSpec.UNSPECIFIED);
int measureWidth = View.MeasureSpec.makeMeasureSpec(
getActivity().getWindow().getDecorView().getWidth(), View.MeasureSpec.EXACTLY);
vh.popupView.measure(measureWidth, measureHeight);
if (showOnTop) {
y = this.targetY - vh.popupView.getMeasuredHeight() + ONE_DIP;
} else {
y = arrowParams.y + arrowParams.height - ONE_DIP * 2;
}
updateAbsoluteLayoutParams(
getActivity().getResources().getDimensionPixelOffset(R.dimen.sixty_dp),
y,
getActivity().getWindow().getDecorView().getWidth() -
getActivity().getResources().getDimensionPixelOffset(R.dimen.seventy_dp),
ViewGroup.LayoutParams.WRAP_CONTENT, vh.popupView);
vh.parent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
exit();
}
});
}
private void setupArrow(SmartWorksPopUpViewHolder vh, boolean showOnTop) {
final int arrowHeight = 15 * ONE_DIP;
final int arrowWidth = arrowWidthMultiple * ONE_DIP;
vh.arrow.setDirectionAndColor(showOnTop ? "down" : "top", vh.popupView.getContext().getResources().getColor(arrowBgColor));
final int x = (int) (targetX + targetWidth / 3 - arrowWidth / 2);
final int y = targetY + (showOnTop ? -arrowHeight : targetHeight);
updateAbsoluteLayoutParams(x, y, arrowWidth, arrowHeight, vh.arrow);
}
private void setupTargetDummyView(SmartWorksPopUpViewHolder vh) {
vh.targetViewDummy.setImageBitmap(targetViewImage);
updateAbsoluteLayoutParams(targetX, targetY, targetWidth, targetHeight, vh.targetViewDummy);
}
protected void updateAbsoluteLayoutParams(int x, int y, int width, int height, View view) {
AbsoluteLayout.LayoutParams layoutParams =
(android.widget.AbsoluteLayout.LayoutParams) view.getLayoutParams();
layoutParams.x = x;
layoutParams.y = y;
layoutParams.height = height;
layoutParams.width = width;
view.setLayoutParams(layoutParams);
}
private boolean shouldShowOnTop() {
int windowHeight = getActivity().getWindow().getDecorView().getHeight();
int windowMid = windowHeight / 4;
return targetY > windowMid;
}
@Override
public void onDestroyView() {
this.fragmentViewHolder = null;
super.onDestroyView();
}
protected static class SmartWorksPopUpViewHolder {
protected AbsoluteLayout parent;
protected View popupView;
protected TringleView arrow;
protected AppCompatImageView targetViewDummy;
protected SmartWorksPopUpViewHolder(View fragmentView, View content) {
this.parent = (AbsoluteLayout) fragmentView;
final Context mContext = fragmentView.getContext();
this.popupView = content;
this.arrow = new TringleView(mContext);
this.targetViewDummy = new SmartWorksAppCompactImageView(mContext);
this.parent.addView(popupView);
this.parent.addView(arrow);
this.parent.addView(targetViewDummy);
this.parent.setBackgroundColor(0x00000000);
content.setBackgroundResource(bgDrawable);
}
}
public static PopUp showPopupOnView(FragmentManager fm, View contentView, View targetView, boolean showTargetView) {
int[] location = new int[2];
targetView.getLocationInWindow(location);
PopUp fragment = new PopUp();
fragment.targetX = location[0];
fragment.targetY = (int) (location[1] - TypedValue
.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 25,
targetView.getResources().getDisplayMetrics()));
fragment.targetWidth = targetView.getMeasuredWidth();
fragment.targetHeight = targetView.getMeasuredHeight();
fragment.contentView = contentView;
fragment.show(fm, "offer");
return fragment;
}
public void exit() {
dismiss();
}
public static void setArrowBackgroundColor(int color) {
arrowBgColor = color;
}
public static void setArrowWidthMultiple(int arrowWidth) {
arrowWidthMultiple = arrowWidth;
}
}
<强> TringleView.class 强>
public class TringleView extends View {
private String direction;
private int color;
public TringleView(Context context) {
super(context);
setDirectionAndColor("right", Color.RED);
}
public TringleView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setDirectionAndColor(attrs.getAttributeValue(null, "direction"), Color.RED);
}
public TringleView(Context context, AttributeSet attrs) {
super(context, attrs);
setDirectionAndColor(attrs.getAttributeValue(null, "direction"), Color.RED);
}
public void setDirectionAndColor(String direction, int color) {
if (direction != null && !direction.equals(this.direction) || this.color != color) {
createTriangleDrawable(direction, color);
}
}
private void createTriangleDrawable(String string, int color) {
int width = MeasureSpec.makeMeasureSpec(30, MeasureSpec.UNSPECIFIED);
int height = MeasureSpec.makeMeasureSpec(20, MeasureSpec.UNSPECIFIED);
Path path = new Path();
if (string == null) {
string = "right";
}
if (string.equals("top")) {
path.moveTo(0, height);
path.lineTo(width / 2, 0);
path.lineTo(width, height);
} else if (string.equals("left")) {
path.moveTo(width, 0);
path.lineTo(0, height / 2);
path.lineTo(width, height);
} else if (string.equals("right")) {
path.moveTo(0, 0);
path.lineTo(width, height / 2);
path.lineTo(0, height);
} else if (string.equals("down")) {
path.moveTo(0, 0);
path.lineTo(width / 2, height);
path.lineTo(width, 0);
}
path.close();
ShapeDrawable shapeDrawable = new ShapeDrawable(new PathShape(path, width, height));
shapeDrawable.getPaint().setColor(color);
setBackground(shapeDrawable);
this.color = color;
this.direction = string;
}
}
<强> edit_delete_layout.xml 强>
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
app:cardCornerRadius="@dimen/five_dp"
android:layout_margin="@dimen/ten_dp"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<LinearLayout
app:layout_behavior="android.support.design.widget.BottomSheetBehavior"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="5"
android:gravity="center"
android:orientation="horizontal"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<sis.com.smartworks.widget.SmartWorksTextView
android:id="@+id/share"
android:textSize="@dimen/smallest_text_size"
android:textColor="@color/black"
android:visibility="visible"
android:gravity="center"
android:paddingRight="@dimen/four_dp"
android:paddingLeft="@dimen/four_dp"
android:paddingTop="@dimen/ten_dp"
android:paddingBottom="@dimen/ten_dp"
android:text="Share"
android:layout_weight="1"
android:textStyle="bold"
android:layout_width="0dp"
android:layout_height="wrap_content" />
<View
android:layout_width="1dp"
android:background="@color/grey_unselect"
android:layout_height="match_parent" />
<sis.com.smartworks.widget.SmartWorksTextView
android:id="@+id/reportSpam"
android:textSize="@dimen/smallest_text_size"
android:textColor="@color/black"
android:visibility="visible"
android:gravity="center"
android:paddingRight="@dimen/four_dp"
android:paddingLeft="@dimen/four_dp"
android:paddingTop="@dimen/ten_dp"
android:paddingBottom="@dimen/ten_dp"
android:text="Spam"
android:layout_weight="1"
android:textStyle="bold"
android:layout_width="0dp"
android:layout_height="wrap_content" />
<View
android:layout_width="1dp"
android:background="@color/grey_unselect"
android:layout_height="match_parent" />
<!--<View-->
<!--android:layout_width="match_parent"-->
<!--android:layout_marginLeft="@dimen/three_dp"-->
<!--android:layout_marginRight="@dimen/three_dp"-->
<!--android:background="@color/white"-->
<!--android:layout_height="@dimen/one_dp" />-->
<sis.com.smartworks.widget.SmartWorksTextView
android:id="@+id/edit"
android:textSize="@dimen/smallest_text_size"
android:textColor="@color/black"
android:gravity="center"
android:paddingRight="@dimen/four_dp"
android:paddingLeft="@dimen/four_dp"
android:paddingTop="@dimen/ten_dp"
android:paddingBottom="@dimen/ten_dp"
app:swFontName="robotoNormal"
android:layout_weight="1"
android:text="@string/edit"
android:textStyle="bold"
android:layout_width="0dp"
android:layout_height="wrap_content" />
<View
android:layout_width="1dp"
android:background="@color/grey_unselect"
android:layout_height="match_parent" />
<!--<View-->
<!--android:layout_width="match_parent"-->
<!--android:layout_marginLeft="@dimen/three_dp"-->
<!--android:layout_marginRight="@dimen/three_dp"-->
<!--android:background="@color/white"-->
<!--android:layout_height="@dimen/one_dp" />-->
<sis.com.smartworks.widget.SmartWorksTextView
android:id="@+id/delete"
android:textSize="@dimen/smallest_text_size"
android:textColor="@color/black"
android:gravity="center"
android:paddingRight="@dimen/four_dp"
android:paddingLeft="@dimen/four_dp"
android:paddingTop="@dimen/ten_dp"
android:paddingBottom="@dimen/ten_dp" android:layout_weight="1"
android:text="@string/delete"
android:textStyle="bold"
android:layout_width="0dp"
android:layout_height="wrap_content" />
<View
android:layout_width="1dp"
android:background="@color/grey_unselect"
android:layout_height="match_parent" />
<sis.com.smartworks.widget.SmartWorksTextView
android:id="@+id/cancel"
android:textSize="@dimen/smallest_text_size"
android:textColor="@color/black"
android:gravity="center"
android:layout_weight="1"
android:visibility="visible"
android:paddingRight="@dimen/four_dp"
android:paddingLeft="@dimen/four_dp"
android:paddingTop="@dimen/ten_dp"
android:paddingBottom="@dimen/ten_dp"
android:textStyle="bold"
android:text="@string/select_cancel"
android:layout_width="0dp"
android:layout_height="wrap_content" />
</LinearLayout>
</android.support.v7.widget.CardView>
<强>结果强>
因此,如果您想将视图设置为水平视图,则需要根据您的要求进行水平布局。因此,可以执行此任务来更改您放入edit_delete_layout.xml
然后传递到contentView
的{{1}}。
注意: - 您可以根据自己的要求自定义弹出类,我知道此代码有很多不推荐的视图,因此您可以自行更新。
答案 4 :(得分:0)
要显示紧凑的上下文菜单,您需要为ActionMode
创建Menu
,让我告诉您如何:
假设您的操作菜单XML具有删除,复制和转发操作:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_copy"
android:icon="@drawable/ic_vector_menu_copy"
android:title="Copy"
app:showAsAction="always" />
<item
android:id="@+id/action_delete"
android:icon="@drawable/ic_vector_menu_delete"
android:title="Delete"
app:showAsAction="always" />
<item
android:id="@+id/action_forward"
android:icon="@drawable/ic_vector_menu_forward"
android:title="Forward"
app:showAsAction="always" />
</menu>
在您的活动中创建操作菜单
//Global variable in Activity/Fragment to manage close the menu
private ActionMode mActionMode;
//Action mode callbacks
//Contextual Action bar - for showing delete/copy/... on action bar
private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {
// Called when the action mode is created; startActionMode() was called
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// Inflate a menu resource providing context menu items
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.menu_contextual_action, menu);
return true;
}
// Called each time the action mode is shown.
// Always called after onCreateActionMode, but
// may be called multiple times if the mode is invalidated.
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false; // Return false if nothing is done
}
// Called when the user selects a contextual menu item
@Override
public boolean onActionItemClicked(final ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.action_delete:
//Do the delete action
//mAdapter.resetSelection();
mode.finish(); // Action picked, so close the TAB
//showToast "Deleted successfully"
return true;
case R.id.action_copy:
//mAdapter.resetSelection();
MyClipboardManager.copyToClipboard(ChatDetailActivity.this, mAdapter.getSelectedMessageText());
mode.finish(); // Action picked, so close the TAB
//showToast "Text copied to clipboard"
return true;
default:
return false;
}
}
// Called when the user exits the action mode
@Override
public void onDestroyActionMode(ActionMode mode) {
mActionMode = null;
//mAdapter.resetSelection();
}
};
@Override
public void onBackPressed() {
//Closing menu first if it's visible rather than doing the back press action
if (mActionMode != null && mActionMode.getMenu().hasVisibleItems()) {
mActionMode.finish();
return;
}
super.onBackPressed();
}
@Override
public void onDestroy() {
//Closing menu
if (mActionMode != null) {
mActionMode.finish();
}
super.onDestroy();
}
*将回调设置为全局操作模式变量
mActionMode = startSupportActionMode(mActionModeCallback);
*将标题设置为菜单
mActionMode.setTitle("Menu title");
*设置值
后使菜单无效mActionMode.invalidate();
管理紧凑上下文菜单的样式
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:windowDisablePreview">true</item>
<!--CONTEXTUAL action MODE-->
<item name="android:windowContentOverlay">@null</item>
<!--ActionMode background color-->
<!-- <item name="android:actionModeBackground">@color/colorPrimary</item>-->
<!--To Overlay existing toolbar, NOTE We are not using android: to let it work everywhere-->
<item name="windowActionModeOverlay">true</item>
<item name="actionModeStyle">@style/AppActionModeStyle</item>
<item name="android:actionModeCloseDrawable">@drawable/ic_arrow_back_24dp</item>
</style>
<style name="AppActionModeStyle" parent="@style/Widget.AppCompat.ActionMode">
<!--ActionMode background color-->
<item name="background">@color/colorPrimary</item>
<!--ActionMode text title color-->
<item name="titleTextStyle">@style/ActionModeTitleTextStyle</item>
</style>
<style name="ActionModeTitleTextStyle" parent="@style/TextAppearance.AppCompat.Widget.ActionMode.Title">
<item name="android:textColor">@android:color/white</item>
</style>