我在stackoverflow上找到了自定义LinearLayout的这个示例,但是当我尝试运行它时会抛出错误,有人可以找到它的错误吗?
自定义LinearLayout:
package com.example.androidapp.widgets;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.Transformation;
import android.widget.LinearLayout;
public class ExpandablePanel extends LinearLayout {
private final int mHandleId;
private final int mContentId;
private View mHandle;
private View mContent;
private boolean mExpanded = true;
private int mCollapsedHeight = 0;
private int mContentHeight = 0;
public ExpandablePanel(Context context) {
this(context, null);
}
public ExpandablePanel(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.ExpandablePanel, 0, 0);
// How high the content should be in "collapsed" state
mCollapsedHeight = (int) a.getDimension(
R.styleable.ExpandablePanel_collapsedHeight, 0.0f);
int handleId = a.getResourceId(R.styleable.ExpandablePanel_handle, 0);
if (handleId == 0) {
throw new IllegalArgumentException(
"The handle attribute is required and must refer "
+ "to a valid child.");
}
int contentId = a.getResourceId(R.styleable.ExpandablePanel_content, 0);
if (contentId == 0) {
throw new IllegalArgumentException(
"The content attribute is required and must refer "
+ "to a valid child.");
}
mHandleId = handleId;
mContentId = contentId;
a.recycle();
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mHandle = findViewById(mHandleId);
if (mHandle == null) {
throw new IllegalArgumentException(
"The handle attribute is must refer to an"
+ " existing child.");
}
mContent = findViewById(mContentId);
if (mContent == null) {
throw new IllegalArgumentException(
"The content attribute is must refer to an"
+ " existing child.");
}
mHandle.setOnClickListener(new PanelToggler());
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (mContentHeight == 0) {
// First, measure how high content wants to be
mContent.measure(widthMeasureSpec, MeasureSpec.UNSPECIFIED);
mContentHeight = mContent.getMeasuredHeight();
}
// Then let the usual thing happen
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
private class PanelToggler implements OnClickListener {
@Override
public void onClick(View v) {
Animation a;
if (mExpanded) {
a = new ExpandAnimation(mContentHeight, mCollapsedHeight);
} else {
a = new ExpandAnimation(mCollapsedHeight, mContentHeight);
}
a.setDuration(500);
mContent.startAnimation(a);
mExpanded = !mExpanded;
}
}
private class ExpandAnimation extends Animation {
private final int mStartHeight;
private final int mDeltaHeight;
public ExpandAnimation(int startHeight, int endHeight) {
mStartHeight = startHeight;
mDeltaHeight = endHeight - startHeight;
}
@Override
protected void applyTransformation(float interpolatedTime,
Transformation t) {
android.view.ViewGroup.LayoutParams lp = mContent.getLayoutParams();
lp.height = (int) (mStartHeight + mDeltaHeight * interpolatedTime);
mContent.setLayoutParams(lp);
}
@Override
public boolean willChangeBounds() {
// TODO Auto-generated method stub
return true;
}
}
}
res>值> attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="ExpandablePanel">
<attr name="handle" format="reference" />
<attr name="content" format="reference" />
<attr name="collapsedHeight" format="dimension" />
</declare-styleable>
</resources>
main.xml中:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:cl="http://schemas.android.com/apk/lib/com.example.androidapp.widgets"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<com.example.androidapp.widgets.ExpandablePanel
android:orientation="vertical"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
cl:handle="@+id/expand"
cl:content="@+id/value"
cl:collapsedHeight="50dip">
<TextView
android:id="@id/value"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:maxHeight="50dip"
/>
<Button
android:id="@id/expand"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="More" />
</com.example.androidapp.widgets.ExpandablePanel>
</LinearLayout>
活动类:
package com.example.androidapp.widgets;
import android.app.Activity;
import android.os.Bundle;
public class GoodPanelsActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
LogCat错误:
FATAL EXCEPTION:main java.lang.RuntimeException:无法启动 活动 ComponentInfo {com.example.androidapp.widgets / com.example.androidapp.widgets.GoodPanelsActivity}: android.view.InflateException:二进制XML文件行#9:错误 inflating class com.example.androidapp.widgets.ExpandablePanel
编辑:更多来自LogCat
java.lang.reflect.InvocationTargetException at java.lang.reflect.Constructor.constructNative(Native Method)at java.lang.reflect.Constructor.newInstance(Constructor.java:415)at android.view.LayoutInflater.createView(LayoutInflater.java:505)导致 by:java.lang.IllegalArgumentException:handle属性是 必须且必须提及有效的孩子。在 com.example.androidapp.widgets.ExpandablePanel。(ExpandablePanel.java:39)
答案 0 :(得分:6)
最后我发现了这个问题:
在main.xml中查看以下行:
xmlns:cl="http://schemas.android.com/apk/lib/com.example.androidapp.widgets"
它应该是:
xmlns:cl="http://schemas.android.com/apk/res/com.example.androidapp.widgets"
因为我没有使用外部库和ExpandablePanel存在于res。
下干杯。
答案 1 :(得分:0)
您需要将包含此类com.example.androidapp.widgets.ExpandablePanel
的项目添加到项目buildpath
。如果这不是一个开源项目,或者源不可用,则无法执行此操作。
如果你有这个项目,并且它是LibraryProject
,你应该右键点击Project->Properties->Android
并在Library
部分添加该项目。
如果是正常的Project
,只需转到Properties->Java Build Path->Projects
,然后添加该项目。
答案 2 :(得分:-1)
我也在试用这个脚本,因为我是Android编程的新手,我正在寻找一些很好的例子来学习。
当我将布局添加到main.xml时,我的应用程序强制关闭。
当我为ExpendablePanel添加布局时,图形布局变为灰色,我无法编辑它:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:cl="http://schemas.android.com/apk/lib/com.martin.myapp.widgets"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<com.martin.myapp.widgets.ExpandablePanel
android:orientation="vertical"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
cl:handle="@+id/expand"
cl:content="@+id/value"
cl:collapsedHeight="50dip">
<TextView
android:id="@id/value"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:maxHeight="50dip"
/>
<Button
android:id="@id/expand"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="More" />
</com.martin.myapp.widgets.ExpandablePanel>
所以这实际上是一个没有自定义小部件的空应用程序。
我制作了一个ExpandablePanel.java并复制了那里扩展LinearLayout的脚本,没有给我任何错误。我的attrs.xml也没有错误。
Eclipse在运行时没有给我任何错误。它运行并将其发送到我的手机很好。这就是力量关闭的地方。当我在main.xml中删除ExpandablePanel布局时,它运行并且是一个空的应用程序。
我真的无法理解。