I have a View which is contained in a Fragment. The View contains a number of "buttons" (Each "Button is an ImageView)(see screen 1) Screen 1
My objective is that when I click on one of these buttons a PopupMenu will appear (see screen 2) Screen 2
This is working well most of the time but on some "buttons", when the "button" is clicked, the PopupMenu does not usually show (although the toast message does appear indicating that the 'cick' has been registered).
The issue is apparent on the "button" in the top left corner and on buttons at the bottom of the fragment. Sometimes the menu appears (but usually after many 'clicks')
My working assumption is that, for some reason, the menu is not being displayed on the screen (I believe it is being displayed but is 'off screen'/not visible).
I have researched the issue but cannot find anyone with a similar issue.
I have tried different Gravity settings when creating the PopupMenu, but nothing made a difference.
The code I am using to create the PopupMenu appears to be classical.
Thanks in advance for any help you can offer me on this.
Extract from RemoteView.java
// Constructors
public RemoteView(Context context) {
super(context);
init(context);
}
public RemoteView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public RemoteView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context) {
rootview = inflate(context, R.layout.remote, this);
}
public class IconViewOnTouchListener implements View.OnTouchListener {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (!edit) {
actionDOWN(v);
}
break;
case MotionEvent.ACTION_UP:
KeyMap keyMap=(KeyMap) v.getTag();
if (edit) {
if (movingButton) {
toIndex=keyMap.AMKeyItem;
toKey=keyMap.keyIndex;
exchangeButtons();
} else {
//popup edit options
if (keyMap.AMKeyItem >= 0) showPopup(v);
}
} else {
actionUP(v);
performClick();
}
break;
}
return true;
}
}
private void showPopup(final View view) {
//Creating the instance of PopupMenu
PopupMenu popup = new PopupMenu(context, view, Gravity.RIGHT, R.attr.actionOverflowMenuStyle, 0);
//Inflating the Popup using xml file
popup.getMenuInflater()
.inflate(R.menu.edit_button_menu, popup.getMenu());
Toast.makeText(context, "Popup Menu is visible",
Toast.LENGTH_SHORT).show();
popup.show(); //showing popup menu
}
remote.xml
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="match_parent">
<com.andy.andymote.CommunicatorView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/remote_communicator">
</com.andy.andymote.CommunicatorView>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/buttons"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:numColumns="5"
android:gravity="center"
android:stretchMode="spacingWidthUniform"
>
</GridView>
</RelativeLayout>
</merge>
frag_device.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="top"
android:orientation="vertical"
>
<com.andy.andymote.RemoteView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/remote">
</com.andy.andymote.RemoteView>
</LinearLayout>
edit_button_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/moveButton"
android:title="Move"/>
<item
android:id="@+id/editButton"
android:title="Edit"/>
<item
android:id="@+id/insertRow"
android:title="Insert Row Above"/>
</menu>
Extract from DeviceACTIVITY.java
private void loadFragment(){
device = new DeviceFRAGMENT();
device.setDevice(GLOBALS.deviceList.getDevice(deviceName));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
device).commit();
}
Extract from DeviceFRAGMENT.java
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.frag_device, container, false);
//Declare Widgets
remote = view.findViewById(R.id.remote);
remote.setKeys(device.getRemote());
return view;
}
RemoteKeysAdapter.java
import static com.andy.andymote.GLOBALS.iconSize;
public class RemoteKeysAdapter extends BaseAdapter {
private final Context mContext;
private final List<RemoteButton> remoteButtons;
private _resourceAccess resource;
private RemoteView.IconViewOnTouchListener iconViewOnTouchListener;
private Remote remote;
// 1
public RemoteKeysAdapter(Context context, Remote remote, List<RemoteButton> remoteButtons,
RemoteView.IconViewOnTouchListener iconViewOnTouchListener) {
this.mContext = context;
this.remote=remote;
this.remoteButtons = remoteButtons;
this.iconViewOnTouchListener=iconViewOnTouchListener;
resource = new _resourceAccess(context);
}
// 2
@Override
public int getCount() {
return remoteButtons.size();
}
// 3
@Override
public long getItemId(int position) {
return 0;
}
// 4
@Override
public Object getItem(int position) {
return null;
}
// 5
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// Find the proper remoteButton for this cell by using the position index
final RemoteButton remoteButton = remoteButtons.get(position);
if (convertView == null) {
final LayoutInflater layoutInflater = LayoutInflater.from(mContext);
convertView = layoutInflater.inflate(R.layout.remote_button, null);
}
// create reference for the image in the XML layout file.
final AppCompatImageView imageView = convertView.findViewById(R.id.button);
// Set the image
int indexOfAndyMoteKeyItem=remoteButton.getFromToIndex();
if (indexOfAndyMoteKeyItem == -1){
imageView.setImageDrawable(mContext.getResources().getDrawable(R.drawable.ic_nobutton));
} else {
AndyMoteKeyItem andyMoteKeyItem=remote.getRemoteLayout().get(indexOfAndyMoteKeyItem);
if (andyMoteKeyItem.getLircKeyItem().getIcon().length() == 0) {
displayText(imageView, andyMoteKeyItem.getLircKeyItem().getText());
} else {
displayIcon(imageView, andyMoteKeyItem.getLircKeyItem().getIcon());
}
}
KeyMap keyMap=new KeyMap();
keyMap.AMKeyItem=indexOfAndyMoteKeyItem;
keyMap.keyIndex=position;
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
params.gravity= Gravity.CENTER;
params.width=iconSize;
params.height=iconSize;
convertView.setLayoutParams(params);
convertView.setOnTouchListener(iconViewOnTouchListener);
convertView.setPadding(16, 0, 0, 16);
convertView.setVisibility(remoteButton.getVisibility());
convertView.setTag(keyMap);
return convertView;
}
private void displayIcon(AppCompatImageView imageView, String icon) {
clIcon newIcon = factory.createIcon(icon);
imageView.setImageDrawable(resource.getDrawableFromUri(newIcon.getURI(mContext)));
}
private void displayText(AppCompatImageView imageView, String text) {
//https://github.com/amulyakhare/TextDrawable
TextDrawable drawable = TextDrawable.builder().beginConfig()
.textColor(Color.WHITE)
.bold()
.withBorder(4)
.useFont(Typeface.DEFAULT)
.fontSize(30) /* size in px */
.endConfig()
.buildRound(text, Color.DKGRAY);
imageView.setImageDrawable(drawable);
}
}
I fixed this by using Droppy instead of PopupMenu. No other magic was required
private void showPopup(final View view) {
DroppyMenuPopup.Builder popup = new DroppyMenuPopup.Builder(context, view);
popup.addMenuItem(new DroppyMenuItem("Move").setId(R.id.moveButton));
popup.addMenuItem(new DroppyMenuItem("Edit").setId(R.id.editButton));
popup.addMenuItem(new DroppyMenuItem("Insert Row Above").setId(R.id.insertRow));
// Set Callback handler
popup.setOnClick(new DroppyClickCallbackInterface() {
@Override
public void call(View v, int id) {
switch (id) {
case R.id.editButton:
//code for editButton
break;
case R.id.moveButton:
//code for moveButton
break;
case R.id.insertRow:
//code for insertRow
break;
default:
}
}
});
DroppyMenuPopup droppyMenu = popup.build();
droppyMenu.show();
}