Пользовательский вид Android с кнопкой, не нажимаемой

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

Странно то, что я могу найти виды и изменить их видимость просто отлично.

Можно ли так нажимать на кнопку, или это нужно делать по-другому?

То, что я пробовал:

  • Анонимный внутренний класс для onClickListener
  • Атрибут XML для onClick
  • Посмотреть onClick с onClickListener(this)
  • Проверьте, кликабельно ли это с кодом (он возвращает true)
  • Добавлено clickable(true) как в XML, так и в код.
  • Частный контекст из конструктора вместо getContext()
  • Логика перемещена с init() на onFinishInflate()
  • Использовал вид из инфлятора, чтобы найти виды
  • Переключиться с inflate() на LayoutInflater

Раздутый пользовательский вид:

<?xml version="1.0" encoding="utf-8"?>
<merge
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/internet_view_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="@string/internet_offline"/>

    <custom.IconView
        android:id="@+id/internet_view_icon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="ICON"
        android:visibility="invisible"
        android:layout_below="@+id/internet_view_text"/>

    <Button
        android:id="@+id/internet_view_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="BUTTON"
        android:clickable="true"
        android:layout_below="@+id/internet_view_text"/>
</merge>

Соответствующая часть родительского представления:

<custom.NoInternetView
    android:id="@+id/webview_no_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:visibility="invisible"
    app:automaticReconnect="false"/>

Файл класса:

public class NoInternetView extends RelativeLayout implements View.OnClickListener {

    private static final String TAG = NoInternetView.class.getSimpleName();

    private static ConnectivityChangeListener listener;
    private static boolean automaticReconnect;
    private Context mContext;
    private View view;

    private Button button;

    public NoInternetView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.NoInternetView, defStyleAttr, 0);
        automaticReconnect = a.getBoolean(R.styleable.NoInternetView_automaticReconnect, false);
        a.recycle();
        init();
    }

    public NoInternetView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public NoInternetView(Context context) {
        this(context, null);
    }

    @Override
    protected void onFinishInflate() {
        Log.d(TAG, "onFinishInflate");
        super.onFinishInflate();

        button = (Button) view.findViewById(R.id.internet_view_button);
        button.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d(TAG, "Clicked on some Button");
                if (listener != null && NetworkHelper.hasAccess(getContext())) {
                    listener.connected();
                }
            }
        });
        button.setClickable(true);

        boolean clicked = button.callOnClick();
        Log.d(TAG, "clicked: "+clicked);

        TextView text = (TextView) view.findViewById(R.id.internet_view_icon);
        text.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d(TAG, "Clicked on some TextView");
                if (listener != null && NetworkHelper.hasAccess(getContext())) {
                    listener.connected();
                }
            }
        });

        //check if the attribute 'automaticReconnect' is set to true
        //if so, show an icon instead of a button
        if (automaticReconnect){
            button.setVisibility(INVISIBLE);
            view.findViewById(R.id.internet_view_icon).setVisibility(VISIBLE);
        }

    }

    public void init(){
        Log.d(TAG, "init");
        view = LayoutInflater.from(mContext).inflate(R.layout.no_internet_view, this, false);
    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        Log.d(TAG, "something happened?");
        return super.dispatchKeyEvent(event);
    }

    @Override
    public void onClick(View v) {
        Log.d(TAG, "Clicked on Button(TextView)");
        if (listener != null && NetworkHelper.hasAccess(getContext())){
            listener.connected();
        }
    }

person Lars Celie    schedule 20.10.2015    source источник
comment
Почему вы используете тег слияния здесь? Макет, который вы используете здесь, предназначен только для надувания в CustomView, здесь слияние не требуется. Это работает, если вы замените слияние типом макета.   -  person Henry    schedule 20.10.2015
comment
@ Генри Я использовал тег слияния, потому что прочитал эту ссылку который показывает дополнительный макет в иерархии, когда вы не используете теги слияния. Также, когда я меняю слияние на RelativeLayout, мой TextView и Button не видны.   -  person Lars Celie    schedule 20.10.2015
comment
Дай мне пару часов. Я отлаживаю его и дам вам знать.   -  person Henry    schedule 20.10.2015
comment
Я использовал тег ‹merge› и получил исключение при раздувании. Пожалуйста, обратитесь к этому, чтобы понять, почему не использовать ‹merge›: stackoverflow.com/questions/14039162/   -  person Henry    schedule 20.10.2015
comment
Однако я не получил сообщения об ошибке при слиянии.   -  person Lars Celie    schedule 20.10.2015


Ответы (1)


Так что я заставил его работать. Вот что я сделал, чтобы заставить его работать.

  1. Замените тег merge на RelativeLayout, потому что вы увеличиваете макет, чтобы показать его внутри представления. Дополнительная информация здесь: Ошибка макета слияния Android xml при раздувании

  2. Вы установили android:visibility="invisible", измените его на android:visibility="visible" (это просто для того, чтобы представление было видимым, позже вы можете изменить его программно)

  3. Добавьте приведенную ниже строку в метод init() вашего NoInternetView. Вы наполняете макет всеми представлениями, но только когда добавите это представление, вы сможете его увидеть.

    public void init(){
           Log.d(TAG, "init");
           view = LayoutInflater.from(mContext).inflate(R.layout.no_internet_view, this, false);
           this.addView(view);}
    

Как только вы закончите с этим, кнопка будет видна, и нажатие на кнопку будет доступно для нажатия. Вы можете либо использовать анонимный onClickListener, либо заставить представление реализовать onClickListener и переопределить метод onClick(). Все работает.

person Henry    schedule 20.10.2015
comment
this.addView(view) вызовет цикл и, в конечном итоге, исключение Out of Memory. - person Lars Celie; 20.10.2015
comment
Не совсем. Вы создали CustomView, это RelativeLayout. Вам нужно что-то показать на экране, поэтому вы раздуваете макет в CustomView. Проблема в том, что одного надувания недостаточно. Вам нужно добавить это завышенное представление в CustomView. Я думаю, что вы делаете что-то не так где-то в другом месте. Я запустил ваш код после внесения всех этих изменений. У меня работает нормально. - person Henry; 20.10.2015
comment
Имеет ли значение, что этот макет загружается в макет фрагмента? - person Lars Celie; 20.10.2015
comment
Нет, это не должно иметь никакого значения. - person Henry; 20.10.2015
comment
я не вижу журнал «onFinishInflate», а последний журнал — «Init». Почему-то это вызывает петлю. Мой текущий макет выглядит так: Активность -> фрагмент -> пользовательский макет - person Lars Celie; 20.10.2015
comment
В этом случае мне нужно просмотреть весь код, чтобы понять, что не так. - person Henry; 20.10.2015
comment
Давайте продолжим это обсуждение в чате. - person Lars Celie; 20.10.2015