Правильный доступ к пользовательским атрибутам пользовательских LinearLayout
Так что я играюсь с андроидом и зашел в тупик.
Этот вопрос может быть связан с этим вопросом, так как его ответ мог бы стать хорошим решением для моей проблемы, но меня интересует причина сбоя моего кода. У меня могут быть некоторые серьезные неправильные представления о представлениях.
Итак, у меня есть эта доска для игры в нарды:
Я хочу выполнять анимацию при каждом движении, и для этого мне нужно получить координаты отправления и назначения движущегося чипа на экране.
Поэтому я должен быть уверен, что точки ведут себя как стеки, новые виды должны быть вставлены внизу перевернутых точек и сверху вниз. Поскольку гравитация любой точки равна ТОП или ВНИЗ, в зависимости от ее положения на экране, я смог бы сделать это, получив этот атрибут, но, похоже, он является закрытым: см. Этот ответ в соответствующем посте.
Итак, я создал собственный LinearLayout:
<resources>
<declare-styleable name="PointView">
<attr name="upsideDown" format="boolean" />
</declare-styleable>
</resources>
Что переопределяет LinearLayout
public class PointView extends LinearLayout {
private boolean mUpsideDown = false;
public PointView(Context context) {
super(context);
}
public PointView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs, 0);
}
public PointView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs, defStyle);
}
private void init(Context context, AttributeSet attrs, int defStyle) {
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PointView);
mUpsideDown = a.getBoolean(R.styleable.PointView_upsideDown, false);
a.recycle();
}
@Override
public View getChildAt(int index) {
return mUpsideDown ? super.getChildAt(index) : super.getChildAt(super.getChildCount() - index + 1);
}
@Override
public void addView(View child) {
if(mUpsideDown) {
super.addView(child);
}
else {
super.addView(child, 0);
}
}
}
Они включены в XML-файл моей активности следующим образом:
<spacebar.backgammoid.PointView
android:orientation="vertical"
android:layout_width="0dp"
android:layout_height="match_parent"
android:background="@drawable/black_point"
android:layout_weight="1"
android:focusableInTouchMode="false"
android:id="@+id/point13"
android:weightSum="5"
android:clipChildren="false"
android:gravity="top"
app:upsideDown="true"/>
Теперь, когда init() вызывается во время выполнения, я получаю исключение:
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.View.resolveLayoutParams()' on a null object reference
Похоже, мой контекст нулевой в:
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PointView);
И я понятия не имею, почему, и поэтому я не могу получить доступ к своему пользовательскому атрибуту upsideDown.
Пытаясь получить доступ к собственности от attrs:
attrs.getAttributeBooleanValue(R.styleable.PointView_upsideDown, false);
Что выглядит как синоним для меня, хотя это явно не так, всегда возвращает истину.
Любая идея?
заранее спасибо
[РЕДАКТИРОВАТЬ]
Трассировка стека исключения:
--------- beginning of crash
06-23 10:04:34.972 2036-2036/spacebar.backgammoid E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: spacebar.backgammoid, PID: 2036
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.View.resolveLayoutParams()' on a null object reference
at android.view.ViewGroup.resolveLayoutParams(ViewGroup.java:6116)
at android.view.ViewGroup.resolveLayoutParams(ViewGroup.java:6116)
at android.view.ViewGroup.resolveLayoutParams(ViewGroup.java:6116)
at android.view.ViewGroup.resolveLayoutParams(ViewGroup.java:6116)
at android.view.ViewGroup.resolveLayoutParams(ViewGroup.java:6116)
at android.view.ViewGroup.resolveLayoutParams(ViewGroup.java:6116)
at android.view.ViewGroup.resolveLayoutParams(ViewGroup.java:6116)
at android.view.ViewGroup.resolveLayoutParams(ViewGroup.java:6116)
at android.view.ViewGroup.resolveLayoutParams(ViewGroup.java:6116)
at android.view.ViewGroup.resolveLayoutParams(ViewGroup.java:6116)
at android.view.ViewGroup.resolveLayoutParams(ViewGroup.java:6116)
at android.view.View.setLayoutParams(View.java:11473)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:273)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:85)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3055)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2395)
at android.app.ActivityThread.access$800(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5257)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
[РЕДАКТИРОВАТЬ 2]
Я заполнял точки микросхемами программно, заполнение в XML-коде Activity вызывало то же исключение во время разработки.
<spacebar.backgammoid.PointView ...>
<ImageView ... />
</spacebar.backgammoid.PointView>
Тем не менее, если я использую обычные LinearLayouts вместо своего пользовательского представления, все работает нормально, и нет ошибки.
<LinearLayout ...>
<ImageView ... />
</LinearLayout>
Кроме того, я не знаю, насколько это актуально, но дизайнер Android-студии не позволяет мне вкладывать Views в мой PoinView:
1 ответ
Хорошо, я получил это работает
В моем коде есть две проблемы.
Девятый закон Мерфи: Природа всегда на стороне скрытого недостатка: это просто неправильно
вернуть mUpsideDown? super.getChildAt(index): super.getChildAt(super.getChildCount() - index + 1);
Я пытался получить доступ к двум позициям после окончания списка детей. Так должно быть
super.getChildAt(super.getChildCount() - (index + 1));
или же
super.getChildAt(super.getChildCount() - index - 1);
Это было причиной для исключения. Android пытался раздуть ноль в тот момент, когда заполнял мой LinearLayout.
Во-вторых,
@Override
public void addView(View child) {
if(mUpsideDown) {
super.addView(child);
}
else {
super.addView(child, 0);
}
}
Не работал, переопределение этого метода дает мне ожидаемое поведение, я думаю, android использует getChildAt() при накачке LinearLayouts, и, таким образом, я могу вставлять дочерние представления обычным образом, чтобы они складывались в верхней части точки независимо от ее ориентации.
То, как я получал доступ к своим настраиваемым атрибутам, было в порядке (что является ответом на мой вопрос в том виде, в каком он был сформулирован)
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PointView);
mUpsideDown = a.getBoolean(R.styleable.PointView_upsideDown, false);
a.recycle();
Спасибо, @Ravi Thapliyal, за ваш интерес