如何获得以编程方式扩展RelativeLayout的自定义组件?

时间:2015-02-13 14:54:28

标签: android android-layout android-activity

成为Android的新手,以下问题让我发疯,而无法通过谷歌答案表明解决方案非常简单......

我尝试从代码中将自定义组件(ArticleView extends RelativeLayout)添加到ViewGroupLinearLayout),但我无法访问{{1}对象,尝试强制转换它只是抛出一个

ArticleView

在我的java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.eo.read/com.example.eo.read.ArticleInfoActivity}: java.lang.ClassCastException: android.widget.RelativeLayout cannot be cast to com.example.eo.read.view.ArticleView Caused by: java.lang.ClassCastException: android.widget.RelativeLayout cannot be cast to com.example.eo.read.view.ArticleView at com.example.eo.read.ArticleInfoActivity.onCreate(ArticleInfoActivity.java:44) 课程中,我做了:

Activity

(简化)package com.example.eo.read; import android.content.Context; import android.content.Intent; import android.support.v7.app.ActionBarActivity; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.widget.LinearLayout; import android.widget.RelativeLayout; import com.example.eo.read.content.Article; import com.example.eo.read.content.ArticleDB; import com.example.eo.read.view.ArticleView; ... protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_article_info); _article = ArticleDB.getInstance().getArticle("test"); LayoutInflater inflater = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); //get the linear layout into which the ArticleView is going LinearLayout container = (LinearLayout) findViewById(R.id.recommendation_container); //get the custom component RelativeLayout ra = (RelativeLayout)inflater.inflate(R.layout.article_view, container, false); //this causes the classcast exception, although this RelativeLayout really should be an ArticleView ((ArticleView)ra).setArticle(_article); //adding the ArticleView to the container works fine, and the customizations //I have made in ArticleView are visible, so indeed it seems ra is an ArticleView ?? container.addView(ra); }

article_view.xml

活动的布局包含要插入<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="260dp" android:layout_height="wrap_content" android:background="@drawable/stroked_grey_plate"> <TextView android:id="@+id/title" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginLeft="8dp" android:layout_marginTop="8dp" android:textSize="16sp" android:text="Sample text" android:textColor="#111111" android:scrollHorizontally="true" android:ellipsize="end" android:maxLines="1" /> </RelativeLayout> 的id / recommedation_container。下面也是以声明方式插入的相同视图,仅为了清楚起见:

ArticleView

<LinearLayout android:id="@+id/recommendation_container" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" android:layout_marginLeft="10dp"> <com.example.eo.read.view.ArticleView android:layout_width="wrap_content" android:layout_height="wrap_content" custom:titleText="my title text" /> </LinearLayout> 类基本上是:

ArticleView

所以,我的问题很多......为什么我不能这样做:

package com.example.eo.read.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet; 
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.example.eo.read.R;
import com.example.eo.read.content.Article;

public class ArticleView extends RelativeLayout {
private TextView _titleView;
private Article _article;

public ArticleView(Context context) {
    this(context,null);
}

public ArticleView(Context context, AttributeSet attrs) {
    super(context, attrs);
    TypedArray a = context.obtainStyledAttributes(attrs,
            R.styleable.ArticleView, 0, 0);

//in the case where the ArticleView is declared in XML the title is retreived from a custom attribute, this works fine.    
String titleText = a.getString(R.styleable.ArticleView_titleText);

    a.recycle();

    LayoutInflater inflater = (LayoutInflater) context
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    inflater.inflate(R.layout.article_view, this, true);

    ViewGroup rl = (ViewGroup)getChildAt(0); //get the RelativeLayout

    _titleView = (TextView) rl.getChildAt(0);
    _titleView.setText(titleText);

} 

//in the case where the ArticleView is initiated from code the title should be set by calling this method, 
//which I never can reach since I cannot get to this ArticleView object from my activity :-(
//I realize this class is maybe not fully functional yet but first step is to actually be able to initiate it...
public void setArticle(Article a) {
    _article = a;
    _titleView.setText(_article.getTitle());
}
}

我该怎么办才能到达ArticleView ra = (ArticleView)inflater.inflate(R.layout.article_view, container, false);

2 个答案:

答案 0 :(得分:1)

使用ArticleView

替换XML文件中的[packagename].ArticleView

例如,如果ArticleView中包含com.john.article类,则ArticleView应替换为com.john.article.ArticleView

答案 1 :(得分:0)

如果我理解正确,您希望以编程方式添加自定义视图,而不是在XML中定义它?

如果是这种情况,如果您只是这样做会发生什么:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_article_info);

    _article = ArticleDB.getInstance().getArticle("test");

    LayoutInflater inflater = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    //get the linear layout into which the ArticleView is going
    LinearLayout container = (LinearLayout) findViewById(R.id.recommendation_container);

    //get the custom component
    ArticleView av = new ArticleView(this);


    av.setArticle(_article);


    container.addView(av);

}

如果您还没有偶然发现它,这个博客似乎有一些关于自定义视图的好建议:http://trickyandroid.com/protip-inflating-layout-for-your-custom-view/

如果您希望自定义视图与布局一起膨胀,则可以执行以下操作:

<LinearLayout
      android:id="@+id/recommendation_container"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:orientation="vertical"
      android:layout_marginLeft="10dp">
    <com.example.eo.read.view.ArticleView
      android:id="@+id/article" 
         android:layout_width="wrap_content" android:layout_height="wrap_content"
         custom:titleText="my title text"
     />
</LinearLayout>

以您的问题中的XML为例,不确定它是否适合您的情况。

但是现在,将上面的XML扩展到一个名为root的视图,然后执行root.findViewById(R.id.article)应该返回一个可以强制转换为ArticleView的视图。

考虑一下,如果您有这样的XML文件:

    <com.example.eo.read.view.ArticleView
         android:layout_width="wrap_content" android:layout_height="wrap_content"
         custom:titleText="my title text"
     />

你实际应该可以在尝试时对其进行充气,然后转换为ArticleView,因为com.example.eo.read.view.ArticleView现在是布局的根目录。