【问题标题】:Android Extends Button - Accessing Members from Java to XMLAndroid 扩展按钮 - 访问成员从 Java 到 XML
【发布时间】:2014-08-29 07:46:27
【问题描述】:

我是 android 编程新手,想扩展一个按钮类,以便可以向按钮添加自定义字段,然后根据字段更改按钮的显示方式。我已经完成了一些教程,有一个很好的 bash 并且有一些可以编译但不起作用的东西 - 所以我正在寻找关于我哪里出错的提示。

我想要实现的目标比我的示例更复杂,但是一旦我可以让这个示例运行,我想我会很好地完成其余的工作。

对于我的示例,我想要一个具有 isRed 布尔成员/属性的按钮。如果设置了成员,则我们将按钮上的可绘制矩形更改为红色,如果为假,则可绘制为绿色。

为此,我有:

  • 在我的 res/drawable 目录中创建了一个 redbutton.xml 文件。此文件包含一个选择器,该选择器提供红色或绿色矩形,具体取决于 isRed 状态。
  • 在我的 src/com.example.redbutton 目录中创建了一个 RedButton.java 文件。此文件包含一个扩展 Button 的 RedButton 类
  • 在我的 res/values 目录中创建了一个 attrs.xml 文件。这列出了 isRed 成员/属性
  • 在我的主布局中放置两个按钮。一个按钮将 custom:isRed 设置为 true,另一个按钮将 isRed 设置为 false。

理论上,我的应用程序中应该有两个按钮,一个红色,一个绿色。不幸的是,我有两个绿色按钮!我似乎无法获得

<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>

【问题讨论】:

标签: java android button android-custom-view extends


【解决方案1】:

你的问题很不清楚。我现在能做的最多的就是猜测你想要达到的目标。

您是否想要一个按钮在未按下时具有默认颜色,然后变为红色或绿色?如果是这样,那么这里有一个示例应用供您使用。

该应用程序有 3 个按钮:一个名为红色,一个名为绿色,一个名为开关。按红色和绿色可查看背景从默认颜色变为所选颜色。如果按下开关,按钮将变为相反的颜色(从绿色变为红色;或从红色变为绿色)

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 类。那是因为如果您尝试使用通用的Button 类,您将获得ClassCastException。更多信息请参考this

<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;
    }
}

试试代码,看看是否是你想要的。

【讨论】:

  • 感谢您的提示。您的示例代码非常有帮助,它帮助我意识到我无法使用 xml 实现我想要的,我需要用 java 编写它。我现在已经为我的问题写了一个解决方案。再次感谢,非常感谢
【解决方案2】:

对于您要完成的工作,我有一些设计上的顾虑。首先,你为什么要创建一个 RedButton 类,清楚地表明它是一个红色按钮,然后让它不仅不是红色,而且是绿色?为什么没有 RedButton 和 GreenButton?更少的混乱和更清晰的目的。

其次,选择器依赖于 Android 框架定义的按钮状态。你不能在那里注入你自己的自定义类型并期望它知道你在说什么。您当然可以在自定义 Button 构造函数中将背景设置为适当的颜色,并在您的设置器中适当地更改它,但我不建议这样做。

【讨论】:

  • 谢谢克里斯托弗,是的 - 你是正确的,有一个红色或绿色的红色按钮令人困惑 - 我应该把它写成一个 red_green 按钮。我真的只是把这个例子写成一个简单的方法来展示我的问题。问题是我正在尝试拥有一个扩展按钮的类,该类具有可以更改的状态,然后根据其状态更改按钮的显示方式。但你可能对我的问题有答案。我可以使用带有自定义字段的选择器吗?如果没有,那我会用什么代替?
  • 你试图代表的“状态”是什么?
  • 感谢您对选择器的帮助和建议。我确实在网上找到了一些代码,这些代码允许您覆盖选择器类并添加自己的状态,但我认为最好只创建红色按钮可绘制对象、绿色按钮可绘制对象,并使用 java 切换可绘制对象,而不是xml。感谢您的帮助,非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-09-16
  • 1970-01-01
  • 1970-01-01
  • 2020-06-15
  • 2015-04-02
  • 1970-01-01
相关资源
最近更新 更多