如何制作横向的上下文菜单?
How to make a horizontal ContextMenu?
我制作了一个名为 Accounts
的 Activity
,我想添加一个水平 ContextMenu
。这可能看起来像剪切、复制和粘贴选项。有没有办法在列表项上添加这个水平自定义菜单onLongClick
?
这是我目前所知道的。
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
LayoutInflater inflater = getLayoutInflater().from(this);
View view = inflater.inflate(R.layout.custom_listview, null, false);
menu.setHeaderView(view);
menu.add("Delete");
menu.add("Edit");
}
@Override
public boolean onContextItemSelected(MenuItem item) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
int position = info.position;
View v = listView.getChildAt(position);
TextView typeTv = v.findViewById(R.id.custom_listview_type);
TextView userTv = v.findViewById(R.id.custom_listview_user);
TextView passTv = v.findViewById(R.id.custom_listview_password);
if (item.getTitle().equals("Delete")) {
db.execSQL("delete from user_added_accounts where accountType = '" + typeTv.getText().toString() + "' and username = '" + userTv.getText().toString() + "';");
recreate();
}
if (item.getTitle().equals("Edit")) {
update(typeTv.getText().toString(), userTv.getText().toString(), passTv.getText().toString());
}
return true;
}
而现在的UI是这样的。
这是我想要的,
我想你需要的是PopupWindow
。它更容易实现并具有自定义布局设置选项。 PopupWindow
可以根据需要设置在自定义位置,并且可以通过 PopupWindow
的实施来实现您正在考虑的实施示例 copy/paste UI 的想法以及。
我发现 this answer 如果您想使用 PopupWindow
来实现您的情况而不是使用上下文菜单来实现它,我发现它非常有用。
在上面我提到并提供了一个赞的答案中,有一个 PopupWindow
只有一个 TextView
。您可以实现任何 custom/complex UI 而不是像此处显示的那样使用简单的 TextView
。
希望对您有所帮助。
更新
如评论中所述,获取 PopupWindow
位置的位置也可以动态设置。我指的是另一个 link,这样您也可以从那里检查实现。
Here's the implementation 在列表中使用 PopupWindow
。
所以,几年前我写了下面的代码。您需要制作两个 class,第一个是 PopUp
,第二个是 TringleView
。
PopUp :- Make dialog box and open into near your view(where you want
to open dialog). You can change popup bg color.
TringleView :- Make tringle view or you can say pointed arrow.You can change pointed arrow bg color.
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
然后传递给Popup class method
。
注意:- 您可以根据您的要求自定义弹出窗口 class,我知道此代码有很多已弃用的视图,因此您可以自行更新。
要显示紧凑的上下文菜单,您需要为 Menu
创建 ActionMode
,让我告诉您如何操作:
Suppose your action menu XML have delete, copy and forward actions:
<?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>
Create your action menu in your Activity
//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();
Style to manage compact contextual menu
<!-- 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>
只需通过QuickAction库即可实现。
https://github.com/piruin/quickaction
https://github.com/lorensiuswlt/NewQuickAction
希望对您有所帮助!!
我制作了一个名为 Accounts
的 Activity
,我想添加一个水平 ContextMenu
。这可能看起来像剪切、复制和粘贴选项。有没有办法在列表项上添加这个水平自定义菜单onLongClick
?
这是我目前所知道的。
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
LayoutInflater inflater = getLayoutInflater().from(this);
View view = inflater.inflate(R.layout.custom_listview, null, false);
menu.setHeaderView(view);
menu.add("Delete");
menu.add("Edit");
}
@Override
public boolean onContextItemSelected(MenuItem item) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
int position = info.position;
View v = listView.getChildAt(position);
TextView typeTv = v.findViewById(R.id.custom_listview_type);
TextView userTv = v.findViewById(R.id.custom_listview_user);
TextView passTv = v.findViewById(R.id.custom_listview_password);
if (item.getTitle().equals("Delete")) {
db.execSQL("delete from user_added_accounts where accountType = '" + typeTv.getText().toString() + "' and username = '" + userTv.getText().toString() + "';");
recreate();
}
if (item.getTitle().equals("Edit")) {
update(typeTv.getText().toString(), userTv.getText().toString(), passTv.getText().toString());
}
return true;
}
而现在的UI是这样的。
这是我想要的,
我想你需要的是PopupWindow
。它更容易实现并具有自定义布局设置选项。 PopupWindow
可以根据需要设置在自定义位置,并且可以通过 PopupWindow
的实施来实现您正在考虑的实施示例 copy/paste UI 的想法以及。
我发现 this answer 如果您想使用 PopupWindow
来实现您的情况而不是使用上下文菜单来实现它,我发现它非常有用。
在上面我提到并提供了一个赞的答案中,有一个 PopupWindow
只有一个 TextView
。您可以实现任何 custom/complex UI 而不是像此处显示的那样使用简单的 TextView
。
希望对您有所帮助。
更新
如评论中所述,获取 PopupWindow
位置的位置也可以动态设置。我指的是另一个 link,这样您也可以从那里检查实现。
Here's the implementation 在列表中使用 PopupWindow
。
所以,几年前我写了下面的代码。您需要制作两个 class,第一个是 PopUp
,第二个是 TringleView
。
PopUp :- Make dialog box and open into near your view(where you want to open dialog). You can change popup bg color.
TringleView :- Make tringle view or you can say pointed arrow.You can change pointed arrow bg color.
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
然后传递给Popup class method
。
注意:- 您可以根据您的要求自定义弹出窗口 class,我知道此代码有很多已弃用的视图,因此您可以自行更新。
要显示紧凑的上下文菜单,您需要为 Menu
创建 ActionMode
,让我告诉您如何操作:
Suppose your action menu XML have delete, copy and forward actions:
<?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>
Create your action menu in your Activity
//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();
Style to manage compact contextual menu
<!-- 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>
只需通过QuickAction库即可实现。
https://github.com/piruin/quickaction
https://github.com/lorensiuswlt/NewQuickAction
希望对您有所帮助!!