2015-02-13 2 views
0

Будучи новым для Android следующий вопрос сводит меня с ума, и не будучи в состоянии Google ответ указывает на то, что решение действительно просто ...Как получить настраиваемый компонент, который программно расширяет RelativeLayout?

Я пытаюсь добавить пользовательский компонент (ArticleView расширяет RelativeLayout) к ViewGroup (LinearLayout) из кода, но я не могу получить доступ к 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); 

} 

The (упрощенный) 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> 

Схема для деятельности содержит идентификатор/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); 

и что я должен делать, чтобы добраться до моего ArticleView?

+0

Что происходит, когда вы делаете «ArticleView ra = (ArticleView) inflater.inflate (R.layout.recommended_article_view, container, false);'? Это должно быть хорошо, чтобы сделать это так ... – vinitius

+0

не могли бы вы показать мне импорт? –

+0

Теперь я нахожусь в автобусе, поэтому не могу показать импорт, но заметьте, что пользовательский компонент добавлен просто отлично в родительский макет и отображается как указано в его макете. Не означает ли это, что импорт в порядке? Что касается имен пакетов, я удалил их (может быть, плохую идею), чтобы сделать код более удобным для чтения. Но они верны, я верю (так как все, кроме работы гаста) – jola

ответ

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 теперь является корнем макета.

+0

Это прекрасно работает! Благодарю. Есть ли какие-либо дополнительные преимущества, делая это так, как я изначально пытался это сделать (инициируя объект через layoutinflater) вместо того, чтобы делать это, как вы предлагаете? Если нет, я могу просто сделать это таким образом. – jola

+0

Ну, в зависимости от случая использования, я думаю. Если вы хотите создать несколько расширенных настраиваемых представлений с множеством настраиваемых атрибутов, было бы лучше просто определить все это в XML вместо того, чтобы создавать и вставлять представление программно. – cYrixmorten

+0

Сделал некоторые изменения для моего ответа – cYrixmorten

1

Заменить ArticleView в файле XML с [packagename].ArticleView

Например, если ваш ArticleView класс содержится в com.john.article, то ваш ArticleView следует заменить com.john.article.ArticleView.

+0

да, я использую имена пакетов, я просто удалил его в примере, чтобы сделать его более читаемым, но я добавил его сейчас. Однако это не является причиной сбоя. – jola

Смежные вопросы