1

Я создал пользовательский вид для Android, который отображает два внутренних вида для хранения ключа и значения в двух столбцах. Класс выглядит следующим образом:NumberFormatException при использовании стилевых атрибутов

public class KeyValueRow extends RelativeLayout { 

    protected TextView mLabelTextView; 
    protected TextView mValueTextView; 

    public KeyValueRow(final Context context) { 
     super(context); 
     init(context, null, 0); 
    } 

    public KeyValueRow(final Context context, final AttributeSet attrs) { 
     super(context, attrs); 
     init(context, attrs, 0); 
    } 

    public KeyValueRow(final Context context, 
         final AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
     init(context, attrs, defStyle); 
    } 

    protected void init(final Context context, 
         final AttributeSet attrs, int defStyle) { 
     View layout = ((LayoutInflater) context 
      .getSystemService(Context.LAYOUT_INFLATER_SERVICE)) 
      .inflate(R.layout.key_value_row, this, true); // line 46 
     mLabelTextView = (TextView) layout.findViewById(
      R.id.key_value_row_label); 
     mValueTextView = (TextView) layout.findViewById(
      R.id.key_value_row_value); 
    } 

    public void setLabelText(final String text) { 
     mLabelTextView.setText(text); 
    } 

    public void setValueText(final String text) { 
     mValueTextView.setText(text); 
    } 

} 

связанный файл макет макет/key_value_row.xml выглядит следующим образом:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:orientation="horizontal" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:weightSum="1.0"> 

    <TextView 
     android:id="@+id/key_value_row_label" 
     style="@style/KeyValueLabel" 
     android:layout_weight=".55" 
     tools:text="Label"/> 

    <TextView 
     android:id="@+id/key_value_row_value" 
     style="@style/KeyValueValue" 
     android:layout_weight=".45" 
     tools:text="Value"/> 

</LinearLayout> 

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

<com.example.myapp.customview.KeyValueRow 
    android:id="@+id/foobar" 
    style="@style/KeyValueRow" /> 

Пока здесь все не работает!

Задача

Теперь я хочу, чтобы пользовательские настройки для layout_weight атрибутов обоих внутренних TextView с. Поэтому я подготовил атрибуты в значений/attrs.xml:

<?xml version="1.0" encoding="utf-8"?> 
<resources> 
    <declare-styleable name="KeyValueRow"> 
     <attr name="label_layout_weight" format="float" /> 
     <attr name="value_layout_weight" format="float" /> 
    </declare-styleable> 
</resources> 

Первый вопрос будет: это поплавок правильный формат для layout_weight?
Далее, я бы применить их в файле макета:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:orientation="horizontal" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:weightSum="1.0"> 

    <TextView 
     android:id="@+id/key_value_row_label" 
     style="@style/KeyValueLabel" 
     android:layout_weight="?label_layout_weight" 
     tools:text="Label"/> 

    <TextView 
     android:id="@+id/key_value_row_value" 
     style="@style/KeyValueValue" 
     android:layout_weight="?value_layout_weight" 
     tools:text="Value"/> 

</LinearLayout> 

Тогда они могут быть использованы в примере:

<com.example.myapp.customview.KeyValueRow 
    android:id="@+id/foobar" 
    style="@style/KeyValueRow" 
    custom:label_layout_weight=".25" 
    custom:value_layout_weight=".75" /> 

Когда я запускаю эту реализацию следующее исключение брошено:

Caused by: java.lang.NumberFormatException: Invalid float: "?2130772062" 
    at java.lang.StringToReal.invalidReal(StringToReal.java:63) 
    at java.lang.StringToReal.parseFloat(StringToReal.java:310) 
    at java.lang.Float.parseFloat(Float.java:300) 
    at android.content.res.TypedArray.getFloat(TypedArray.java:288) 
    at android.widget.LinearLayout$LayoutParams.<init>(LinearLayout.java:1835) 
    at android.widget.LinearLayout.generateLayoutParams(LinearLayout.java:1743) 
    at android.widget.LinearLayout.generateLayoutParams(LinearLayout.java:58) 
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:757) 
    at android.view.LayoutInflater.inflate(LayoutInflater.java:492) 
    at android.view.LayoutInflater.inflate(LayoutInflater.java:397) 
    at com.example.myapp.customview.KeyValueRow.init(KeyValueRow.java:46) 
    at com.example.myapp.customview.KeyValueRow.<init>(KeyValueRow.java:28) 
    ... 33 more 
+0

Похоже, вы не определяете, являются ли значения удвоенными или плавают, но удваивается по умолчанию. Double - 64 бита, float 32, поэтому вы получаете исключение. Или измените все, чтобы удвоить или указать значения как float. –

+0

@ user3427079 Это определение float: '' недостаточно? – JJD

+0

Я думаю, что это на самом деле то, что вызывает проблему. Ожидается, что поплавок будет указан в атрибутах, но то, что фактически передано, является двойным. Возможно, NumberFormatException вызвано помещением большего размера в меньший квадрат, поскольку он передается как String, а затем напрямую применяется к Float, но String также имеет 64 бита. Другой путь будет пойман автобоксированием. Если вы измените их, чтобы удвоить или указать значения, которые вы передаете как float, я думаю, что это должно сработать. Например, попробуйте 1.0f для веса. Я не знаю, как обрабатывается внутренняя атрибуция андроида, надеюсь, что это сработает. –

ответ

1

Вы можете использовать

private void applyAttributes(Context context, AttributeSet attrs) { 
    TypedArray a = context.getTheme().obtainStyledAttributes(
     attrs, R.styleable.KeyValueRow, 0, 0); 
    try { 
     labelWeight = a.getFloat(
      R.styleable.KeyValueRow_label_layout_weight, 0.55f); 
     valueWeight = a.getFloat(
      R.styleable.KeyValueRow_value_layout_weight, 0.45f); 
    } finally { 
     a.recycle(); 
    } 
} 

и после этого вы можете применить это с помощью:

mLabelTextView = (TextView) layout.findViewById(R.id.key_value_row_label); 
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
    LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, labelWeight); 
mLabelTextView.setLayoutParams(layoutParams); 

Чтобы получить это бегущий заменить android:layout_weight="?label_layout_weight" со значением некоторого умолчанию, такие как android:layout_weight="0.5" в layout/key_value_row.xml. Он будет перезаписан.

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