Как передать ссылку на просмотр пользовательского вида Android?
Я сделал следующее:
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
.
что мне не хватает?
Я сделал это, как описано здесь
Ответы
Ответ 1
Я нашел ответ!
Проблема была с 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
вызывается, когда требуется обработать прикрепленный вид через его ссылочный идентификатор где-то еще в вашей деятельности и т.п.
Кредит полностью передается тем парням, которые внесли вклад в этот пост. Я не видел этого сообщения, прежде чем задавать вопрос.
Ответ 2
Я знаю, что это старый вопрос, но я думал, что добавлю еще один способ сделать это, поскольку я хотел инкапсулировать все в свой пользовательский вид.
Вместо вызова извне, другой способ получить представление выше в иерархии, я вместо этого подключился к 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
называется довольно ранним, но, очевидно, достаточно поздно для того, чтобы вся иерархия представлений была улажена. Он работает безупречно для моих потребностей и, по крайней мере, немного более контролируется и не нуждается в взаимодействии со стороны, чтобы работать; -)
Ответ 3
Ваш описанный android:id
установлен на app:linkedView="@+id/tvTest
. Однако @+id/tvTest
используется для создания нового идентификатора с именем "tvTest". Вы хотите использовать app:linkedView="@id/tvTest
.