Как передать ссылку на просмотр пользовательского вида Android?

17

Я сделал следующее:

1) Создание стиля

<declare-styleable name="Viewee">
    <attr name="linkedView" format="reference"/>
</declare-styleable>

2) определение пользовательского макета представления

<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="#ffc0">
    <TextView
            android:id="@+id/custom_text"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="[text]"
            />
</LinearLayout>

3) Создание требуемого класса

public class Viewee extends LinearLayout
{
public Viewee(Context context, AttributeSet attributeSet)
{
    super(context, attributeSet);
    View.inflate(context, R.layout.viewee, this);
    TextView textView = (TextView) findViewById(R.id.custom_text);
    TypedArray typedArray = context.obtainStyledAttributes(attributeSet, R.styleable.Viewee);
    int id = typedArray.getResourceId(R.styleable.Viewee_linkedView, 0);
    if (id != 0)
    {
        View view = findViewById(id);
        textView.setText(((TextView) view).getText().toString());
    }

    typedArray.recycle();
}
}

и, наконец, в такой активности, как ниже

<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res/com.ns"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical">
    <TextView
            android:id="@+id/tvTest"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="android"/>
    <com.ns.Viewee
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            app:linkedView="@+id/tvTest"
            />
</LinearLayout>

теперь, хотя я получаю ненулевой id в Конкретаторе Viewee, findViewById(id) retuns null и NullPointerException .

что мне не хватает?

Я сделал это, как описано здесь     

задан anonim 14.06.2012 в 21:14
источник

3 ответа

17

Я нашел ответ!

Проблема была в findViewById(id) и где я ее назвал. findViewById ищет только детское представление, не существующее на уровне верхней иерархии, поскольку документация говорит , Поэтому я должен назвать что-то вроде getRootView().findViewById(id) , но также возвращает null becase, где я назвал его не корневым.

В Viewee constractor Viewee сама по себе не привязана к своему корню, так что вызов вызывает NullPointerException .

Итак, если я вызываю getRootView().findViewById(id) в другом месте после создания, он работает нормально, и оба "@+id/tvTest" и "@id/tvTest" верны. Я его протестировал!

ответ таков:

public class Viewee extends LinearLayout
{
    public Viewee(Context context, AttributeSet a)
    {
        super(context, attributeSet);
        View.inflate(context, R.layout.main6, this);
        TextView textView = (TextView) findViewById(R.id.custom_text);
        TypedArray t = context.obtainStyledAttributes(a, R.styleable.Viewee);
        int id = t.getResourceId(R.styleable.Viewee_linkedView, 0);
        if (id != 0)
        {
            _id = id;
        }

        t.recycle();
    }

    private int _id;

    public void Foo()
    {
        TextView textView = (TextView) findViewById(R.id.custom_text);
        View view = getRootView().findViewById(_id);
        textView.setText(((TextView) view).getText().toString());
    }
}

и Foo вызывается, когда требуется обработать прикрепленный вид через его ссылочный идентификатор где-то еще в вашей активности и т. п.

Кредит полностью передается тем парням, внесшим вклад в этот пост . Я не видел этого сообщения, прежде чем задавать вопрос.

    
ответ дан anonim 15.06.2012 в 00:14
источник
  • НЕ помещайте его в onDraw, а в onAttachedToWindow. Размещение его в onDraw будет называться X раз в секунду методом, может быть 60 раз в секунду. @DanielWilson вы можете удалить свой комментарий? –  Hugo Gresse 21.01.2016 в 17:36
8

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

Вместо того, чтобы звонить извне, другой способ получить представление выше в иерархии, я вместо этого подключился к onAttachedToWindow() :

public class MyCustomView extends LinearLayout {
    private int siblingResourceId;
    private View siblingView;

    public MyCustomView(Context context, AttributeSet a) {
        super(context, attributeSet);
        View.inflate(context, R.layout.main6, this);
        TextView textView = (TextView) findViewById(R.id.custom_text);
        TypedArray t = context.obtainStyledAttributes(a, R.styleable.Viewee);
        siblingResourceId = t.getResourceId(R.styleable.MyCustomView_siblingResourceId, 0);
        t.recycle();
    }

    @Override
    public void onAttachedToWindow() {
        super.onAttachedToWindow();
        if (siblingResourceId != 0) {
            siblingView = getRootView().findViewById(siblingId);
        }
    }
}

onAttachedToWindow называется довольно ранним, но, очевидно, достаточно поздно для того, чтобы вся иерархия представлений была решена. Он работает безупречно для моих потребностей и, по крайней мере, немного более контролируется и не нуждается в взаимодействии со стороны, чтобы работать; -)

    
ответ дан Darwind 20.01.2016 в 00:21
источник
2

Указанный android:id установлен в app:linkedView="@+id/tvTest . Однако @+id/tvTest используется для создания нового идентификатора с именем «tvTest». Вы хотите использовать app:linkedView="@id/tvTest .

    
ответ дан Jason L 14.06.2012 в 21:16
источник
  • Я применил ваш ответ, хотя View view = findViewById (id); все еще возвращает null! –  anonim 14.06.2012 в 22:21
  • Почему вы используете id для хранения идентификатора представления? Было бы довольно просто использовать R.id.foo вместо создания другой переменной. Кроме того, я не могу рассказать по вашему комментарию, изменили ли вы атрибут app: linkedView вашего элемента <com.ns.Viewee /> на «@ id / tvTest». –  Jason L 14.06.2012 в 22:55
  • Мне нужно удерживать идентификатор, потому что Viewee - это обычное представление, ссылающееся на другое представление для резонанса. Я не могу ссылаться на связанное представление как R.id.foo, как вы сказали. что, если я использую Viewee в другом макете, где R.id.foo не существует? Я также сделал так, как вы рекомендовали, и изменил «@ + id / tvTest» на «@ id / tvTest», но без успеха. –  anonim 14.06.2012 в 23:37
  • @ + id вместо @id не имеет значения, плюс знак в порядке –  Kamil Seweryn 24.09.2015 в 14:41