Кнопка Android расширяет - доступ к членам из Java в XML

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

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

Для моего примера я бы хотел, чтобы кнопка имела логический член / атрибут isRed. Если элемент задан, то мы меняем нарисованный прямоугольник на кнопке на красный цвет, если он ложный, то нарисованный зеленый.

Для этого у меня есть:

  • создал файл redbutton.xml в моей директории res / drawable. Этот файл состоит из селектора, который предоставляет красный или зеленый прямоугольник, в зависимости от состояния isRed.
  • создал файл RedButton.java в моем каталоге src / com.example.redbutton. Этот файл содержит класс RedButton, расширяющий Button
  • создал файл attrs.xml в моей директории res / values. Это перечисляет член / атрибуты isRed
  • поставить две кнопки в моем основном макете. Одна кнопка имеет значение custom: для isRed установлено значение true, для другой - значение isRed.

В теории у меня должно быть две кнопки в приложении: красная, зеленая. К сожалению, у меня есть две зеленые кнопки! Я не могу получить

<item custom:isRed="true"> 

в redbutton.xlm для оценки истинности. Однако, если я изменю эту строку на

<item android:state_pressed="true">

тогда у меня есть красная кнопка всякий раз, когда я нажимаю кнопку. Мне кажется, проблема в том, что доступ к моему настраиваемому полю всегда оценивается как ложный!

Ниже приведен код, который я написал. Кто-нибудь может дать мне несколько советов о том, что я сделал неправильно?

redbutton.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:custom="http://schemas.android.com/apk/res/com.example.redbutton" >

<!-- if the isred value is true, then make the background red -->
<!--    <item android:state_pressed="true"> --> 
     <item custom:isred="true" >  
             <shape android:shape="rectangle"  >
             <size android:width="100dp"
                android:height="100dp"/>
             <solid  android:color="#ff0000"/>             
         </shape>
     </item>
<!-- otherwise make it green -->
    <item >
        <shape android:shape="rectangle"  >
             <size android:width="100dp"
                android:height="100dp"/>
            <solid  android:color="#00ff00"/>       
         </shape>
     </item>
</selector>  

RedButton.java

package com.example.redbutton;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.widget.Button;

public class RedButton extends Button
{

    private boolean mIsRed;

    public RedButton (Context context, AttributeSet attrs) {
        super(context, attrs);

        TypedArray a = context.getTheme().obtainStyledAttributes(
                attrs,
                R.styleable.RedButton,
                0, 0);

           try {
               mIsRed = a.getBoolean(R.styleable.RedButton_isred, false);
           } finally {
               a.recycle();
           }
    }


    //sets and gets for members
    public boolean getIsRed() 
    {
        return mIsRed;
    }

    public void setIsRed(boolean isRed) 
    {
        mIsRed =  isRed;
    }
}

attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="RedButton">
        <attr name="isred" format="boolean" />
    </declare-styleable>
</resources> 

fragment_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:custom="http://schemas.android.com/apk/res/com.example.redbutton"
    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.redbutton.MainActivity$PlaceholderFragment" >

    <com.example.redbutton.RedButton 
                android:id="@+id/Button1"
                android:layout_width="0dp"
                android:layout_height="fill_parent"
                android:layout_weight="1"
                android:text="RedButton"
                android:textSize="30sp" 
                custom:isred="true" 
                android:drawableBottom="@drawable/redbutton"              
    />
    <com.example.redbutton.RedButton 

                android:id="@+id/Button2"
                android:layout_width="0dp"
                android:layout_height="fill_parent"
                android:layout_weight="1"
                android:text="GreenButton"
                android:textSize="30sp" 
                custom:isred="false"              
                android:drawableBottom="@drawable/redbutton"
    />
</LinearLayout>

2 ответа

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

Вы хотите иметь кнопку, которая имеет цвет по умолчанию, когда она еще не нажата, а затем меняется на красный или зеленый? Если это так, то вот пример приложения для вас.

Приложение имеет 3 кнопки: одну с именем Red, одну с именем Green и одну с именем switch. Нажмите Красный и Зеленый, чтобы увидеть изменение фона со стандартного на выбранный цвет. Если вы нажмете переключатель, кнопка изменит цвет на противоположный (с зеленого на красный или с красного на зеленый)

package com.example.buttontest;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.Button;

public class ColoredButton extends Button {

    private boolean isRed = true;

    public ColoredButton(Context context) {
        super(context);
    }

    public ColoredButton(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ColoredButton(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public void setIsRed(boolean isRed) {
        this.isRed = isRed;
        changeBgColor();
    }

    private void changeBgColor() {
        setBackgroundResource(isRed ? R.drawable.bg_red : R.drawable.bg_green);
        setText(isRed? "Red" : "Green");
    }

}

файл main.xml: обратите внимание, что тег xml для красной и зеленой кнопок ссылается на ColoredButton учебный класс. Это потому, что вы собираетесь получить ClassCastException если вы попытаетесь использовать общий Button учебный класс. обратитесь к этому для получения дополнительной информации.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.buttontest.MainActivity" >

    <com.example.buttontest.ColoredButton
        android:id="@+id/btnRed"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Red" />

    <com.example.buttontest.ColoredButton
        android:id="@+id/btnGreen"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Green" />

    <Button
        android:id="@+id/btnSwitch"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Switch Color" />

</LinearLayout>

Теперь вам нужно создать два отдельных нарисованных XML-файла. Как сказал Кристофер, вы не можете просто создавать теги XML самостоятельно. Android не распознает их.

<?xml version="1.0" encoding="utf-8"?>
<!-- Name this file bg_green.xml -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_pressed="true"><color android:color="#00ff00" />
    </item>
    <item android:drawable="@android:drawable/btn_default"></item>

</selector>

<?xml version="1.0" encoding="utf-8"?>
<!-- Name this file bg_red.xml -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_pressed="true"><color android:color="#ff0000" />
    </item>
    <item android:drawable="@android:drawable/btn_default"></item>

</selector>

Основное направление деятельности:

package com.example.buttontest;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity implements OnClickListener {

    ColoredButton btnRed;
    ColoredButton btnGreen;
    Button btnSwitch;

    boolean switched = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initButtons();
    }

    private void initButtons() {
        btnRed = (ColoredButton) findViewById(R.id.btnRed);
        btnGreen = (ColoredButton) findViewById(R.id.btnGreen);

        btnRed.setIsRed(true);
        btnGreen.setIsRed(false);

        btnSwitch = (Button) findViewById(R.id.btnSwitch);
        btnSwitch.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        btnRed.setIsRed(switched);
        btnGreen.setIsRed(!switched);

        switched = !switched;
    }
}

Попробуйте код и посмотрите, хотите ли вы этого.

У меня есть несколько проблем с дизайном, которые вы пытаетесь достичь. Во-первых, зачем создавать класс RedButton, в котором четко указано, что это красная кнопка, а затем разрешать ему не только быть красным, но и зеленым? Почему бы не иметь RedButton и GreenButton? Гораздо меньше путаницы и более четкая цель.

Во-вторых, селекторы работают от состояний кнопок, определенных платформой Android. Вы не можете ввести свой собственный тип и ожидать, что он будет знать, о чем вы говорите. Вы, конечно, можете установить соответствующий цвет фона в своем собственном конструкторе Button, а также соответствующим образом изменить его в своем установщике, но я советую против этого.

Другие вопросы по тегам