Android:在片段内膨胀自定义视图
Posted
技术标签:
【中文标题】Android:在片段内膨胀自定义视图【英文标题】:Android: Inflate Custom View inside Fragment 【发布时间】:2016-12-13 01:16:52 【问题描述】:我有一个应用程序使用片段视图作为其布局的一部分。在这个片段中,我想实例化一个 Paint Canvas,我可以在其中进行自定义绘图。
问题是,当我使用错误 android.view.InflateException: Binary XML file line #15: Binary XML file line #15: Error inflating class com.example.xxxxx.NeckCanvasOverlay
对片段进行充气时,我的应用程序崩溃了
我不确定是什么导致我的 Paint 类不能正确充气。我知道关于如何在片段中使用 findViewById 有一些特殊规则,但我认为我遵守了它们,因为我在片段的视图本身上调用 findViewByid(在我的代码中称为“v”)。
我该如何解决这个问题?
FragmentNeckDisplayMenu.java(片段类)
public class FragmentNeckDisplayMenu extends Fragment
private static View v;
private NeckCanvasOverlay neckHUD;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
v = inflater.inflate(R.layout.menu_fragment_neck_display,container,false); //ERROR HERE
NeckCanvasOverlay neckHUD = (NeckCanvasOverlay) v.findViewById(R.id.neckHUD); //paint test
...
return v;
NeckCanvasOverlay.java(绘画类)
class NeckCanvasOverlay extends View
private Paint mPainter;
public NeckCanvasOverlay(Context context)
super(context);
initView();
private void initView() //Initializes canvas & paint objects here to save performance
mPainter = new Paint(Paint.ANTI_ALIAS_FLAG);
mPainter.setColor(Color.BLUE);
mPainter.setAlpha(128);
@Override
public void onDraw(Canvas canvas)
super.onDraw(canvas);
canvas.drawCircle(180, 900, 200, mPainter);
menu_fragment_neck_display.xml(片段的布局)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
android:orientation="vertical"
android:id="@+id/canvas"
android:background="@drawable/image">
<LinearLayout
android:layout_
android:layout_
android:layout_gravity="center"
android:layout_weight="4">
!--Custom view for Canvas here -->
<com.example.xxxxx.NeckCanvasOverlay
android:id="@+id/neckHUD"
android:layout_
android:layout_
android:background="@drawable/neck_for_menu"/>
</LinearLayout>
<Button
android:id="@+id/menuIcon"
android:layout_
android:layout_
android:layout_marginTop="64dp"
android:text="Menu"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_gravity="bottom"
android:layout_weight="0.5"/>
</LinearLayout>
完整堆栈跟踪(编辑:包含完整跟踪)
08-06 21:47:24.894 26334-26334/com.example.xxxxx E/ACRA: ACRA caught a InflateException for com.example.xxxxx
android.view.InflateException: Binary XML file line #15: Binary XML file line #15: Error inflating class com.example.gu.NeckCanvasOverlay
at android.view.LayoutInflater.inflate(LayoutInflater.java:551)
at android.view.LayoutInflater.inflate(LayoutInflater.java:429)
at com.example.xxxxx.FragmentNeckDisplayMenu.onCreateView(FragmentNeckDisplayMenu.java:32)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1962)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1248)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:738)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1613)
at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:570)
at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:141)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1106)
at android.support.v4.view.ViewPager.populate(ViewPager.java:952)
at android.support.v4.view.ViewPager.setOffscreenPageLimit(ViewPager.java:733)
at com.example.xxxxx.PlayFrets.configMenu(PlayFrets.java:150)
at com.example.xxxxx.AsyncTask_NoteFileLoader.onPostExecute(AsyncTask_NoteFileLoader.java:125)
at com.example.xxxxx.AsyncTask_NoteFileLoader.onPostExecute(AsyncTask_NoteFileLoader.java:9)
at android.os.AsyncTask.finish(AsyncTask.java:651)
at android.os.AsyncTask.access$500(AsyncTask.java:180)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:668)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7229)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
Caused by: android.view.InflateException: Binary XML file line #15: Error inflating class com.example.gu.NeckCanvasOverlay
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:788)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:716)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:847)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:810)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:855)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:810)
at android.view.LayoutInflater.inflate(LayoutInflater.java:527)
at android.view.LayoutInflater.inflate(LayoutInflater.java:429)
at com.example.xxxxx.FragmentNeckDisplayMenu.onCreateView(FragmentNeckDisplayMenu.java:32)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1962)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1248)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:738)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1613)
at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:570)
at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:141)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1106)
at android.support.v4.view.ViewPager.populate(ViewPager.java:952)
at android.support.v4.view.ViewPager.setOffscreenPageLimit(ViewPager.java:733)
at com.example.xxxxx.PlayFrets.configMenu(PlayFrets.java:150)
at com.example.xxxxx.AsyncTask_NoteFileLoader.onPostExecute(AsyncTask_NoteFileLoader.java:125)
at com.example.xxxxx.AsyncTask_NoteFileLoader.onPostExecute(AsyncTask_NoteFileLoader.java:9)
at android.os.AsyncTask.finish(AsyncTask.java:651)
at android.os.AsyncTask.access$500(AsyncTask.java:180)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:668)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7229)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
Caused by: java.lang.ClassNotFoundException: Didn't find class "com.example.gu.NeckCanvasOverlay" on path: DexPathList[[zip file "/data/app/com.example.xxxxx-2/base.apk"],nativeLibraryDirectories=[/data/app/com.example.xxxxx-2/lib/arm64, /vendor/lib64, /system/lib64]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
at android.view.LayoutInflater.createView(LayoutInflater.java:595)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:776)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:716)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:847)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:810)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:855)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:810)
at android.view.LayoutInflater.inflate(LayoutInflater.java:527)
at android.view.LayoutInflater.inflate(LayoutInflater.java:429)
at com.example.xxxxx.FragmentNeckDisplayMenu.onCreateView(FragmentNeckDisplayMenu.java:32)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1962)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1248)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:738)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1613)
at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:570)
at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:141)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1106)
at android.support.v4.view.ViewPager.populate(ViewPager.java:952)
at android.support.v4.view.ViewPager.setOffscreenPageLimit(ViewPager.java:733)
at com.example.xxxxx.PlayFrets.configMenu(PlayFrets.java:150)
at com.example.xxxxx.AsyncTask_NoteFileLoader.onPostExecute(AsyncTask_NoteFileLoader.java:125)
at com.example.xxxxx.AsyncTask_NoteFileLoader.onPostExecute(AsyncTask_NoteFileLoader.java:9)
at android.os.AsyncTask.finish(AsyncTask.java:651)
at android.os.AsyncTask.access$500(AsyncTask.java:180)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:668)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7229)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
Suppressed: java.lang.ClassNotFoundException: com.example.gu.NeckCanvasOverlay
at java.lang.Class.classForName(Native Method)
at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
... 33 more
Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack trace available
08-06 21:47:24.954 26334-27123/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.xxxxx, PID: 26334
android.view.InflateException: Binary XML file line #15: Binary XML file line #15: Error inflating class com.example.gu.NeckCanvasOverlay
at android.view.LayoutInflater.inflate(LayoutInflater.java:551)
at android.view.LayoutInflater.inflate(LayoutInflater.java:429)
at com.example.xxxxx.FragmentNeckDisplayMenu.onCreateView(FragmentNeckDisplayMenu.java:32)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1962)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1248)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:738)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1613)
at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:570)
at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:141)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1106)
at android.support.v4.view.ViewPager.populate(ViewPager.java:952)
at android.support.v4.view.ViewPager.setOffscreenPageLimit(ViewPager.java:733)
at com.example.xxxxx.PlayFrets.configMenu(PlayFrets.java:150)
at com.example.xxxxx.AsyncTask_NoteFileLoader.onPostExecute(AsyncTask_NoteFileLoader.java:125)
at com.example.xxxxx.AsyncTask_NoteFileLoader.onPostExecute(AsyncTask_NoteFileLoader.java:9)
at android.os.AsyncTask.finish(AsyncTask.java:651)
at android.os.AsyncTask.access$500(AsyncTask.java:180)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:668)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7229)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
Caused by: android.view.InflateException: Binary XML file line #15: Error inflating class com.example.gu.NeckCanvasOverlay
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:788)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:716)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:847)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:810)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:855)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:810)
at android.view.LayoutInflater.inflate(LayoutInflater.java:527)
at android.view.LayoutInflater.inflate(LayoutInflater.java:429)
at com.example.xxxxx.FragmentNeckDisplayMenu.onCreateView(FragmentNeckDisplayMenu.java:32)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1962)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1248)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:738)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1613)
at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:570)
at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:141)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1106)
at android.support.v4.view.ViewPager.populate(ViewPager.java:952)
at android.support.v4.view.ViewPager.setOffscreenPageLimit(ViewPager.java:733)
at com.example.xxxxx.PlayFrets.configMenu(PlayFrets.java:150)
at com.example.xxxxx.AsyncTask_NoteFileLoader.onPostExecute(AsyncTask_NoteFileLoader.java:125)
at com.example.xxxxx.AsyncTask_NoteFileLoader.onPostExecute(AsyncTask_NoteFileLoader.java:9)
at android.os.AsyncTask.finish(AsyncTask.java:651)
at android.os.AsyncTask.access$500(AsyncTask.java:180)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:668)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7229)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
Caused by: java.lang.ClassNotFoundException: Didn't find class "com.example.gu.NeckCanvasOverlay" on path: DexPathList[[zip file "/data/app/com.example.xxxxx-2/base.apk"],nativeLibraryDirectories=[/data/app/com.example.xxxxx-2/lib/arm64, /vendor/lib64, /system/lib64]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
at android.view.LayoutInflater.createView(LayoutInflater.java:595)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:776)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:716)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:847)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:810)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:855)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:810)
at android.view.LayoutInflater.inflate(LayoutInflater.java:527)
at android.view.LayoutInflater.inflate(LayoutInflater.java:429)
at com.example.xxxxx.FragmentNeckDisplayMenu.onCreateView(FragmentNeckDisplayMenu.java:32)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1962)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1248)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:738)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1613)
at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:570)
at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:141)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1106)
at android.support.v4.view.ViewPager.populate(ViewPager.java:952)
at android.support.v4.view.ViewPager.setOffscreenPageLimit(ViewPager.java:733)
at com.example.xxxxx.PlayFrets.configMenu(PlayFrets.java:150)
at com.example.xxxxx.AsyncTask_NoteFileLoader.onPostExecute(AsyncTask_NoteFileLoader.java:125)
【问题讨论】:
在堆栈跟踪中进一步查看根本原因。这可能是因为您缺少必要的构造函数来为您的自定义View
膨胀。您需要一个带有 Context
和 AttributeSet
的双参数构造函数。
你可以在这个链接上看到答案***.com/questions/17599450/…
你确定你的包名到处都是正确的吗?你在某些地方有com.example.xxxxx
,在其他地方有com.example.gu
。这只是搜索/替换编辑错误吗?在布局和类中仔细检查,然后尝试清理/重建您的项目。
我不知道你的意思是什么,但你得到了一个ClassNotFoundException
代表com.example.gu.NeckCanvasOverlay
。您在布局 XML 中指定的任何类都不存在于您的 apk 中。无论您现在的类和包名称是什么,您都需要确保在 XML 中正确引用了该类。
好发现,这实际上是问题所在!与自定义视图对应的类在我的布局的 XML 文件中命名错误。如果你发布它,我会接受这个作为答案。
【参考方案1】:
直接的问题是ClassNotFoundException
。在布局中处理自定义 View
s 时,常见原因是布局 XML 中的类名不正确,这似乎是这里的问题。确保 XML 标记具有自定义 View
类的正确、完全限定的类名,这将是文件顶部的类的 package
,附加到类名之前。
此外,从您的布局中膨胀的View
s 将使用一个带有Context
和AttributeSet
的两个参数的构造函数进行实例化。您的类定义至少需要具有允许膨胀的构造函数,否则您将获得NoSuchMethodException
。此外,如果您将构造函数链接起来,如果您只是扩展View
,它会使事情变得更简单。例如:
public NeckCanvasOverlay(Context context)
this(context, null);
public NeckCanvasOverlay(Context context, AttributeSet attrs)
super(context, attrs);
initView();
【讨论】:
【参考方案2】:为自定义View
包含所有三个构造函数会更安全。例如,为您的NeckCanvasOverlay
包含以下构造函数。
public NeckCanvasOverlay(Context context)
super(context);
initView();
public NeckCanvasOverlay(Context context, AttributeSet attrs)
super(context, attrs);
initView();
public NeckCanvasOverlay(Context context, AttributeSet attrs, int defStyle)
super(context, attrs, defStyle);
initView();
我希望这会有所帮助。试一试,如果遇到同样的错误,请告诉我。
【讨论】:
以上是关于Android:在片段内膨胀自定义视图的主要内容,如果未能解决你的问题,请参考以下文章
从 XML 膨胀自定义视图会创建 Illegalstateexception(Android, Java)