当RecylerView项被longClicked时,我试图为重命名/删除选项添加一个简单的PopupMenu。由于某种原因,在将xml文件加载到充气机中后调用mPopup.show()
时,出现XML充气错误。
我在应用程序的其他地方使用了类似的逻辑来制作PopupMenu,并且效果很好。我什至尝试将应用程序无关部分的工作PopupMenu加载到该充气机中,并且在logcat中看到相同的android.view.InflateException: Binary XML file line #17: Failed to resolve attribute at index 1
错误,所以也许XML文件不是问题吗?
我怎样才能使PopupMenu膨胀并显示出来?
致命异常Logcat
05-31 23:02:27.421 19597-20019/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.foo, PID: 19597
android.view.InflateException: Binary XML file line #17: Failed to resolve attribute at index 1: TypedValue{t=0x2/d=0x7f01005d a=-1}
Caused by: java.lang.UnsupportedOperationException: Failed to resolve attribute at index 1: TypedValue{t=0x2/d=0x7f01005d a=-1}
at android.content.res.TypedArray.getLayoutDimension(TypedArray.java:761)
at android.view.ViewGroup$LayoutParams.setBaseAttributes(ViewGroup.java:7060)
at android.view.ViewGroup$MarginLayoutParams.<init>(ViewGroup.java:7241)
at android.widget.FrameLayout$LayoutParams.<init>(FrameLayout.java:438)
at android.widget.FrameLayout.generateLayoutParams(FrameLayout.java:370)
at android.widget.FrameLayout.generateLayoutParams(FrameLayout.java:369)
at android.view.LayoutInflater.inflate(LayoutInflater.java:505)
at android.view.LayoutInflater.inflate(LayoutInflater.java:426)
at android.support.v7.view.menu.MenuAdapter.getView(MenuAdapter.java:93)
at android.support.v7.view.menu.MenuPopup.measureIndividualMenuWidth(MenuPopup.java:160)
at android.support.v7.view.menu.StandardMenuPopup.tryShow(StandardMenuPopup.java:153)
at android.support.v7.view.menu.StandardMenuPopup.show(StandardMenuPopup.java:187)
at android.support.v7.view.menu.MenuPopupHelper.showPopup(MenuPopupHelper.java:290)
at android.support.v7.view.menu.MenuPopupHelper.tryShow(MenuPopupHelper.java:175)
at android.support.v7.view.menu.MenuPopupHelper.show(MenuPopupHelper.java:141)
at android.support.v7.widget.PopupMenu.show(PopupMenu.java:233)
at com.example.foo.FragmentChordMenu.showChordOptionsMenu(FragmentChordMenu.java:132)
at com.example.foo.CustomChordAdapter$ChordViewHolder$2.onLongClick(CustomChordAdapter.java:138)
at android.view.View.performLongClickInternal(View.java:5687)
at android.view.View.performLongClick(View.java:5645)
at android.view.View.performLongClick(View.java:5663)
at android.view.View$CheckForLongPress.run(View.java:22234)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
FragmentActivity
public class FragmentChordMenu extends Fragment implements CustomChordAdapter.onItemClickListener {
private static RecyclerView mCustomChordList;
private static CustomChordAdapter mRecyclerViewAdapter;
private static Context mContext;
private FloatingActionButton mFAB;
private View mPopupView;
private PopupWindow mCustomChordMenu;
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mRecyclerViewAdapter = new CustomChordAdapter(this);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
mContext = getActivity().getApplicationContext(); //stores application context for later use in fragment without risk
//of detachment
View v = inflater.inflate(R.layout.menu_fragment_chord, container, false);
LayoutInflater layoutInflater = (LayoutInflater)getActivity().getBaseContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
...
mFAB = (FloatingActionButton) v.findViewById(R.id.addChord);
mFAB.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
mCustomChordMenu.showAtLocation(mPopupView, Gravity.CENTER, 10, 10);
mCustomChordList = (RecyclerView) mPopupView.findViewById(R.id.rv_userChords);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
mCustomChordList.setLayoutManager(layoutManager);
mCustomChordList.setAdapter(mRecyclerViewAdapter);
}
});
return v;
}
public static void showChordOptionsMenu(final int position){
View anchorView = mCustomChordList.findViewHolderForAdapterPosition(position).itemView;
PopupMenu mPopup = new PopupMenu(mContext, anchorView);
mPopup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()){
case R.id.delete:
mRecyclerViewAdapter.deleteChord(position);
return true;
case R.id.rename:
Log.d("FragmentChordMenu: ", "Rename clicked");
}
return true;
}
});
MenuInflater popupInflater = mPopup.getMenuInflater();
popupInflater.inflate(R.menu.popup_delete_chord, mPopup.getMenu());
mPopup.show(); //ERROR HERE
}
...
}
PopupMenu XML
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<item
android:id="@+id/rename"
android:title="@string/rename"/>
<item
android:id="@+id/delete"
android:title="@string/delete"/>
</menu>
FragmentActivity XML
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android.support.design="http://schemas.android.com/tools"
android:id="@+id/chordMenu"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:id="@+id/scrollview"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/chordButtons"
android:orientation="vertical" >
</LinearLayout>
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_margin="16dp"
android:clickable="true"
app:fabSize="mini"
android:id="@+id/addChord"
app:borderWidth="0dp"
app:useCompatPadding="false"
android:src="@drawable/ic_add_black_24dp"/>
</LinearLayout>
</ScrollView>
</RelativeLayout>
最佳答案
此处直接出现问题的原因-InflateException
-使用appcompat-v7 Context
的应用程序PopupMenu
。
mContext = getActivity().getApplicationContext();
...
PopupMenu mPopup = new PopupMenu(mContext, anchorView);
该
Context
不会为v7小部件设置正确的主题资源,从而导致InflateException
。 Activity
确实具有适当的主题,使用该主题可以解决该特定问题。mContext = getActivity();
但是,在解决此问题之后,由于
WindowManager$BadTokenException
从PopupMenu
传递了 anchor View
,因此出现了PopupWindow
。弹出窗口必须在顶级View
中 anchor 定到Window
,并且Popup*
类基本上是简单的View
,因此是Exception。一个简单的解决方案是将
PopupWindow
替换为确实具有Dialog
的Window
。例如:AlertDialog dlg = new AlertDialog.Builder(getActivity()).setView(mPopupView).show();
最后,我建议您修改设置,以消除对
static
类中的Fragment
成员的需要。这些static
字段可能会导致内存泄漏,并且您的IDE可能现在就警告您。一个类似于CustomChordAdapter
中的监听器接口(interface)就足够了。关于java - Android上PopupMenu.show()的二进制XML膨胀错误,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44298079/