5

我在stackoverflow上找到了自定義LinearLayout的示例,但當我嘗試運行它時會引發錯誤,有人會發現它有什麼問題嗎?解析XML時出錯:自定義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> 

Activity類:

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: Unable to start activity ComponentInfo{com.example.androidapp.widgets/com.example.androidapp.widgets.GoodPanelsActivity}: android.view.InflateException: Binary XML file line #9: Error 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) Caused by: java.lang.IllegalArgumentException: The handle attribute is required and must refer to a valid child. at com.example.androidapp.widgets.ExpandablePanel.(ExpandablePanel.java:39)

回答

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下。

乾杯。

+0

接受你的回答,即使你發佈了它 – 2012-01-06 16:21:37

+0

謝謝,不允許我接受它,20小時後會接受 – 2012-01-06 16:50:14

0

您需要添加包含該類com.example.androidapp.widgets.ExpandablePanel到項目中的項目buildpath。如果這不是一個開源項目,或者源代碼不可用,則無法執行此操作。

如果您確實有這個項目,並且它是一個LibraryProject您應該右鍵單擊您的Project->Properties->Android並在Library部分添加該項目。

如果是正常的Project只需去Properties->Java Build Path->Projects並從那裏添加該項目。

+0

類ExpandablePanela是我的項目的一部分,它不是一個外部類。 – 2012-01-05 13:51:46

+0

好的。也許你在構造函數中有錯誤...從logcat中粘貼更多。 – 2012-01-05 13:57:26

+0

我已經更新了我的問題,更多logcat日誌,請找到它。 – 2012-01-05 14:05:06

-1

我也在嘗試這個腳本,因爲我是Android編程的新手,我正在尋找一些很好的示例來學習。

當我將佈局添加到main.xml時,我的app force關閉。

當我爲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佈局時,它運行並且是一個空的應用程序。我真的搞不清楚。

相關問題