5

Я использую Android Studio и создал свой собственный вид:Использование пользовательских атрибутов в пользовательских представлений в макете просмотра

<LinearLayout 
     xmlns:android="http://schemas.android.com/apk/res/android" 
     android:orientation="vertical" 
     android:gravity="center_horizontal|center_vertical" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_margin="4dp"> 

    <Button 
      android:id="@+id/dateTile" 
      android:layout_height="@dimen/date_tile_height" 
      android:layout_width="@dimen/date_tile_width" 
      android:background="@drawable/bg_january"/> 

    <CheckBox 
      android:id="@+id/dateTileCheckbox" 
      android:button="@drawable/check_green" 
      android:layout_width="30dp" 
      android:layout_height="30dp" 
      android:layout_marginLeft="15dp" 
      android:layout_marginTop="-20dp" 
      android:focusable="false"/> 

    <TextView 
      android:id="@+id/dateTileLabel" 
      android:layout_width="wrap_content" 
      android:layout_marginTop="-10dp" 
      android:layout_height="wrap_content"/> 

</LinearLayout> 

в дополнение я определил следующие пользовательские атрибуты

<resources> 
    <declare-styleable name="DateTileView"> 
     <attr name="monthLabel" format="string" localization="suggested" /> 
     <attr name="tileBackground" format="reference" /> 
    </declare-styleable> 
</resources> 

Я использую настраиваемые атрибуты для определения метки и фона плитки даты в конструкторе, подобном этому.

public class DateTileView extends LinearLayout 
{ 
//.... 
//.... 
public DateTileView(Context context, AttributeSet attrs) 
    { 
     super(context, attrs); 
     TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DateTileView, 0, 0); 

     String monthLabel = a.getString(R.styleable.DateTileView_monthLabel); 
     Drawable monthBG = a.getDrawable(R.styleable.DateTileView_tileBackground); 

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

     TextView dateTileLabel = (TextView) findViewById(R.id.dateTileLabel); 
     dateTileLabel.setText(monthLabel); 

     Button dateTileButton = (Button) findViewById(R.id.dateTile); 
     dateTileButton.setBackgroundDrawable(monthBG); //TODO: remove deprecated use if JELLY BEAN 

     a.recycle(); 
    } 
//... 
//... 
} 

при использовании даты плитки в другой XML я Получать эту ошибку:

The following classes could not be instantiated: 
- com.endilo.widget.DateTileView (Open Class, Show Exception) 
    Tip: Use View.isInEditMode() in your custom views to skip code 
    or show sample data when shown in the IDE 

Exception Details java.lang.NullPointerException   at 
com.endilo.widget.DateTileView.<init>(DateTileView.java:35)   at 
java.lang.reflect.Constructor.newInstance   at 
android.view.LayoutInflater.rInflate_Original   at 
android.view.LayoutInflater_Delegate.rInflate   at 
android.view.LayoutInflater.rInflate   at 
android.view.LayoutInflater.rInflate_Original   at 
android.view.LayoutInflater_Delegate.rInflate   at 
android.view.LayoutInflater.rInflate   at 
android.view.LayoutInflater.rInflate_Original   at 
android.view.LayoutInflater_Delegate.rInflate   at 
android.view.LayoutInflater.rInflate   at 
android.view.LayoutInflater.inflate   at android.view.LayoutInflater.inflate 

приложение работает нормально, но предварительный просмотр не будет. Есть ли способ загрузить пользовательские атрибуты, чтобы показать предварительный просмотр с помощью настраиваемых атрибутов?

+0

Та же проблема здесь, любое решение? –

ответ

-1

Вы не можете делать то, что у вас есть в строке 35, когда приложение не работает, потому что режим разработки получит нулевую ссылку для некоторого объекта, который создается только во время выполнения.

Вы должны избегать выполнения тех, кто в проектном режиме с использованием isInEditMode(), как здесь:

if(!isInEditMode()) { 
    whatever there is in the line 35 of your class 
} 

Если вам необходимо выполнить некоторые изменения в представлении, и вы хотите, чтобы это было видно на дизайнер, переопределить OnDraw(), как здесь:

@Override 
protected void onDraw(Canvas canvas) { 
    super.onDraw(canvas); 

    TypedArray a = this.getContext().obtainStyledAttributes(attrs, R.styleable.DateTileView, 0, 0); 

    String monthLabel = a.getString(R.styleable.DateTileView_monthLabel); 
    Drawable monthBG = a.getDrawable(R.styleable.DateTileView_tileBackground); 

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

    TextView dateTileLabel = (TextView) findViewById(R.id.dateTileLabel); 
    dateTileLabel.setText(monthLabel); 

    Button dateTileButton = (Button) findViewById(R.id.dateTile); 
    dateTileButton.setBackgroundDrawable(monthBG); //TODO: remove deprecated use if JELLY BEAN 

    a.recycle(); 
}