精华内容
下载资源
问答
  • 常见控件对象
    千次阅读
    2020-07-16 10:18:13

    QT中最常用的控件QPushButton(按钮)、QLineEdit(文本框)、QRadioButton(单选框)、QCheckBox(复选框)、QFrame(一般用作容器控件,配合布局)、QProgressBar(进度条控件)这些控件的使用方法都非常简单,查一下帮助文档就可以搞定,下面的章节中,我们会讲解另外的一些控件的常用但是却不是很容易找到的功能。

    QVariant 类型
    再讲解其他控件之前,我们需要先了解Qt中的QVariant类型,为什么呢,因为需要为控件绑定数据,就离不开对QVariant类型的了解,下面章节中我们要说到的一些控件,在绑定数据的时候就会使用QVariant类型。他除了可以包裹Qt中常见的QString,int等类型之外,还可以包裹自定义的类对象。该类型提供了一系列的构造函数以及转换函数来携带常见类型的数据,和转换到常见类型数据的方法:

    QVariant(int val)
    QVariant(uint val)
    QVariant(qlonglong val)
    QVariant(qulonglong val)
    QVariant(bool val)
    QVariant(double val)
    QVariant(float val)
    QVariant(const char * val)
    QVariant(const QString & val)
    QVariant(const QDate & val)
    QVariant(const QTime & val)
    QVariant(const QDateTime & val)
     
    bool    toBool() const
    QByteArray  toByteArray() const
    QChar   toChar() const
    QDate   toDate() const
    QDateTime   toDateTime() const
    double  toDouble(bool * ok = 0) const
    float   toFloat(bool * ok = 0) const
    int toInt(bool * ok = 0) const
    QJsonArray  toJsonArray() const
    qlonglong   toLongLong(bool * ok = 0) const
    QString toString() const
    QTime   toTime() const
    uint    toUInt(bool * ok = 0) const
    qulonglong  toULongLong(bool * ok = 0) const
    

    这只是其中的一部分,其实还包括了一些画图相关的类型的封装,例如QPoint,QRect等,当然Qt提供的是使用频率很高的常见的类型,有时候我们需要绑定自己定义的类对象,例如实体类:

    //设置
    MyClass myclass;
    QVariant courseModelVariant=QVariant::fromValue(myclass);
         
    //获取
    myclass = courseModelVariant.value<MyClass>();
    

    这样我们就可以使用QVariant携带任意数据类型了

    QComboBox控件
    下拉列表框控件最常见的功能需求就是为该控件添加下拉项目,并且为每个下拉项目添加对应的自定义隐藏数据,例如在下拉列表中每一项上面显示的文字描述是给用户看的,然而在程序中,我们可能需要该项目对应的隐藏数据,例如ID甚至是自定义的对象。

    QComboBox类使用QComboBox::addItem(const QString &atext, const QVariant &auserData)成员函数为下拉列表添加项目,第一个参数text表示显示在下拉项中的文字,而第二个参数我们可以利用来为该项绑定自定义的数据,其类型为QVariant类型。我们可以通过QVariant类型方便的为该下拉项关联任意自定义的数据类型。

    在获取数据的时候,通过QComboBox:: currentData(int role = Qt::UserRole)函数获取当前选中下拉项关联的QVariant类型的数据,也可以通过QComboBox:: itemData(int index, int role = Qt::UserRole)获取指定下拉项的关联数据。通过currentText()、itemText(int index)可以获取下拉项上显示的文本。

    QTableWidget控件
    QTableWidget是Qt中的表格显示控件,与C#中的Grid、GridView类似,主要是用来绑定数据。在UI设计界面中选中该控件之后可以在属性栏对控件的属性进行设置,最常用的属性有如下:

    focusPolicy 焦点策略,如果设置为NoFocus可以去掉单击时候现实的单元格的虚线框
    contextMenuPolicy 可以设置右键菜单
    frameShape 设置外边框,一般设置为NoFrame去掉边框
    editTriggers触发单元格的编辑状态,值NoEditTriggers表示不触发编辑状态
    selectionMode选择模式,值ExtendedSelection表示多选
    selectionBehavior选择行为,值SelectRows按行选择
    showGrid是否显示网格线
    rowCount行数
    columnCount列数
    horizontalHeaderVisible是否显示水平表头
    verticalHeaderVIsible是否显示垂直表头
    verticalScrollBarPolicy设置垂直滚动条策略
    horizontalScrollBarPolicy设置水平滚动条策略

    另外的一些比较实用的功能代码:
    在单元格中添加控件:

    QComboBox *comBox = new QComboBox();
    comBox->addItem("F");
    comBox->addItem("M");
    ui->qtablewidget->setCellWidget(0,3,comBox);//这里不是setItem而是setCellWidget
    

    为单元格添加checkBox:

    QTableWidgetItem *item = new QTableWidgetItem();
    //设置item的check状态的时候,item会自动变成QCheckBox的样子,
    //不必通过setCellWidget专门插入QCheckBox控件
    //通过item->checkState()可以获取该item是否勾选
    item->setCheckState(Qt::Unchecked);
    ui->tableWidgetCourseList->setItem(rowIndex, columnIndex, item);
    

    单元格中显示字符串:

    QTableWidgetItem *item = new QTableWidgetItem(QString("xx"));
    ui->tableWidgetCourseList->setItem(rowIndex, columnIndex, item);
    

    设置单元格关联的自定义数据:

    QTableWidgetItem *item = new QTableWidgetItem(QString(""));
    QVariant courseModelVariant=QVariant::fromValue(MyClass("xx"));
    item->setData(USER_DEFINE_ROLE,courseModelVariant);
    this->ui->tableWidgetCourseList->setItem(rowIndex, columnIndex, item);
    

    获取单元格关联的自定义数据:

    QTableWidgetItem * item = this->ui->tableWidgetCourseList->item(row,col);
    Myclass model = item->data(USER_DEFINE_ROLE).value<MyClass>();
    

    设置单元格中的文本对齐方式:

    ui->tableWidgetCourseList->item(rowIndex, columnIndex)->setTextAlignment(Qt::AlignCenter);
    

    通过x,y坐标获取所在的item对象:

    QModelIndex index = ui->tableWidgetCourseList->indexAt(QPoint(x,y));
    int row = index.row();
    int col = index.column();
    QTableWidgetItem * item = ui->tableWidgetCourseList->item(row,col);
    

    设置表头的列宽:

    ui->tableWidgetCourseList->horizontalHeader()->resizeSection(colIndex,20);//宽20
    

    设置列宽自适应:

    ui->tableWidgetCourseList->horizontalHeader()->setSectionResizeMode(colIndex,QHeaderView::Stretch);
    

    初始化表头文本:

    QStringList headerText;
    headerText.append("列1");
    headerText.append("列2");
    headerText.append("列3");
    ui->tableWidgetCourseList->setHorizontalHeaderLabels(headerText);
    

    为表头添加复选框按钮:

    在表头上添加复选框不能通过在表头单元格中添加QCheckBox的方式实现,必须进行重绘,下面的代码是我们自定义的表头类
    myqheaderview.h的内容:

    //该类实现自定义的表头,主要是为了在表头中加入CheckBox控件
    class MyQHeaderView : public QHeaderView
    {
        Q_OBJECT
    public:
        explicit MyQHeaderView(Qt::Orientation orientation, QWidget *parent = 0);
     
        void setChecked(bool checked);
     
    signals:
        void headCheckBoxToggled(bool checked);
     
    protected:
        void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const;
        void mousePressEvent(QMouseEvent *event);
     
    private:
        QRect checkBoxRect(const QRect &sourceRect) const;
     
        bool m_isOn;
    };
    

    myqheadview.cpp的内容:

    MyQHeaderView::MyQHeaderView(Qt::Orientation orientation, QWidget *parent)
        : QHeaderView(orientation, parent)
        , m_isOn(false)
    {
        // set clickable by default
        setChecked(false);
    }
     
    void MyQHeaderView::setChecked(bool checked)
    {
        if (isEnabled() && m_isOn != checked)
        {
            m_isOn = checked;
            updateSection(0);
            emit headCheckBoxToggled(m_isOn);
        }
    }
     
    void MyQHeaderView::paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const
    {
        painter->save();
        QHeaderView::paintSection(painter, rect, logicalIndex);
        painter->restore();
        if (logicalIndex == 0)
        {
            QStyleOptionButton option;
            if (isEnabled())
                option.state |= QStyle::State_Enabled;
            option.rect = checkBoxRect(rect);
            if (m_isOn)
                option.state |= QStyle::State_On;
            else
                option.state |= QStyle::State_Off;
            style()->drawControl(QStyle::CE_CheckBox, &option, painter);
        }
    }
     
    void MyQHeaderView::mousePressEvent(QMouseEvent *event)
    {
        if (isEnabled() && logicalIndexAt(event->pos()) == 0)
        {
            m_isOn = !m_isOn;
            updateSection(0);
            emit headCheckBoxToggled(m_isOn);
        }
        else QHeaderView::mousePressEvent(event);
    }
     
    QRect MyQHeaderView::checkBoxRect(const QRect &sourceRect) const
    {
        QStyleOptionButton checkBoxStyleOption;
        QRect checkBoxRect = style()->subElementRect(QStyle::SE_CheckBoxIndicator,
                                                     &checkBoxStyleOption);
        QPoint checkBoxPoint(sourceRect.x()+5,
                             sourceRect.y() +
                             sourceRect.height() / 2 -
                             checkBoxRect.height() / 2);
        return QRect(checkBoxPoint, checkBoxRect.size());
    }
    

    使用自定义表头:

    MyQHeaderView*myHeader=new MyQHeaderView(Qt::Horizontal, ui->tableWidgetCourseList);
    ui->tableWidgetCourseList->setHorizontalHeader(myHeader);
    

    为QTableWidget添加一行数据实际上是根据行数和列数,循环QTableWidget的所有单元格,对每个单元格item设置数据来实现的。

    QTabWidget控件
    该控件类就是一个选项卡控件,有多个tab页,下面是一些实用的方法:

    切换到tab:

    ui->tabWidgetExportEdit->setCurrentIndex(tabIndex);
    

    移除选项卡:

    ui->tabWidgetExportEdit->removeTab(tabIndex);
    

    关于选项卡控件的操作不多,重要的是怎么美化控件的显示,QSS将会作为单独的一篇文章来讲解如何美化Qt中的各种控件。

    QWebview控件
    该控件是用于在Qt中显示网页的控件,一般而言会将contextMenuPolicy属性设置为NoContextMenu隐藏系统为其提供的默认右键菜单

    <1>. 加载网页:

    ui->webViewCut->load(QUrl("http://www.baidu.com"));
    //如果是本地网页,必须使用file:///的前缀作为网页地址
    ui->webViewCut->load(QUrl("file:///c:/test.html "));
    

    <2>. Qt代码中调用QWebview加载的网页中的js函数:

    /先作如下设置
    ui->webViewCut->page()->setForwardUnsupportedContent(true);
    ui->webViewCut->page()->settings()->setAttribute(QWebSettings::JavascriptEnabled, true);
    ui->webViewCut->page()->settings()->setAttribute(QWebSettings::PluginsEnabled, true);
    ui->webViewCut->page()->settings()->setAttribute(QWebSettings::JavaEnabled, true);
    ui->webViewCut->page()->settings()->setAttribute(QWebSettings::AutoLoadImages, true);
     
    //然后在QWebview的loadFinished槽函数中调用js,该槽函数表示网页已经加载完毕
    QString js = QString("alert(\'hello Qt!\')");
    ui->webViewCut->page()->mainFrame()->evaluateJavaScript(js);
    

    <3>. 在QWebview加载的html的js代码中调用Qt的函数:

    默认情况下在QwebViewCut中的网页里面的js不能直接调用Qt中的相关功能,这涉及到安全性问题。要满足js中调用Qt的功能必须满足下面的条件:

    在Qt中暴露一个对象给js,然后js就可以在网页中直接使用这个对象以及该对象的[特定]函数,要求是被暴露Qt对象必须继承自QObject类,并且在js中调用这个暴露的对象的成员函数的定义是有要求的,该对象的满足下面的要求的成员函数都可以直接被js调用:

    1.必须是该对象的公共函数,并且在函数声明前面添加Q_INVOKABLE修饰,例如:

    public :
     Q_INVOKABLE int TestQt();
    

    2.如果该函数被声明成一个public slot 也可以不添加Q_INVOKABLE修饰:

    public slots:
      void TestQt();
    

    个人认为第一种方法更好,因为可以设置返回值,而Qt的槽函数是没有返回值的,都是返回void,只需要调用this->ui->webViewCut->page()->mainFrame()->addToJavaScriptWindowObject(“QtObj”, this); 就可以将一个Qt对象,也就是这里传递的this代表的对象,当然也可以直接传递其他对象指针,暴露给网页中的javascript,网页中的javascript在调用的时候可以直接使用 QtObj 去引用我们的Qt对象,以及通过QtObj去直接调用符合条件的Qt对象的成员函数。

    那么this->ui->webViewCut->page()->mainFrame()->addToJavaScriptWindowObject(“QtObj”, this);代码在什么时候执行呢? 推荐是在QWebFrame的信号javaScriptWindowObjectCleared发出的时候执行,所以我们可以在当前UI界面类的构造函数中添加下面的代码:

    onnect(ui->webViewCut->page()->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()),
        this, SLOT(populateJavaScriptWindowObject()));
    

    然后在处理javaScriptWindowObjectCleared()信号的槽函数中实现上述暴露功能:

    void MainWindow::populateJavaScriptWindowObject()
    {
       ui->webViewCut->page()->mainFrame()->addToJavaScriptWindowObject("QtObj", this);
    }
    

    根据Qt文档上对该信号的描述javaScriptWindowObjectCleared()这个信号会在我们调用QwebViewCut::load()加载新的url之前就触发,我们在这个时候去处理这个信号,将我们需要暴露的Qt对象暴露给即将载入的网页

    <4>. 将Qt的属性暴露出去供js调用,使用如下方法:

    Q_PROPERTY(int Qtvalue READ testValue WRITE setTestValue)
    

    将上面的语句加入到类的声明中,在private块下面就可以,最后不需要以分号结尾,例如:

    private:
     Q_PROPERTY(int Qtvalue READ testValue WRITE setTestValue)
    

    这一行的作用是将属性 Qtvalue 注册到Qt的元对象系统中,在js中可以通过名字Qtvalue来访问该属性,但在js中访问该属性的时候假设Qt暴露给js的对象为QtObj,那么在js中可以这样访问该属性:

    QtObj.Qtvalue = 10; //设置该属性的时候会调用void setTestValue(int)
    alert(QtObj.Qtvalue) //获取该属性的时候会调用 int testValue()
    

    Q_PROPERTY(int Qtvalue READ testValue WRITE setTestValue)的结构如下:

    Q_PROPERTY( 类型   属性名    READ     返回属性值的函数    WRITE     设置属性值的函数 )
                int   Qtvalue           int testValue()          void setTestValue(int)
    

    也就是说在js中我们可以直接使用Qtvalue,当获取Qtvalue的值的时候会自动调用暴露对象的 int testValue() 函数 ,Qt规定其返回值必须与Q_PROPERTY语句中指定的类型相同,并且必须没有参数。当我们为Qtvalue设置值的时候会调用暴露对象的void setTestValue(int)函数,该函数必须有一个int类型的参数(类型也必须与前面Q_PROPERTY语句中指定的类型相同),并且不能有返回值。

    经过实验int testValue()与void setTestValue(int)函数的声明在private区域也可以,好像无所谓。其实这两个函数的名字是可以随意定的,对js暴露的属性名是Qtvalue,当访问Qtvalue属性的时候,会自动调用Q_PROPERTY声明中READ后面指定的函数去获取值,并且调用WRITE后面指定的函数去设置值,而不在乎这两个函数的名字。

    另外这两个函数获取的值或者设置的值从哪里得来呢,我们可以在Qt对象中定义一个私有变量来保存这个值,而这个私有变量的名字是无所谓的,甚至如果需要的话,我们也不必保存这个值,直接在函数testValue里面返回一个常量值,也就是说是否应该定义一个私有变量来保存Qtvalue相关联的属性值,这个也不是必须的。

    更多Qt QWidget与js的交互可以在Qt文档中搜索 The Qt WebKit Bridge关键字,其实Q_PROPERTY并不是专用于暴露属性给js的,Q_PROPERTY是Qt元对象系统的一部分。

    <5>. 如果在QWebview加载的网页中有Flex应用程序,并且Qt中调用该QWebview加载的网页中的js函数中需要调用flex程序暴露给js的接口,那么还需要作如下设置:

    在"%appdata%\Macromedia\Flash Player#Security\FlashPlayerTrust"路径下新建xxx.cfg文件,将当前flex应用程序所在位置(也就是swf文件所在的目录)填写到该文件中即可,该xxx.cfg的名字是无所谓的,随便什么名字,在xxx.cfg文件中指定的目录路径中的swf文件的运行是被信任的。xxx.cfg文件中可以指定多个目录,每行一个。实际上%appdata%\Macromedia\Flash Player#Security\FlashPlayerTrust\路径下也可以有多个文件名不同的cfg文件。xxx.cfg文件中指定的目录实际上可以直接指定为根目录,例如swf文件的路径是F:/xxx/yyy/zzz/test.swf,那么我们新建的xxx.cfg中的内容的第一行可以直接指定为F:/即可。

    其实FlexBuilder在建立项目的时候,其生成的swf所在的目录都被添加到了%appdata%\Macromedia\Flash Player#Security\FlashPlayerTrust\下面的flashbuilder.cfg中了,所以使用FlexBuilder调试项目的时候,运行的swf都是被信任的。

    更多相关内容
  • 本页内容引言简化和缩短窗体代码开始:从反射中检索属性列表将对象属性值绑定到控件用已知属性设置未知控件的值反转过程:BindControlsToObject性能和FormBinding方案的扩展结论引言在Web开发人员的最常见任务之中,...
  • * * 第3章 对话框和常见控件 ? 对话框和控件之间是一对密不可分的卵生姐妹通常来讲对话框中有一些控件元素控件通常也建在对话框中对话框是一个弹出式的标准窗口当我们在一个应用程序中需要用户进行数据的输入或需要...
  • (3)Android常见界面控件

    千次阅读 2022-03-27 22:06:19
    文章目录3.1 简单控件的使用3.1.1 TextView控件3.1.2 EditText控件3.1.3 Button控件方法一:布局文件中指定点击事件(不常用)方法二:使用内部匿名类实现点击事件方法三:使用Activity实现OnClickListener接口全部...

    3.1 简单控件的使用

    Android界面上有很多的输入框,文字,图片,按钮等,这些都是Android提供的一些简单的控件来显示这些信息

    3.1.1 TextView控件

    用于显示文字信息,可在XML文件中设置其样式,相关属性如图

    image-20220323184647478

    image-20220323184717910

    <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="hello"
            android:textSize="20dp"
            android:id="@+id/tv_1"/>
    

    3.1.2 EditText控件

    表示编辑框,是TextView控件类的子类,下图是除TextView外其他的属性

    image-20220323185357792

    <TextView
        android:id="@+id/tv_1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="姓名"
        android:textSize="50dp"
        android:layout_margin="20dp"/>
    <EditText
        android:layout_below="@id/tv_1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入姓名:"
        android:layout_margin="20dp"/>
    

    image-20220323185842545

    3.1.3 Button控件

    Button控件表示按钮,继承自TextView控件类,既可以显示文本,也可以显示图片,可以执行点击操作(理论上所有控件都可以设置点击事件)

    通过以下属性来设置Button的点击事件,这句代码在XML中,需要在对应的Activity中设置一个方法名为click的点击事件方法,也就是与属性值同名

    一下为三种方法实现点击事件

    方法一:布局文件中指定点击事件(不常用)

    android:onClick = "click"
    
       //Activity中的代码
       public void click(View view)
        {
            Log.w("MainActivity","yes");
        }
    

    方法二:使用内部匿名类实现点击事件

    在Activity中使用内部匿名类实现点击操作

    mbtn1.setOnClickListener(new View.OnClickListener() {//按钮1点击事件,使用方法二匿名内部类
                @Override
                public void onClick(View view) {
                    mbtn1.setText("按钮1被点击");
                }
            });
    

    方法三:使用Activity实现OnClickListener接口

    使用当前Activity实现View.OnClickListener接口,可以实现点击事件,实现代码在下面

    全部实现代码举例

    activity_main.xml

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="20dp">
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/btn1"
            android:text="按钮1"/>
        <Button
            android:layout_below="@id/btn1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/btn2"
            android:onClick="click"
            android:text="按钮2"/>
    
        <Button
            android:id="@+id/btn3"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/btn2"
            android:text="按钮3" />
    
    </RelativeLayout>
    
    

    MainActivity

    package cn.itcast.animalconnection;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    
    import java.nio.BufferUnderflowException;
    
    public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    
        private Button mbtn1,mbtn2,mbtn3;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mbtn1 = findViewById(R.id.btn1);//找到xml中的Button控件与Button变量一一对应
            mbtn2 = findViewById(R.id.btn2);
            mbtn3 = findViewById(R.id.btn3);
            mbtn3.setOnClickListener(this);//设置按钮3的监听按钮事件
    
            mbtn1.setOnClickListener(new View.OnClickListener() {//按钮1点击事件,使用方法二匿名内部类
                @Override
                public void onClick(View view) {
                    mbtn1.setText("按钮1被点击");
                }
            });
        }
    
        public void click(View view)//按钮2点击事件,使用方法一,在xml中指定了onClick属性
        {
            mbtn2.setText("按钮2被点击");
        }
    
        @Override
        public void onClick(View v)//按钮3点击事件,使用方法三,实现OnClickListener接口
        {
            switch (v.getId())
            {
                case R.id.btn3:
                    mbtn3.setText("按钮3被点击");
            }
        }
    }
    

    image-20220323213834517

    3.1.4 ImageView控件

    ImageView控件表示图片,继承自View,可以加载各种图片资源,常用属性如下

    image-20220323214202197

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="20dp"
        android:orientation="vertical">
        <ImageView
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:background="@drawable/s"/>
        <ImageView
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:background="@drawable/w"/>
        <ImageView
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:background="@drawable/q"/>
    </LinearLayout>
    
    

    image-20220323214902220

    注意点:

    android:background="@drawable/w"设置的背景,默认拉伸显示

    android:src="@drawable/w"设置的是前景,默认原图显示

    3.1.5 RadioButton控件

    RadioButton表示单选按钮,是Button的一个子类,每一个单选按钮都有选中和未选中两种状态,都是通过android:checked属性指定的

    在Android程序中,该控件经常与RadioGroup配合使用,实现单选按钮的功能,RadioGroup是单选组合框,RadioGroup继承自LinearLayout,可以使用android:orientation属性控制RadioButton的排列方向

        <RadioGroup
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">
    
            <RadioButton
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text=""/>
            <RadioButton
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text=""/>
        </RadioGroup>
    

    image-20220323220434984

    设置监听事件

    参考代码

    //MainActivity
    public class MainActivity extends AppCompatActivity{
        private RadioGroup mrg1;
        private TextView mtv1;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mrg1 = findViewById(R.id.rg_1);
            mtv1 = findViewById(R.id.tv_1);
            //设置监听事件
            mrg1.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(RadioGroup radioGroup, int i) {//i就是状态为选中的那个单选按钮的id
                    if(i == R.id.rb_1)
                    {
                        mtv1.setText("你的性别是:男");
                    }
                    else
                    {
                        mtv1.setText("你的性别是:女");
                    }
                }
            });
        }
    }
    

    3.1.6 CheckBox控件

    CheckBox表示复选框,是Button的子类,选中的属性和单选按钮是一样的

    与单选框类似,但不需要包含在RadioGroup中

    代码举例

    activity_main.xml

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="20dp"
        android:orientation="vertical">
    
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="选择你的性别:"
            android:textSize="15sp"/>
        <CheckBox
            android:id="@+id/cb_1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="羽毛球"/>
        <CheckBox
            android:id="@+id/cb_2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="篮球"/>
        <CheckBox
            android:id="@+id/cb_3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="乒乓球"/>
        <TextView
            android:id="@+id/tv_1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="你的兴趣爱好是"
            android:textSize="20sp"/>
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/tv_2"
            android:textSize="20sp"/>
    </LinearLayout>
    
    

    MainActivity

    package cn.itcast.animalconnection;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.CheckBox;
    import android.widget.CompoundButton;
    import android.widget.RadioGroup;
    import android.widget.TextView;
    
    import java.nio.BufferUnderflowException;
    
    public class MainActivity extends AppCompatActivity implements CompoundButton.OnCheckedChangeListener{
        private TextView hobby;//输出TextView控件
        private String hobbys;//存放输出内容
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            CheckBox mcb1 = findViewById(R.id.cb_1);
            CheckBox mcb2 = findViewById(R.id.cb_2);
            CheckBox mcb3 = findViewById(R.id.cb_3);
            mcb1.setOnCheckedChangeListener((CompoundButton.OnCheckedChangeListener) this);//找到对应控件,需要转换一下类型
            mcb2.setOnCheckedChangeListener((CompoundButton.OnCheckedChangeListener) this);
            mcb3.setOnCheckedChangeListener((CompoundButton.OnCheckedChangeListener) this);
            hobby = findViewById(R.id.tv_2);
            hobbys = new String();
        }
        @Override
        public void onCheckedChanged(CompoundButton buttonview,boolean ischecked)//监听事件,两个参数表示被点击的控件和控件的状态,实现对应接口
        {
            String motion = buttonview.getText().toString();//被点击控件的文字
            if(ischecked)
            {
                if(!hobbys.contains(motion))//字符串中没有这个文字就加入,下面else没有就删除
                {
                    hobbys = hobbys + motion;
                    hobby.setText(hobbys);
                }
            }
            else
            {
                if (hobbys.contains(motion))
                {
                    hobbys = hobbys.replace(motion,"");//替换字符串
                    hobby.setText(hobbys);
                }
            }
        }
    }
    

    image-20220323224311620

    3.1.7 Toast类

    Toast类是android提供的轻量级信息提醒机制,用于向用户提示即时消息,显示在应用程序的最上层,显示一段时间后自动消失不会打断当前操作,也不会获得焦点

    Toast.makeText(Context,Text,time).show();//需要调用show()方法才会显示
    
    • Context:表示应用程序环境信息,即当前组件的上下文环境,Context是一个抽象类,若在Activity中使用,可以将参数设置为``Activity.this`
    • Text:提示的字符串信息
    • Time:表示显示时间的长短,属性值包括两个固定的参数

    3.1.8 实战演练—实现注册界面效果

    目标:实现一个注册演示界面,通过日志返回注册信息

    创建样式

    下面是示例创建的样式,我实际没有使用这些样式,都是一个一个打上去的,这个样式不知道为什么覆盖了其他的默认属性值

    themes.xml

    <resources xmlns:tools="http://schemas.android.com/tools">
        <!-- Base application theme. -->
        <style name="Theme.仿连连看" parent="Theme.MaterialComponents.DayNight.Bridge">
            <!-- Primary brand color. -->
            <item name="titleTextColor">@android:color/white</item>
            <item name="colorPrimary">@color/purple_500</item>
            <item name="colorPrimaryVariant">@color/purple_700</item>
            <item name="colorOnPrimary">@color/white</item>
            <!-- Secondary brand color. -->
            <item name="colorSecondary">@color/teal_200</item>
            <item name="colorSecondaryVariant">@color/teal_700</item>
            <item name="colorOnSecondary">@color/white</item>
            <!-- Status bar color. -->
            <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
            <!-- Customize your theme here. -->
        </style>
    <!--    竖分割线样式-->
        <style name="hline">
            <item name="android:layout_width">match_parent</item>
            <item name="android:layout_height">1dp</item>
            <item name="android:background">@android:color/white</item>
        </style>
    <!--    横分割线样式-->
        <style name="vline">
            <item name="android:layout_width">1dp</item>
            <item name="android:layout_height">match_parent</item>
            <item name="android:background">@android:color/white</item>
        </style>
    <!--    文本样式1-->
        <style name="tvOne">
            <item name="android:layout_width">0dp</item>
            <item name="android:layout_height">match_parent</item>
            <item name="android:layout_weight">1</item>
            <item name="android:drawablePadding">8dp</item>
            <item name="android:gravity">center_horizontal</item>
            <item name="android:paddingTop">40dp</item>
            <item name="android:textColor">@android:color/white</item>
            <item name="android:textSize">15sp</item>
        </style>
    <!--    文本样式2-->
        <style name="tvTwo">
            <item name="android:layout_width">wrap_content</item>
            <item name="android:layout_height">wrap_content</item>
            <item name="android:layout_marginLeft">20dp</item>
            <item name="android:textColor">@android:color/white</item>
            <item name="android:textSize">15sp</item>
        </style>
    <!--    输入框样式-->
        <style name="teOne">
            <item name="android:layout_width">match_parent</item>
            <item name="android:layout_height">wrap_content</item>
            <item name="android:layout_marginTop">30dp</item>
            <item name="android:background">@null</item>
            <item name="android:textColor">@android:color/black</item>
        </style>
    </resources>
    

    放置界面控件

    activity_main.xml

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="20dp"
        android:orientation="vertical">
    
        <TextView
            android:layout_marginTop="20dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="注册"
            android:textSize="35sp"
            android:layout_gravity="center_horizontal"/>
        <LinearLayout
            android:layout_marginTop="30dp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">
    
            <EditText
                android:id="@+id/name"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="20dp"
                android:hint="输入账号名:"/>
            <EditText
                android:id="@+id/email"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="20dp"
                android:hint="输入邮箱:"/>
            <EditText
                android:id="@+id/pwd"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="20dp"
                android:hint="输入密码"
                android:password="true"/>
        </LinearLayout>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:layout_marginTop="20dp">
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="性别:"
                android:textSize="20sp"
                android:layout_marginRight="20dp"
                android:layout_marginLeft="10dp"/>
            <RadioGroup
                android:id="@+id/sex"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                >
                <RadioButton
                    android:id="@+id/man"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text=""
                    android:layout_marginRight="20dp"/>
                <RadioButton
                    android:id="@+id/woman"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text=""/>
            </RadioGroup>
    
        </LinearLayout>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp">
    
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="请选择兴趣爱好:"
                android:textSize="20sp"/>
            <CheckBox
                android:id="@+id/sing"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="唱歌"/>
            <CheckBox
                android:id="@+id/dance"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="跳舞"/>
            <CheckBox
                android:id="@+id/read"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="读书"/>
        </LinearLayout>
        <CheckBox
            android:id="@+id/fage"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="我已确认信息无误"
            android:textColor="#00BCD4"
            android:layout_marginTop="20dp"/>
        <Button
            android:id="@+id/login"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="注册"
            android:layout_margin="30dp"/>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:text="--其他登陆方式--"/>
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                android:layout_marginTop="20dp"
                android:layout_marginLeft="40dp"
                android:layout_marginRight="40dp">
    
    
            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_weight="1"
                android:layout_height="wrap_content"
                android:orientation="vertical">
                <ImageView
                    android:layout_width="30dp"
                    android:layout_height="30dp"
                    android:src="@drawable/w"
                    android:layout_gravity="center_horizontal"/>
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="QQ"
                    android:layout_gravity="center_horizontal"/>
            </LinearLayout>
            <LinearLayout
                android:layout_weight="1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical">
                <ImageView
                    android:layout_width="30dp"
                    android:layout_height="30dp"
                    android:src="@drawable/s"
                    android:layout_gravity="center_horizontal"/>
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="微信"
                    android:layout_gravity="center_horizontal"/>
            </LinearLayout>
            <LinearLayout
                android:layout_weight="1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical">
                <ImageView
                    android:layout_width="30dp"
                    android:layout_height="30dp"
                    android:src="@drawable/q"
                    android:layout_gravity="center_horizontal"/>
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="游客"
                    android:layout_gravity="center_horizontal"/>
            </LinearLayout>
            </LinearLayout>
        </LinearLayout>
    </LinearLayout>
    
    

    实现注册功能

    package cn.itcast.animalconnection;
    import androidx.appcompat.app.AppCompatActivity;
    import android.graphics.Color;
    import android.os.Bundle;
    import android.text.TextUtils;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.CheckBox;
    import android.widget.CompoundButton;
    import android.widget.EditText;
    import android.widget.RadioGroup;
    import android.widget.TextView;
    import android.widget.Toast;
    import java.nio.BufferUnderflowException;
    public class MainActivity extends AppCompatActivity implements View.OnClickListener,CompoundButton.OnCheckedChangeListener{
    
        private EditText ed_name,ed_pwd,ed_email;
        private Button btn_submit;
        private String name,email,pwd,sex,hobbys;
        private RadioGroup rg_sex;
        private CheckBox cb_sing,cb_dance,cb_read,flge;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            init();
        }
        private void init()
        {
            ed_name = findViewById(R.id.name);
            ed_email = findViewById(R.id.email);
            ed_pwd = findViewById(R.id.pwd);
            btn_submit = findViewById(R.id.login);
            rg_sex = findViewById(R.id.sex);
            cb_sing = findViewById(R.id.sing);
            cb_dance = findViewById(R.id.dance);
            cb_read = findViewById(R.id.read);
            flge = findViewById(R.id.fage);
            btn_submit.setOnClickListener(this);//提交
            cb_sing.setOnCheckedChangeListener(this);//复选框
            cb_dance.setOnCheckedChangeListener(this);
            cb_read.setOnCheckedChangeListener(this);
            hobbys = new String();
            rg_sex.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {//单选控件设置监听事件
                @Override
                public void onCheckedChanged(RadioGroup radioGroup, int i) {
                    switch (i)
                    {
                        case R.id.man:
                            sex = "男";
                            break;
                        case R.id.woman:
                            sex = "女";
                            break;
                    }
                }
            });
        }
        private void getDate()//获取界面信息
        {
            name = ed_name.getText().toString();
            email = ed_email.getText().toString();
            pwd = ed_pwd.getText().toString();
        }
    
        @Override
        public void onClick(View view) //提交按钮
        {
            switch (view.getId()) {
                case R.id.login:
                    getDate();
                    if (TextUtils.isEmpty(name))
                        Toast.makeText(MainActivity.this, "请输入名字", Toast.LENGTH_LONG).show();
                    else if (TextUtils.isEmpty(email))
                        Toast.makeText(MainActivity.this, "请输入邮箱", Toast.LENGTH_LONG).show();
                    else if (TextUtils.isEmpty(pwd))
                        Toast.makeText(MainActivity.this, "请输入密码", Toast.LENGTH_LONG).show();
                    else if (TextUtils.isEmpty(sex))
                        Toast.makeText(MainActivity.this, "请选择性别", Toast.LENGTH_LONG).show();
                    else if (TextUtils.isEmpty(hobbys))
                        Toast.makeText(MainActivity.this, "请选择兴趣爱好", Toast.LENGTH_LONG).show();
                    else if (!flge.isChecked())//确认复选框
                    {
                        Toast.makeText(MainActivity.this, "请选择确认无误", Toast.LENGTH_LONG).show();
                        flge.setTextColor(Color.parseColor("#FF3030"));
                    }
                    else
                    {
                        Toast.makeText(MainActivity.this, "注册成功", Toast.LENGTH_LONG).show();
                        Log.i("MainActiity","注册的用户信息:"+" 名字:"+name+"邮箱:"+email+"密码:"+pwd+"性别:"+sex+"兴趣爱好:"+hobbys);
                    }
                    break;
            }
        }
    
        @Override
        public void onCheckedChanged(CompoundButton compoundButton, boolean b)//复选框设置监听事件
        {
            String motion = compoundButton.getText().toString();
            if(b)
            {
                if(!hobbys.contains(motion))
                    hobbys = hobbys + motion;
            }
            else
            {
                if(!hobbys.contains(motion))
                    hobbys = hobbys + motion;
            }
        }
    }
    

    示例图

    image-20220324175732867

    3.2 列表控件的使用

    日常生活中,淘宝,微信等应用程序,通常会在页面中展示很多的条目,并且每一个条目的风格一致,这种数据方式就是通过ListView或RecyclerView控件实现的

    3.2.1 ListView控件的使用

    ListView是一个比较常用的控件,以列表的形式展示数据内容,能够根据列表的高度自适应屏幕显示,ListView的属性如下图

    image-20220324190912574

    <ListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:listSelector="#fefefe" >
    </ListView>
    

    ###3.2.2 常用数据适配器

    为ListView添加数据的时候会用到数据适配器,数据适配器是数据与视图之间沟通的桥梁,类似一个转换器,将复杂的数据转换成用户可以接受的方式进行呈现,下面是几个常用的数据适配器

    BaseAdapter

    BaseAdapter是一个基本适配器,实际上是一个抽象类,通常在自定义数据适配器的时候会继承自这个类,该类的抽象方法如下

    image-20220324191928227

    SimpleAdapter

    SimpleAdapter继承自BaseAdapter,实现了四个抽象方法,并进行封装,使用SimpleAdapter进行数据适配的时候只需要在构造函数传入对应的参数即可

    public SimpleAdapter(Context context,List<? extends Map<String,?>>data,int resource,String[] from,int[] to);
    
    • context :上下文对象
    • data :数据集合,data中的每一项对应ListView条目中的数据
    • resource :Item布局的资源id
    • from :Map集合中的key值
    • to :Item布局中对应的控件

    ArrayAdapter

    ArrayAdapter是BaseAdapter的子类,ArrayAdapter控件通常用于适配TextView控件,例如Android中的设置菜单

    构造方法如下

    public ArrayAdapter(Context context,int resource);
    public ArrayAdapter(Context context,int resource,int textViewResourceId);
    public ArrayAdapter(Context context,int resource,T[] objects);
    public ArrayAdapter(Context context,int resource,List<T>objects);
    public ArrayAdapter(Context context,int resource,int textViewResourceId,List<T> objects);
    
    • context:上下文对象
    • resource:Item布局的资源id
    • textViewResourceId:Item布局中相应TextView控件的id
    • T[] objects:需要适配数组类型的数据
    • Listobjects:需要适配List类型的数据

    设置数据适配器到ListView控件举例

    ListView mListView = (ListView)findViewById(R.id.lv);
    BaseAdapter madapter = new BaseAdapter();
    mListView.setAdapter(madapter);
    

    3.2.3 实战演练-购物商城

    ####activity_main.xml----创建ListView控件

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity"
        android:padding="20dp"
        android:orientation="vertical">
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="购物商城"
            android:gravity="center_horizontal"
            android:background="#DA8282"/>
        <ListView
            android:id="@+id/lv_1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
        </ListView>
    </LinearLayout>
    

    list_item.xml----用于定义ListView单个条目的布局

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="16dp">
    
        <ImageView
            android:id="@+id/iv"
            android:layout_width="120dp"
            android:layout_height="90dp"
            android:layout_centerVertical="true" />
        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:layout_toRightOf="@+id/iv"
            android:layout_centerVertical="true">
            <TextView
                android:id="@+id/title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="桌子"
                android:textSize="20sp"
                android:textColor="#000000" />
            <TextView
                android:id="@+id/tv_price"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="价格:"
                android:textSize="20sp"
                android:layout_marginTop="10dp"
                android:layout_below="@+id/title"
                android:textColor="#FF8F03" />
            <TextView
                android:id="@+id/price"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="1000"
                android:textSize="20sp"
                android:layout_below="@+id/title"
                android:layout_toRightOf="@+id/tv_price"
                android:textColor="#FF8F03"
                android:layout_marginTop="10dp"/>
        </RelativeLayout>
    </RelativeLayout>
    
    

    MainActivity.java

    package cn.itcast.test2;
    import androidx.appcompat.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.BaseAdapter;
    import android.widget.ImageView;
    import android.widget.ListView;
    import android.widget.TextView;
    public class MainActivity extends AppCompatActivity {
        private ListView mlistview;
        private String[] titles = {"桌子","苹果","蛋糕","线衣","猕猴桃","围巾"};
        private String[] prices = {"1800元","10元","300元","350元","500元","10元","280元"};
        private int[] icons ={R.drawable.a,R.drawable.b,R.drawable.c,R.drawable.a,R.drawable.b,R.drawable.c};//图片集合
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mlistview = findViewById(R.id.lv_1);
            MyBaseAdapter madapter = new MyBaseAdapter();
            mlistview.setAdapter(madapter);
        }
        class MyBaseAdapter extends BaseAdapter//实现抽象类,不然不能使用
        {
            @Override
            public int getCount() {//获取条目的总数
                return titles.length;
            }
            @Override
            public Object getItem(int i) {//返回条目的数据对象
                return titles[i];
            }
            @Override
            public long getItemId(int i) {//返回条目的id
                return i;
            }
            @Override
            public View getView(int i, View view, ViewGroup viewGroup) {//获取条目的视图
                View v = View.inflate(MainActivity.this,R.layout.list_item,null);//创建视图对象
                TextView title = v.findViewById(R.id.title);//引入控件对象
                TextView price = v.findViewById(R.id.price);
                ImageView iv = v.findViewById(R.id.iv);
                title.setText(titles[i]);
                price.setText(prices[i]);
                iv.setBackgroundResource(icons[i]);
                return v;
            }
        }
    }
    
    
    image-20220326212033368

    优化ListView控件

    当运行上述程序的时候,当ListView控件上加载的item过多,并且快速滑动屏幕的时候就会产生卡顿,出现的原因如下

    • 滑出屏幕区域的item会被销毁,滑入的会创建,当滑动屏幕的时候就会不断销毁创建
    • 不断执行findViewById()方法初始化控件,每创建一个对象都需要执行这个方法

    优化:

    在item出屏幕的时候,item会先以缓存的形式暂时保存,getView()方法中的第二个参数就是旧的对象,就可以修改getView()方法利用原来的旧对象来刷新新的信息,就可以有效减少频繁的创建销毁对象,具体修改的代码如下

    MyBaseAdapter类下的getView()方法

    public View getView(int i, View view, ViewGroup viewGroup) {//获取条目的视图,第二个参数代表滑出的item
                ViewHolder holder = null;
                if(view == null)
                {
                    view = View.inflate(MainActivity.this,R.layout.list_item,null);//获取item样式
                    holder = new ViewHolder();
                    holder.title = view.findViewById(R.id.title);
                    holder.price = view.findViewById(R.id.price);
                    holder.iv = view.findViewById(R.id.iv);
                    view.setTag(holder);
                }
                else//如果有旧对象
                {
                    holder = (ViewHolder) view.getTag();//获得缓存中的ViewHolder类的对象
                }
                holder.title.setText(titles[i]);
                holder.price.setText(prices[i]);
                holder.iv.setBackgroundResource(icons[i]);
                return view;
            }
    

    3.2.4 RecyclerView控件的使用

    此控件用于在有限的空间内显示大量数据,与ListView类似,该控件以列表的形式展示数据,数据通过数据适配器加载,但是这个控件比ListView更加强大

    优越性:

    • RecyclerView控件可以通过LayoutManner类实现横向和竖向的列表效果,瀑布流效果和GridView效果,而ListView只能实现竖直的列表效果
    • RecyclerView控件使用RecyclerView.Adapter,该数据适配器将BaseAdapter中的getView()方法拆分成onCreateViewHoulder()方法和OnBindViewHoulder()方法,强制使用ViewHoulder类,使得代码编写更加规范化
    • RecyclerView控件复用Item对象的工作由自己实现
    • RecyclerView控件可以通过setItemAnimator()方法设置动画效果

    3.3自定义控件

    通常在Android开发过程中,都不直接使用View控件,而是使用它的子类,最简单的自定义控件就是创建一个继承View类或其他子类的类,并重写该类的构造方法,示例代码如下

    class Customview extends View{
        public Customview(Context context)
        {
            super(context);
        }
        public Customview(Context context, AttributeSet attrs)
        {
            super(context, attrs);
        }
    }
    

    如果想要创建一个该类的对象,则需要使用到第一个构造函数,如果需要在布局文件中引用该自定义类,则需要使用到该类的第二个构造方法

    我们可以在自定义控件中通过重写指定方法来添加额外的样式和功能,自定义控件常用的三个方法具体介绍如下

    onMeasure()方法

    该方法用于测量尺寸,在该方法中可以设置控件本身或者是其子控件的宽高

    onMeasure(int widthMeasureSpec,int heightMeasureSpec);
    

    第一个参数表示获取父容器指定该控件的宽度,第二个则是高度

    这两个参数不仅包含属性值,还包括父容器的测量模式,测量模式分为三种

    • EXACTLY:当自定义控件的宽高值设置为具体值的时候使用,如100dp,match_parent
    • AT_MOST:当自定义控件的宽高值为wrap_content时使用
    • UNSPECIFIED:当父容器没有指定自定义控件的宽高值时使用

    注意点:虽然这两个参数是父容器为该控件指定的宽高,但是该控件还需要通过设置setMeasureDimension(int,int)来设置宽高

    onDraw()方法

    该方法用于绘制图像

    onDraw(Canvas canvas);
    

    canans表示画布,经常与Paint类配合使用,通过Paint类可以在Canans中绘制图像

    onLayout()方法

    onLayout()方法,用于指定布局中子控件的位置,该方法通常在ViewGroup容器中重写

    onLayout(boolean changed,int left,int top,int right,int bottom);
    

    第一个参数表示自定义控件的大小和位置是否发生改变,剩下的四个控件代表与父容器的左边,顶部,右边,底部的距离

    举例

    使用自定义控件在界面中画一个图形

    CircleView.java

    package cn.itcast.myapplication;
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.util.AttributeSet;
    import android.view.View;
    
    public class CircleView extends View {
        public CircleView(Context context) {
            super(context);
        }
    
        public CircleView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            int r = getMeasuredWidth() / 2;//获取半径
            int centerX = getLeft() + r;
            int centerY = getTop() + r;
            Paint paint = new Paint();
            paint.setColor(Color.RED);//设置颜色为红色
            canvas.drawCircle(centerX, centerY, r, paint);//调用画笔绘制
        }
    }
    
    

    activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
    
        <cn.itcast.myapplication.CircleView
            android:layout_width="100dp"
            android:layout_height="100dp" />
    
    </RelativeLayout>
    

    注意点:一个java源文件只能设置一个public类,这里的CircleView自定义控件类必须单独放在一个源文件中,如果不加public属性放在主函数类对应的java源文件中也是不行的,当在布局文件中创建一个子对象控件的时候是检测不到的

    展开全文
  • 第3章 Android 常见界面控件(ListView、RecyclerView、自定义View篇) 目录3.3 ListView的使用3.3.1 ListView控件的简单使用3.3.2 常用数据适配器3.3.3 案例——Android生物商城3.4 RecyclerView的使用3.5 自定义...

    Android 常见界面控件(ListView、RecyclerView、自定义View篇)

    3.3 ListView的使用

    例如微信淘宝等应用程序,这些程序通常会在一个页面中展示多个条目,并且每一个条目布局风格一致,这种数据的展示方式是通过ListView控件实现的

    3.3.1 ListView控件的简单使用

    ListView以列表的形式展示数据内容,并且能根据列表高度自适应屏幕显示,ListView控件的常用属性:

    在这里插入图片描述

    3.3.2 常用数据适配器

    在为ListView控件添加数据时会用到数据适配器。数据适配器是数据与视图之间的桥梁,它类似于一个转换器,将复杂的数据转换成用户可以接受的方式进行呈现。在Android系统中提供了多种适配器(Adapter)对ListView控件进行数据适配

    1. BaseAdapter

    BaseAdapter是基础的适配器,其实际上是一个抽象类,通常在自定义适配器时会继承BaseAdapter,该类有四个抽象方法,根据这些抽象方法来对ListView控件进行数据适配

    在这里插入图片描述

    1. SimpleAdapter

    SimpleAdapter继承自BaseAdapter,实现了BaseAdapter的四个抽象方法对其进行封装,因此在使用SimpleAdapter进行数据适配时,只需要在构造方法中传入相应的参数即可

    public SimpleAdapter(Context context,List<? extends Map ?>

    data, int resource,String[] from,int[] to)

    • context:上下文对象
    • data:数据集合,data中的每一项对应ListView控件中的条目的数据
    • resource:Item布局的资源id
    • from:Map集合中的key值
    • to:Item布局中对应的控件
    1. ArrayAdapter

    ArrayAdapter也是BaseAdapter的子类,使用时只需要在构造方法中传入相应的参数即可,ArrayAdapter常用于适配TextView控件,例如Android Studio的Help,ArrayAdapter有多个构造方法

    在这里插入图片描述

    • context:上下文对象
    • resource:Item布局的资源id
    • textViewResourceID:Item布局中相应TextView的id
    • T[] objects:需要适配的数组类型的数据
    • List object:需要适配的List类型的数据

    在创建数据适配器后,可以通过ListView对象的setAdapter()方法添加适配器

    例如:要将继承 BaseAdapter的MyBaseAdapter实例添加到ListView

    ListView mListView =ListView)findViewById(R.id.lv);
    MyBaseAdapter mAdapter = new MyBaseAdapter();
    mListView.setAdapter(mAdapter);
    

    3.3.3 案例——Android生物商城

    1. 创建listview应用程序

    2. 导入图片资源

    3. 放置界面控件(编写activity_main.xml文件)

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <TextView
            android:layout_width="368dp"
            android:layout_height="45dp"
            android:text="生物图鉴"
            android:textSize="18sp"
            android:textColor="#FFFFFF"
            android:background="#FF8F03"
            android:gravity="center" />
        <ListView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/lv"/>
    </LinearLayout>
    
    1. 创建Item界面(编写list_item.xml文件)
    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="16dp">
        <ImageView
            android:id="@+id/iv"
            android:layout_width="120dp"
            android:layout_height="90dp"
            android:layout_centerVertical="true"/>
        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:layout_toRightOf="@+id/iv"
            android:layout_centerVertical="true">
            <TextView
                android:id="@+id/title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="豹猫"
                android:textSize="20sp"
                android:textColor="#000000"/>
            <TextView
                android:id="@+id/tv_price"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="价格"
                android:textSize="20sp"
                android:textColor="#FF8F03"
                android:layout_below="@+id/title"
                android:layout_marginTop="10dp"/>
            <TextView
                android:id="@+id/price"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="1000"
                android:textSize="20sp"
                android:textColor="#FF8F03"
                android:layout_below="@+id/tv_price"
                android:layout_marginTop="10dp"/>
        </RelativeLayout>
    </RelativeLayout>
    
    1. 编写界面交互代码(MainActivity中的MyBaseAdapter)
    public class MainActivity extends AppCompatActivity {
        private ListView mListView;
        //生物与价格数据集合
        private String[] titles = {"豹猫","毪菇","马","狼"};
        private String[] prices = {"1000","4000","6577","5000"};
        //图片数据集合
        private int[] icons = {R.mipmap.cat,R.mipmap.cow,R.mipmap.horse,R.mipmap.wolf};
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            //初始化ListView控件
            mListView = (ListView)findViewById(R.id.lv);
            //创建一个数据适配器实例
            MyBaseAdapter ma = new MyBaseAdapter();
            mListView.setAdapter(ma);
        }
        //编写一个实现了BaseAdapter抽象类的数据适配器类
        class MyBaseAdapter extends BaseAdapter{
            @Override
            public int getCount() {
                //获取Item的总数
                return titles.length;
            }
            @Override
            public Object getItem(int position) {
                //返回Item的数据对象
                return titles[position];
            }
            @Override
            public long getItemId(int position) {
                //返回item的id
                return position;
            }
            //得到item的视图
            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                //加载activity_item.xml布局文件
                View view = View.inflate(MainActivity.this,R.layout.activity_item,null);
                TextView title = (TextView) view.findViewById(R.id.title);
                TextView price = (TextView) view.findViewById(R.id.price);
                ImageView iv = (ImageView) view.findViewById(R.id.iv);
                title.setText(titles[position]);
                price.setText(prices[position]);
                iv.setBackgroundResource(icons[position]);
                return view;
            }
        }
    }
    

    启动测试

    在这里插入图片描述

    1. 优化ListView加载数据逻辑

    运行上述程序后,当ListView控件 上加载的Item过多并快速滑动该控件时,界面会出现卡顿的现象,出现这个现象的原因如下:

    (1)当滑动屏幕时,不断地创建Item对象。ListView控件在当前屏幕上显示多少个Item,就会在适配器MyBaseAdapter中的getView0方法中创建多少Item对象。当滑动ListView控件时, 滑出屏幕的Item对象会被销毁,新加载到屏幕上的Item会创建新的对象,因此快速滑动ListView控件时会不断地对Item对象进行销毁和创建

    (2)不断执行findViewByld0方法初始化控件。每创建-一个Item对象都需要加载一次Item布局,加载布局时会不断地执行findViewByld0方法初始化控件。这些操作比较耗费设备(模拟器、手机等设备)的内存并且浪费时间,如果每个Item都需要加载网络图片,加载网络图片是个比较耗时的操作,就会造成程序内存溢出的异常

    由于以上两点原因,我们需要对ListView控件进行优化,优化的目的就是使ListView控件在快速滑动时不再重复创建Item对象,减少内存的消耗和屏幕渲染的处理

    优化步骤

    1. 创建ViewHolder类。 在MainActivity中创建一 个ViewHolder类, 将需要加载的控件变量放在改类中
    class ViewHolder{
    	TextView title;
        ImageView iv;
    }
    
    1. 在MyBaseAdapter的getView(int position, View convertView, ViewGroup parent)方法中,第2个参数convertView代表的就是之前滑出屏幕的Item对象。如果第一次加载getView0方法时,会创建Item对象,当滑动ListView控件时, 滑出屏幕的Item对象会以缓存的形式存在,而convertView代表的就是缓存的Item对象,我们可以通过复用convertView对象从而减少Item对象的创建,在getView()方法中进行优化的代码
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder = null;
        if(convertView == null){
            //将activity_item.xml布局文件找出来并转换为View对象
            convertView = View.inflate(MainActivity.this,R.layout.activity_item,null);
            //找到activity_item.xml中的TextView
            holder = new ViewHolder();
            holder.title = (TextView) convertView.findViewById(R.id.title);
            holder.price = (TextView) convertView.findViewById(R.id.price);
            holder.iv = (ImageView) convertView.findViewById(R.id.iv);
            convertView.setTag(holder);
        }else{
            holder = (ViewHolder) convertView.getTag();
        }
        holder.title.setText(titles[position]);
        holder.price.setText(prices[position]);
        holder.iv.setBackgroundResource(icons[position]);
        return convertView;
    }
    

    代码解析

    第2行代码用于判断convertView对象是否为null,若为null,则会创建ViewHolder类中的对象holder,并将获取的界面控件赋值给ViewHolder类中的属性,最后通过setTag()方法将对象holder添加到convertView对象中,否则不会创建ViewHolder类的对象,会通过getTag()方法获取缓存在convertView对象中的ViewHolder类的对象

    3.4 RecyclerView的使用

    在Android5.0之后,谷歌提供了用于在有限的窗口范围内显示大量数据的控件RecyclerView,与ListView控件相似,RecyclerView控件同样 是以列表的形式展示数据,并且数据都是通过适配器加载的。但是,RecyclerView的功能更加强大

    (1)展示效果: RecyclerView控件 可以通过LayoutManager类实现横向或竖向的列表效果、瀑布流效果和GridView效果,而ListView控件 只能实现竖直的列表效果

    (2)适配器: RecyclerView 控件使用的是RecyclerView.Adapter适配器,该适配器将BaseAdapter中的getView()方法拆分为onCreateViewHolder()方法和onBindViewHolder0方法,强制使用ViewHolder类,使代码编写规范化,避免了初学者写的代码性能不佳

    (3)复用效果: RecyclerView控件复用Item对象的工作由该控件自己实现,而ListView控件复用Item对象的工作需要开发者通过convertView的setTag()方法和getTag()方法进行操作

    (4)动画效果: RecyclerView控件可以通过setltemAnimator()方法为Item添加动画效果,而ListView控件不可以通过该方法为Item添加动画效果

    典例

    RecyclerView是com.android. support:recyclerview-v7库中的控件,因此需要将该库添加到程序中。首先选中程序名称,右击选择[Open Module Settings]选项,在Project Structure窗口中的左侧选择[app],接着选中[Dependencies]选项卡,单击右上角的绿色加号

    在这里插入图片描述

    activity_main.xml文件

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <android.support.v7.app.AlertController.RecycleListView
            android:id="@+id/id_recyclerview"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
        </android.support.v7.app.AlertController.RecycleListView>
    </RelativeLayout>
    

    activity_item.xml文件

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="16dp"
        android:gravity="center"
        android:orientation="horizontal">
        <ImageView
            android:id="@+id/iv"
            android:layout_width="120dp"
            android:layout_height="90dp"
            android:src="@drawable/cat"/>
        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:layout_marginTop="5dp">
            <TextView
                android:id="@+id/name"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="豹猫"
                android:textSize="20sp"
                android:textColor="#000000"/>
            <TextView
                android:id="@+id/introduce"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="16sp"
                android:textColor="#FF716C6D"
                android:layout_below="@+id/name"
                android:layout_marginTop="10dp"
                android:maxLines="2"
                android:ellipsize="end"
                android:text="没有被驯服的豹猫会杀鸡,它会渐渐靠近一只鸡,然后迅速扑过去杀掉它,也是十分的凶残啊!小豹猫一点也不示弱,照样会杀鸡哦!"/>
        </RelativeLayout>
    </LinearLayout>
    

    MainActivity.java文件

    public class MainActivity extends AppCompatActivity {
        private RecyclerView mRecyclerView;
        private HomeAdapter mAdapter;
        private String[] names = {"豹猫","马","毪菇","兔子"};
        private int[] icons = {R.drawable.cat,R.drawable.cow,R.drawable.horse,R.drawable.wolf};
        private String[] introduces = {"...","...","...","..."};
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mRecyclerView = (RecyclerView)findViewById(R.id.id_recyclerview);
            mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
            mAdapter = new HomeAdapter();
            mRecyclerView.setAdapter(mAdapter);
        }
    
        class HomeAdapter extends  RecyclerView.Adapter<HomeAdapter.MyViewHolder>{
            @Override
            public HomeAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
                MyViewHolder holder = new MyViewHolder(LayoutInflater.from(MainActivity.this).inflate(R.layout.activity_item,parent,false));
                return holder;
            }
            @Override
            public void onBindViewHolder(MyViewHolder holder, int position) {
                holder.name.setText(names[position]);
                holder.iv.setImageResource(icons[position]);
                holder.introduce.setText(introduces[position]);
            }
            @Override
            public int getItemCount() {
                return names.length;
            }
            class MyViewHolder extends RecyclerView.ViewHolder {
                TextView name;
                ImageView iv;
                TextView introduce;
                public MyViewHolder(View itemView) {
                    super(itemView);
                    name = (TextView) itemView.findViewById(R.id.name);
                    iv = (ImageView) itemView.findViewById(R.id.iv);
                    introduce = (TextView) itemView.findViewById(R.id.introduce);
                }
            }
        }
    }
    

    代码解析

    先在第11行代码获取RecyclerView控件,接着通过setLayoutManager()方法设置RecyclerView控件的显示方式为线性垂直的效果,然后通过setAdapter()方法将适配器HomeAdapter的对象设置在RecyclerView上

    在第17行创建一个HomeAdapter类继承自RecyclerView.Adapter类,并在其中重写方法,onCreateViewHolder()方法用于加载Item界面的布局文件,并将MyViewHolder类的对象返回,onBindViewHolder()方法用于将获取的数据设置在对应控件上,getItemCount()方法用于获取列表条目的总数

    第33行创建了一个MyViewHolder类继承自RecyclerView.ViewHolder类,在该类中获取Item界面上的控件

    关键语句:

    MyViewHolder holder = new MyViewHolder(LayoutInflater.from(MainActivity.this).inflate(R.layout.activity_item,parent,false));

    启动测试

    在这里插入图片描述

    3.5 自定义View

    通常开发Android应用的界面时,使用的控件都不直接使用View,而是使用View的子类。例如,如果要显示一段文字,可以使用View的 子类TextView,如果要显示-一个按钮,可以使用View的子类Button。虽然Android系统中提供了很多继承自View类的控件,但是在实际开发中,还会出现不满足需求的情况,因此我们可以通过自定义View的方式进行实现

    最简单的自定义View就是创建一个类继承View类或其子类,并重写该类的构造方法

    public class CustomView extends View{
        public CustomView(Context context){
            super(context);
        }
        public CustomView(Context context,AttributeSet attrs){
            super(context,attrs);
        }
    }
    

    定义好自定义类CustomView后,若想创建一个该类的对象,则需要使用到该类的第一个构造方法,若想要在布局文件中引入该自定义的CustomView控件,则需要使用到该类的第二个构造方法

    3.5.1 自定义View常用的3个方法

    由于系统自带的控件不能满足需求中的某种样式或功能,因此我们需要在自定义View中通过重写指定的方法来添加额外的样式和功能,自定义View常用的3个方法的具体介绍如下:

    (1) onMeasure()方法:该方法用于测量尺寸,在该方法中可以设置控件本身或其子控件的宽高

    onMeasure (int widthMeasureSpec, int heightMeasureSpec)

    onMeasure()方法中的第1个参数widthMeasureSpec表示获取父容器指定该控件的宽度,第2个参数heightMeasureSpec表示获取父容器指定该控件的高度
    widthMeasureSpec和heightMeasureSpec参数不仅包含父容器指定的属性值,还包括父容器指定的测量模式

    测量模式分为三种:

    ●EXACTLY: 当自定义控件的宽高的值设置为具体值时使用,如100dp、 match _parent等,此时控件的宽高值是精确的尺寸
    ●AT_MOST: 当自定义控件的宽高值为wrap_content时使用,此时控件的宽高值是控件中的数据内容可获得的最大空间值
    ●UNSPECIFIED: 当父容器没有指定自定义控件的宽高值时使用

    需要注意的是,虽然参数widthMeasureSpec和heightMeasureSpec是父容器指定该控件的宽高,但是该控件还需要通过setMeasuredDimension(int,int)方法设置具体的宽高

    (2) onDraw()方法:该方法用于绘制图像

    onDraw (Canvas canvas)

    onDraw0方法中的参数canvas表示画布。Canvas类经常与Paint类(画笔)配合使用,使用Paint类可以在Canvas类中绘制图像

    (3) onLayout()方法:onLayout()方 法用于指定布局中子控件的位置,该方法通常在自定义ViewGroup中重写

    onLayout (boolean changed, int left, int top, int right, int bottom)

    onLayout(方法中有5个参数,其中,第1个参数changed表示自定义View的大小和位置是否发生变化,剩余的4个参数left、top、 right、 bottom分别表示子控件与父容器左边、顶部、右边、底部的距离

    3.5.2 用自定义View在界面中显示圆形

    CustomView.java

    public class CustomView extends View {
    
        public CustomView(Context context) {
            super(context);
        }
        public CustomView(Context context,AttributeSet attrs) {
            super(context, attrs);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            int r = getMeasuredWidth()/2;
            int cX = getLeft()+r;
            int cY = getTop()+r;
            Paint paint = new Paint();
            paint.setColor(Color.RED);
            //绘制
            canvas.drawCircle(cX,cY,r,paint);
        }
    }
    

    activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="16dp">
        <com.itcast.CustomView.CustomView
            android:layout_width="100dp"
            android:layout_height="100dp"
            />
    </RelativeLayout>
    

    启动测试

    在这里插入图片描述

    如果文章对您有所帮助,记得一键三连支持一下哦~

    展开全文
  • 目录一、View和ViewGroup二、Android的五种常见控件2.1 文本控件2.1.1 TextView2.1.2 EditText2.2 按钮控件2.2.1 Button2.2.2 RadioButton2.2.3 CheckBox2.3 图片控件2.3.1 ImageView2.4 列表控件2.4.1 ListView...

    一、View和ViewGroup

    Android体系中UI的设计采用视图层次的结构。

    视图层次: 由View和ViewGroup组成。在创建UI时,开发人员不会真正去创建View或者ViewGroup,而是直接使用Android所提供的具有不同功能的控件,因此通常是看不到View或ViewGroup。

    View是Android系统中最基本的组件,同时也是Android所有可视组件的父类,它完成了构建按钮、文本框、时钟等诸多控件的基本功能。此外View还有一个非常重要的子类ViewGroup。
    View与ViewGroup的区别:ViewGroup能够容纳多个View作为ViewGroup的子组件,同时View也可以包含ViewGroup作为其子组件,所以View和ViewGroup是相互包容、“你中有我,我中有你”的关系。


    wrap_content: 是layout_width和layout_height的属性值之一,表示和自身内容一样的长度。(由内容决定)

    match_parent: 是layout_width和layout_height的属性值之一,表示和父组件一样的长度。

    fill_parent: 以填充布局单元内尽可能多的空间。

    margin属性: 外边距,指当前视图与其他视图间的距离,可以一次性指定上下左右四个外边距值,也可以一次性指定上下左右采用同一个边距值。

    android:layout_margin="10dp"
    
    android:layout_marginTop="10dp"
    android:layout_marginBottom="10dp"
    android:layout_marginLeft="10dp"
    android:layout_marginRight="10dp"
    

    padding属性: 内边距,指当前视图边距与其内容间的距离。赋值跟margin属性同类型。

    android:layout_padding="10dp"
    
    android:layout_paddingTop="10dp"
    android:layout_paddingBottom="10dp"
    android:layout_paddingLeft="10dp"
    android:layout_paddingRight="10dp"
    

    visible属性:

    android:visiblity="visible"
    android:visiblity="invisible"
    android:visiblity="gone"
    

    二、Android的五种常见控件

    2.1 文本控件

    在Android的体系结构中,TextView和EditView之间是父类和子类的关系。即EditText继承于TextView,因此EditText几乎具备TextView的所有功能,两者之间最大的不同在于:EditText能够支持用户输入,而TextView不能。

    2.1.1 TextView


    TextView是用于显示文字(字符串)的控件,可在代码中通过设置属性改变文字的大小、颜色、样式等功能。

    注意:
    颜色值组成(三原色)有三种表示方法

    1.#RGB:3位16进制整数,如:#f00

    2.#RRGGBB:#00ff00

    3.#AARRGGBB:#ff0000ff

    2.1.2 EditText


    EditText是可以进行编辑操作(用于用户输入和编辑文字或字符的控件)的文本框,将用户信息传递给Android程序。还可以为EditText控件设置监听器,用来测试用户输入的内容是否合法。

    2.2 按钮控件

    2.2.1 Button

    Android的体系结构中Button继承于TextView,而ImageButton继承于ImageView。虽然这两个控件继承于不同的控件,但是Button和ImageButton都是用于完成用户的单击按钮时的onClick事件。


    Button是按钮,是用于响应用户的一系列点击事件,使程序更加流畅和完整。

    点击事件(监听事件)实现方式(三种):

    ☞ 实现方式一:

    先在layout文件中指定onClick属性:Android:onClick=“click”。然后在Activity中实现这个click方法

    public void click (View v){
       /// 处理按钮监听事件
    }
    

    ☞ 实现方式二:在Activity中添加匿名内部类

    Button button = findViewById(R.id.button);
    
    
    button.setOnClickListener(new View.OnClickListener(){
        @Override
        public void OnClick(View v){
       /// 处理按钮监听事件
        Log.i("匿名内部类方式","button is clicked");  
        }
    });
    

    ☞ 实现方式三:

    public class MainActivity implements View.OnClickListener
    {
        //实现接口抽象方法
        public void onClick(View v){
        //处理按钮监听事件
        }
    }
    
    //在Activity中注册回调接口
    button.setOnClickListener(this);
    

    2.2.2 RadioButton


    RadioButton为单选按钮,它需要与RadioGroup配合使用,提供两个或多个互斥的选项集。(如男、女)
    RadioGroup是单选组合框,可容纳多个RadioButton,并把它们组合在一起,实现单选状态。


    RadioButton按钮的实现步骤:

    1.先在UI布局文件activity——main.xml中的LinearLayout标签中添加如下代码:

    <RadioGroup
       android:id="@+id/radiogroup"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:orientation="horizontal">
       
        <RadioButton
       android:id="@+id/radiobutton1"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:checked="true"
       android:text="Male"/>
       <RadioButton
       android:id="@+id/radiobutton2"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="Female"/>
       
     </RadioGroup>
    

    然后在MainActivity.java中添加onCreate函数中添加以下代码:

    RadioGroup radiogroup = (RadioGroup)findViewById(R.id.radiogroup);
    radioGroup.setOnCheckedChangeListener(new OnCheckedChangeListener(){
        public void onCheckedChanged(RadioGroup group,int checkedId){
        switch(checkedId){
            case R,id.maleradio:editText.setText("男");
            break;
         }
           case R,id.femaleradio:editText.setText("女");
            break;
         }
        }
    }
    
    ///另外Switch也可以用以下方法表示
    if(checked==R.id.radiobutton1){
        textView.setText("男");
    }
    else{
         case R,id.maleradio:editText.setText("女");
            break;
         } 
    }
    

    2.2.3 CheckBox


    CheckBox即多选按钮,允许用户在一组选项中进行单选和多选。用法与RadioButton类似。

    CheckBox按钮的实现步骤:

    1.先在UI布局文件activity——main.xml中的LinearLayout标签中添加代码(与radioBox的相似)
    2.

    注意:响应事件从何而来?(两个来源)

    1.由系统提供的,具有特定函数名的响应函数(在OnCreate中进行定义和实现)

    2.自定义响应函数名的方法来响应用户事件(放在Activity中作为一个成员函数来使用)

    public void CheckboxClicked(View view){
        boolean checked = ((Checked)view).isChecked();
        case R.id.meat:
        if(checked){
            editText.setText("肉类");
        }else{
            ...
        }
        break;
        
        ...
    }
    

    2.3 图片控件

    2.3.1 ImageView

    ImageView是视图控件,它继承于View,其功能是在屏幕中显示图像,ImageView类可以从各种来源加载图像(如资源库或网络),并提供缩放、裁剪、着色(渲染)等功能。

    ///在UI布局文件activity——main.xml中添加
    
    <ImageView 
    android:id="@id/imageView1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:srcCompat="@tolls:sample/backgrounds/scenic[0]"
    
    ///在MainActivity.java中添加onCreate函数中定义ImageView对象
    ImageView imageView;
    imageView.setImageResource(R.drawable.ic_launcher_foreground);
    

    2.4 列表控件

    2.4.1 ListView

    普通列表–ListView在程序中使用频率相对比较高,很多地方都会用到这个控件,其中的内容会以一个列表的形式显示出来,但是在使用ListView时需要一个适配器(应用自带适配器、z自定义适配器)(Adapter)类显示需要的内容。当显示的内容复杂的时候系统的适配器不能满足要求了,这时可以自定义适配器,写一个类继承BaseAdapter。

    2.4.2 Spinner

    下拉列表–Spinner 控件也是一种列表类型的控件,可以极大地提高用户的体验性。当需要用户选择时,可以提供一个下拉列表将所有可选的项列出来,供用户选择。

    2.4.3 ExpandableListView

    多级列表ExpandableListView控件提供的是一个多级列表(一般是两级)。


    如何实现这个两级列表呢?既然ExpandableListView采用列表的形式,它也是应该有一个适配器,但是它的适配器不是继承BaseAdapter,而是继承它独有的适配器BaseExpandableListView,同时也需要实现其中的几个方法:

    BaseExpandableListView中的方法:

    方法名称参数说明
    getGroudIdint groundPosition获取在给定的位置编号
    getChildIdint groundPosition,int childPosition获取给定组的孩子的ID
    getGroudCount获取第一级列表的列数
    getChildrenCountint groupPosition获取指定组中孩子的数量
    getGroupint groupPosition获取定组相关的数据
    getGroupViewint groupPositin,boolean isExpanded,View convertView,ViewGroup parent获取一个显示的视图给定组
    getChildint groupPosition,int childPosition获取与孩子在给定的组相关的数据
    getChildViewint groupPosition,boolean isLastChild,View convertView,ViewGroup parent获取一个视图显示在给定的组的孩子的数据

    2.5 时间日期控件

    2.5.1 AnalogClock(模拟时钟的显示方式)和DigitalClock

    这两个控件都是通过获取系统时间展示给用户。AnalogClock是以模拟时钟的形式展示,DigitalClock是以数字时钟 的形式向用户展示。

    2.5.2 DatePicker和TimePiker

    用户可以通过这两个控件来设置日期和时间,DatePicker(会在Android 4.0中自动产生一个日历的功能)用于选择日期,TimePicker用于选择时间。

    三、五种常用的布局

    在Android程序中界面是通过布局文件设定的,在每个应用程序创建会默认包含一个主界面布局,该布局位于res/layout目录中。实际开发中每个应用程序都包含多个界面,而程序默认提供的一个主界面布局无法满足需求,因此经常会在程序中添加多个布局。

    在Android中有两种方式创建布局:一种是在项目中的layout文件夹中写XML,将各个布局写在XML中;一种是在程序中通过代码去编写,这种方式一般用得比较少。

    四种布局常用的单位:

    1.px: 像素,即在屏幕中可以显示最小元素单位。

    2.pt: 磅数,一磅等于1/72英寸,一般pt作为字体的单位来显示

    3.dp(与密度无关的像素,dp与dip相同): 基于屏幕密度的抽象单位。不同设备由不同的显示效果,更具分辨率的不同来去顶控件的尺寸。

    4.sp: 可伸缩像素,采用与dp相同的设计理念,推荐设置文字大小时使用。

    3.1 线性布局(LinearLayout)

    线性布局就是将一些控件排放在一条线上,但是有水平方向和垂直方向两种。水平和垂直方向的控制由属性android:orientation来控制,这个属性有两个值:垂直(Vertical)和水平(Horizaontal),在线性布局中还有一些比较常用的属性,如:android:gravity、android:weight(控件的权值)等。

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical"
        android:background="#ffffff"
        >
        <LinearLayout
            android:id="@+id/LinearLayout01"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_weight="1.0"
            android:orientation="horizontal"
            >
            <Button
                android:layout_width="wrap_content"
                android:layout_height="fill_parent"
                android:gravity="center_horizontal"
                android:text="按钮1"
                android:layout_weight="1.0"
                />
            <Button
                android:layout_width="wrap_content"
                android:layout_height="fill_parent"
                android:gravity="center_horizontal"
                android:text="按钮2"
                android:layout_weight="1.0"
                />
            <Button
                android:layout_width="wrap_content"
                android:layout_height="fill_parent"
                android:gravity="center_horizontal"
                android:text="按钮3"
                android:layout_weight="1.0"
                />
        </LinearLayout>
        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">
    
            <Button
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:text="按钮4"
                android:layout_weight="1.0"
                />
            <Button
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:text="按钮5"
                android:layout_weight="1.0"
                />
            <Button
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:text="按钮6"
                android:layout_weight="1.0"
                />
        </LinearLayout>
    </LinearLayout>
    

    运行效果效果如下:

    3.2 相对布局(RelativelLayout)

    线对布局是指按照控件间的相对位置进行布局,也就是说我们可以选一个控件作为参照,其他的控件可以在它的上边、下边、左边及右边等。

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical"
        android:background="#ffffff"
        >
       <TextView
           android:id="@+id/textView01"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="AA"
           android:textColor="#00FF00"
           android:textSize="22sp"
           android:layout_marginLeft="20px"/>
    
        <TextView
        android:id="@+id/textRight"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
            android:layout_toRightOf="@id/textView01"
        android:text="BB"
            android:textColor="#FF0000"
            android:textSize="22sp"
        android:layout_marginLeft="20px"/>
        <TextView
            android:id="@+id/text02"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/textView01"
            android:text="CC"
            android:textColor="#00FFFF"
            android:textSize="22sp"
            android:layout_marginLeft="20px"/>
        <TextView
            android:id="@+id/textView02"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/textRight"
            android:layout_toRightOf="@id/text02"
            android:text="DD"
            android:textColor="#000000"
            android:textSize="22sp"
            android:layout_marginLeft="20dip"/>
    
    </RelativeLayout>
    

    运行结果如下:
    BB相对于AA的左边,CC相对于AA的下边边,DD相对于BB的下边且相对于CC的右边

    3.3 帧布局(FrameLayout)

    帧布局是五大布局中最简单的一个布局,在这个布局中,整个界面被当成一块空白备用区域,所有的子元素都不能被指定放置的位置,它们统统放于这块区域的左上角,并且后面的子元素直接覆盖在前面的子元素上,将前面的子元素部分和全部遮挡。

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/FrameLayout01"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:background="#ffffff"
        >
        <TextView
            android:id="@+id/TextView01"
            android:layout_width="1000px"
            android:layout_height="1000px"
            android:background="#ff0000"
            android:text="文本框1"
            android:textColor="#ffffff"/>
        <TextView
            android:id="@+id/TextView02"
            android:layout_width="750px"
            android:layout_height="750px"
            android:background="#0000ff"
            />
        <TextView
            android:id="@+id/TextView03"
            android:layout_width="500px"
            android:layout_height="500px"
            android:background="#00ff00"
            />
    </FrameLayout>
    

    运行结果如下:

    3.4 表格布局(TableLayout)

    表格布局适用于N行N列的布局格式。一个TableLayout由许多TableRow组成,一个TableRow就代表TableLayout中的一行。TableRow的数量决定表格的行数。而表格的列数是由包含最多控件的TableRow决定。

    <?xml version="1.0" encoding="utf-8"?>
    <TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:background="#ffffff"
        android:stretchColumns="1"
        >
        <TableRow>
        <TextView
            android:layout_column = "1"
            android:padding="3dip"
            android:textColor="#000000"
            android:text="open..."/>
        <TextView
            android:gravity="right"
            android:padding="3dip"
            android:textColor="#000000"
            android:text="Ctrl_o"/>
        </TableRow>
    
        <View
            android:layout_height="2dip"
            android:background="#FF909090"/>
    
        <TableRow>
        <TextView
            android:layout_column = "1"
            android:padding="3dip"
            android:textColor="#000000"
            android:text="Save..."/>
        <TextView
            android:gravity="right"
            android:padding="3dip"
            android:textColor="#000000"
            android:text="Ctrl_s"/>
        />
        </TableRow>
    
        <View
            android:layout_height="2dip"
            android:background="#FF909090"/>
    
        <TableRow>
        <TextView
            android:layout_column = "1"
            android:padding="3dip"
            android:textColor="#000000"
            android:text="Save As..."/>
        <TextView
            android:gravity="right"
            android:padding="3dip"
            android:textColor="#000000"
            android:text="Ctrl_shift_s"/>
        </TableRow>
    
        <View
            android:layout_height="2dip"
            android:background="#FF909090"/>
    
        <TableRow>
        <TextView
            android:layout_column = "1"
            android:padding="3dip"
            android:textColor="#000000"
            android:text="X"/>
        <TextView
            android:gravity="right"
            android:padding="3dip"
            android:textColor="#000000"
            android:text="Import..."/>
        </TableRow>
    </TableLayout>
    

    运行结果如下:

    3.5 绝对布局(AbsoluteLayout)

    绝对布局是通过指定x、y坐标来控制每一个控件位置的。

    四、参考资料

    《从零开始学Android编程》

    中国大学慕课网:Android应用开发

    中国大学慕课网:Android基础应用开发

    展开全文
  • web常见控件介绍

    万次阅读 2018-05-18 08:40:05
    常见控件: 1.文本输入框(TextBox) 2.按钮控件(Button) 3.下拉选框(DropList) 4.日期/时间控件(Date/TimePicker) 5.(图片、文件)上传控件(Upload) 6.树形控件(TreeView) 7.列表框(ListBox) 8...
  • 一、常见界面布局及案例 二、常见界面控件及案例 三、Activity
  • Android 常见界面控件(对话框篇)

    千次阅读 2022-01-22 11:39:06
    第3章 Android 常见界面控件(简单控件篇) 目录第3章 Android 常见界面控件(简单控件篇)3.2 AlterDialog对话框的使用3.2.1 AlterDialog对话框概述3.2.2 普通对话框3.2.3 单选对话框3.2.4 多选对话框3.2.5 自定义...
  • 针对 win7 8 10(32位64位)加载 控件 MSCOMCTL.OCX 时提示常见4中错误的解决办法。
  • C#常见控件与SQL Sever数据库交互

    千次阅读 2022-03-24 14:00:36
    那么,我们先创建两个成员(对象) string sqlcon = "Data Source=DESKTOP-TF1OFLN;Initial Catalog=Demo;Integrated Security=True"; DataSet ds = new DataSet(); 这里,我们先用一个string保存数据库的连接...
  • iOS常见控件的基本使用

    万次阅读 2016-04-29 17:01:44
    UIView 常见属性和方法 UIView属性 UIView方法 UIControl 常用控件 UIImageView 图片显示控件android ImageView UISlider可拖动的进度条 android SeekBar UIButton按钮 UILable 文本 android TextView UIText 文本...
  • 常见控件 控件对象属性设置方法 lable标签 输入控件Entry Text多行文本框 单(复)选框 画布Canvas 布局管理器 grid布局管理器 pack布局管理器 place布局管理器 事件对象 鼠标和键盘事件 event对象常用...
  • 支持指定宽高缩放、支持比例缩放、只支持常见图片格式 支持直接返回字节集、或者直接写出指定目录。 目前发现的缺点也可以算优点 就是 缩小后 图片是真的缩小 而不是缩小后 像素还在 重新放大将不会还原图片
  • 12.16 Android常见标签 UI控件

    千次阅读 2021-12-17 18:09:16
    background控件背景色 maxHeight最大高度 maxWidth最大宽度 adjustViewBounds是否需要ImageView调整自己的边界,保证图片的显示比例 常见方法:setAlpha(Int)透明度、setImageBitmap显示内容为Bitmap对象、...
  • MFC开发 常见控件

    千次阅读 2016-03-12 10:40:58
    APB还包含了其他效果,比如,设置整个按钮对象或其背景透明以及不同的透明度级别的设定。APB提供了针对图片和标题的垂直和水平对齐以及合并的功能。 Prof-UIS也算一个, 不过免费版本功能不多 用这样的库...
  • 下面重点介绍前一种,目前常见的有两种方法,基本上大同小异: 第一种,在主窗体类中定义一个静态成员,来保存当前主窗体对象,例如: 代码如下:public static yourMainWindow pCurrentWin = null; 然后在主窗体...
  • Active-X barcode controls 试用版 试用版 开发语言: ActiveX 可用平台: VC/VB/VBA 当前版本: v7.3 Active-X barcode controls是一...像一个对象或一个完全可编程的 ActiveX 控件一样使用。不需要 MFC 动态链接库。
  • 一、简单介绍 ...在IOS中,UIWindow对象并没有像windows应用程序中常见的关闭框或标题栏这样的部件,普通用户不能直接对其进行关闭或其它操作。所有对窗口的操作都需要通过其编程接口来实现。应用程序
  • MFC 对话框常用控件详解

    千次阅读 2019-08-19 10:24:28
    文章目录按钮控件命令按钮(Button)单选按钮(Radio Button)复选框(Check Box)编辑框(Edit Control) 按钮控件 按钮控件包括命令按钮(Button)、单选按钮(Radio Button)和复选框(Check Box)等。 按钮...
  • 简易日历作为javascript中Date对象常见应用,用途较广泛,本文将详细说明简易日历的实现思路。 效果演示   HTML说明  使用type=number的两个input分别作为年和月的输入控件,这样在高级浏览器下自带调节按钮 ...
  • java Swing常用控件与使用方法

    千次阅读 2018-11-16 22:59:59
    各种窗口控件的显示,  JFrame,JLabel,JPanel,JTextField,JPasswordField,JRadioButton ,  JComboBox&lt;&gt; ,JButton,JTextArea ,JScrollPane,DefaultListModel&lt;&gt;  JList&...
  • 文章目录一、QT输入控件二、QT输出控件三、使用举例1.建立工程 eg:工程名input_out2.添加widget.h内容3.添加widget.cpp内容4.ctrl+r 运行四、总结 一、QT输入控件 二、QT输出控件 三、使用举例 1.建立工程 eg:...
  • 【工控老马出品,必属精品...源码说明:无需任何OCX或DLL控件,直接调用windows内置对象实现HTTP请求,支持GET/POST等各种请求方法。返回HTML支持常见编码处理,避免中文乱码。 适合人群:新手及有一定经验的开发人员
  • delphi FMX控件常见属性

    千次阅读 2017-11-01 22:07:14
    EnableDragHighlight:指定拖动对象超出控件时是否突出显示控件。 Height : 指定控件的垂直尺寸(像素) Width : 指定控件的水平尺寸 HIT :当鼠标放在控件上显示 HitTest :当这个属性为True时hit才...
  • Qt中常用控件

    千次阅读 2021-06-24 18:55:16
    一、输入类控件 1、QLineEdit 单选文本框,主要用来从界面获取数据,常用于获取用户名密码。 常用设置: 字体字号设置 垂直、水平对齐设置 只读设置 输入模式: Normal 正常模式 NoEcho 不显示输入的内容 PassWord ...
  • matlab GUI编程技巧系列文章索引:Matlab GUI编程技巧(一):如何使gui编的界面一运行就居中Matlab GUI编程技巧(二):函数结构与参数传递Matlab GUI编程技巧(三):把figure文件显示到GUI的axe上 ...控件.
  • 控件分类

    千次阅读 2019-06-03 17:36:27
    控件分类 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 开发工具与关键技术:Visual Studio 2015 作者:李成富 撰写时间:2019年06月01日 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~...
  • Auto.js学习笔记1—基于控件的操作

    千次阅读 2021-12-03 20:46:48
    checkable 控件是否可勾选 checked 控件是否可已勾选 scrollable 控件是否可滑动 selected 控件是否已选择 editable 控件是否可编辑 visibleToUser 控件是否可见 enabled 控件是否已启用 depth 控件的布局...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 90,012
精华内容 36,004
热门标签
关键字:

常见控件对象