所以,我创建了一个名为CustomView
的{{1}},
ButtonWithCaption.xml
及其控制器<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="?attr/selectableItemBackground"
android:paddingBottom="@dimen/spacing_normal"
android:paddingLeft="@dimen/spacing_small"
android:paddingRight="@dimen/spacing_small"
android:paddingTop="@dimen/spacing_normal">
<ImageView
android:id="@+id/bwc_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginBottom="2dp"
android:scaleType="centerCrop" />
<TextView
android:id="@+id/bwc_caption"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/bwc_icon"
android:textAlignment="center" />
ButtonWithCaption.java
没什么特别的。
然后,我在public class ButtonWithCaption extends RelativeLayout {
private ImageView mImageView;
private TextView mTextView;
private int mIconSrc;
private String mCaptionText;
private boolean mShowIcon;
private boolean mShowText;
public ButtonWithCaption(Context context) {
super(context);
init(context, null, 0);
}
public ButtonWithCaption(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs, 0);
}
public ButtonWithCaption(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs, defStyleAttr);
}
private void init(Context context, AttributeSet attrs, int defStyleAttr) {
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.ButtonWithCaption, 0, 0);
try {
mIconSrc = a.getResourceId(R.styleable.ButtonWithCaption_iconSrc, 0);
mCaptionText = a.getString(R.styleable.ButtonWithCaption_captionText);
mShowIcon = a.getBoolean(R.styleable.ButtonWithCaption_showIcon, mIconSrc != 0);
mShowText = a.getBoolean(R.styleable.ButtonWithCaption_showText, !mCaptionText.isEmpty());
mImageView = (ImageView) findViewById(R.id.bwc_icon);
mTextView = (TextView) findViewById(R.id.bwc_caption);
mImageView.setImageResource(mIconSrc);
mTextView.setText(mCaptionText);
} finally {
a.recycle();
}
}
}
attrs.xml
这是我的<resources>
<declare-styleable name="ButtonWithCaption">
<attr name="iconSrc" format="reference" />
<attr name="captionText" format="string" />
<attr name="showIcon" format="boolean" />
<attr name="showText" format="boolean" />
</declare-styleable>
</resources>
activity_main.xml
...但奇怪的是,Android Studio的预览给了我渲染错误:
无法实例化一个或多个类
with stacktrace:
显示java.lang.NullPointerException 在id.foodmap.foodmapcustomviews.ButtonWithCaption.init(ButtonWithCaption.java:54) 在id.foodmap.foodmapcustomviews.ButtonWithCaption。(ButtonWithCaption.java:29) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) 在org.jetbrains.android.uipreview.ViewLoader.createNewInstance(ViewLoader.java:475) 在org.jetbrains.android.uipreview.ViewLoader.loadClass(ViewLoader.java:262) 在org.jetbrains.android.uipreview.ViewLoader.loadView(ViewLoader.java:220) 在com.android.tools.idea.rendering.LayoutlibCallbackImpl.loadView(LayoutlibCallbackImpl.java:186) 在android.view.BridgeInflater.loadCustomView(BridgeInflater.java:334) 在android.view.BridgeInflater.loadCustomView(BridgeInflater.java:345) 在android.view.BridgeInflater.createViewFromTag(BridgeInflater.java:245) 在android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:727) 在android.view.LayoutInflater.rInflate_Original(LayoutInflater.java:858) 在android.view.LayoutInflater_Delegate.rInflate(LayoutInflater_Delegate.java:70) 在android.view.LayoutInflater.rInflate(LayoutInflater.java:834) 在android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:821) 在android.view.LayoutInflater.inflate(LayoutInflater.java:518) 在android.view.LayoutInflater.inflate(LayoutInflater.java:397) 在com.android.layoutlib.bridge.impl.RenderSessionImpl.inflate(RenderSessionImpl.java:324) 在com.android.layoutlib.bridge.Bridge.createSession(Bridge.java:429) 在com.android.ide.common.rendering.LayoutLibrary.createSession(LayoutLibrary.java:368) 在com.android.tools.idea.rendering.RenderTask $ 2.compute(RenderTask.java:567) 在com.android.tools.idea.rendering.RenderTask $ 2.compute(RenderTask.java:549) 在com.intellij.openapi.application.impl.ApplicationImpl.runReadAction(ApplicationImpl.java:863) 在com.android.tools.idea.rendering.RenderTask.createRenderSession(RenderTask.java:549) 在com.android.tools.idea.rendering.RenderTask.lambda $ inflate $ 1(RenderTask.java:680) at java.util.concurrent.FutureTask.run(FutureTask.java:266) 在java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:617) 在java.lang.Thread.run(Thread.java:745)
<?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:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="id.foodmap.foodmapcustomviews.MainActivity">
<id.foodmap.foodmapcustomviews.ButtonWithCaption
android:id="@+id/button_with_caption"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:captionText="Test"
app:iconSrc="@drawable/ic_email_gray_24dp" />
</RelativeLayout>
findViewById()
ButtonWithCaption.java
查找TextView
和ImageView
也会返回null。
有谁知道是什么造成的?因为它甚至没有显示在编辑器预览窗口中。
P.S。如果我使用,预览会正确显示元素。
P.S.S.它编译到我的手机没有错误,但没有显示ButtonWithCaption
。
提前致谢
答案 0 :(得分:2)
您收到NullPointerException
,因为您没有从ButtonWithCaption.xml
夸大观看次数。解决此问题的一种方法是使用静态View.inflate()
方法:
private void init(Context context, AttributeSet attrs, int defStyleAttr) {
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.ButtonWithCaption, 0, 0);
try {
mIconSrc = a.getResourceId(R.styleable.ButtonWithCaption_iconSrc, 0);
mCaptionText = a.getString(R.styleable.ButtonWithCaption_captionText);
mShowIcon = a.getBoolean(R.styleable.ButtonWithCaption_showIcon, mIconSrc != 0);
mShowText = a.getBoolean(R.styleable.ButtonWithCaption_showText, !mCaptionText.isEmpty());
View v = View.inflate(context, R.layout.ButtonWithCaption, this); // add this line
mImageView = (ImageView) findViewById(R.id.bwc_icon);
mTextView = (TextView) findViewById(R.id.bwc_caption);
mImageView.setImageResource(mIconSrc);
mTextView.setText(mCaptionText);
} finally {
a.recycle();
}
}
答案 1 :(得分:-1)
您必须将标记<RelativeLayout>
替换为您的类,如下所示:
<?xml version="1.0" encoding="utf-8"?>
<com.yourpackage.app.ButtonWithCaption xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
...
>
...
</com.yourpackage.app.ButtonWithCaption>
com.yourpackage.app应该是ButtonWithCaptionclass所在的路径。
编辑:
您发布的布局应该是您的活动布局,ButtonWithCaptionclass应该是您的xml元素,而不是您的xml名称,因此请更改名称,将RelativeLayout
替换为您的自定义类并尝试使用。