zoukankan      html  css  js  c++  java
  • #安卓杂记(七):自定义控件及属性获取

    平日里喜欢阅读网易云阅读客户端的资讯,对订阅版块的设计甚是喜爱,就想琢磨着如何实现类似于卡片式的文件夹的样式:
    网易云客户端订阅版块
    显然,安卓里没有自带的这样的控件。有人一定会问,每个卡片无非就是个LinearLayout或RelativeLayout啊。的确没错。如果用RelativeLayout写的话,许是这样的罢:

    <RelativeLayout 
                android:id="@+id/news01"
                android:layout_height="match_parent"
                android:layout_width="0dp"
                android:layout_marginTop="2dp"
                android:layout_marginLeft="2dp"
                android:background="@color/white"
                android:clickable="true"
                android:layout_weight="1">
    
                <ImageView 
                    android:contentDescription="@string/news_image"
                    android:src="@drawable/news01"
                    android:layout_height="wrap_content"
                    android:layout_width="wrap_content"
                    android:layout_centerInParent="true"/>
    
                <TextView 
                    android:layout_centerHorizontal="true"
                    android:layout_alignParentBottom="true"
                    android:layout_marginBottom="10dp"
                    android:layout_height="wrap_content"
                    android:layout_width="wrap_content"
                    android:text="国内"/>
    
     </RelativeLayout> 

    嗯,确实没错,可是十个RelativeLayout一起叠加下去,不仅代码冗余难读,而且不易维护。再者,如果我们要在这个Layout上加个Listener呢,莫非也要一个一个加?显然不成。由此,自定义控件就变得格外有意义。

    一、定义xml样式

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:id="@+id/news_card"
                android:layout_height="match_parent"
                android:layout_width="match_parent"
                android:focusable="true"
                android:clickable="true"
                android:background="@color/white">
    
                <ImageView 
                    android:id="@+id/card_image"
                    android:src="@drawable/news02"
                    android:layout_height="wrap_content"
                    android:layout_width="wrap_content"
                    android:layout_centerInParent="true"/>
    
                <TextView 
                    android:id="@+id/card_text"
                    android:layout_centerHorizontal="true"
                    android:layout_below="@id/card_image"
                    android:layout_marginTop="10dp"
                    android:layout_height="wrap_content"
                    android:layout_width="wrap_content"
                    android:text="card_name"/>
    
            </RelativeLayout>

    我们期待的样子是这样嘀:
    自定义样式

    二、定义attrs.xml文件

    定义自定义控件属性需要在res/values文件下定义一个attrs.xml文件,以布局文件可以调用定义属性:

    <?xml version="1.0" encoding="utf-8"?>
        <resources >
            <declare-styleable name="newsCard">
                <attr name="card_id" format="integer"/>
                <attr name="text" format="string"/>
                <attr name="src" format="reference"/>
            </declare-styleable>
        </resources> 

    其中,中的format有以下几种格式:
    string , integer , dimension , reference , color , enum
    reference指资源引用。

    三、布局文件中使用控件属性

    <?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/com.example.courseexamplev2"
        android:id="@+id/news_layout"
        android:layout_margin="10dp"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        >
    
       <LinearLayout 
            android:baselineAligned="false"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:background="@color/background_blue"
            android:orientation="horizontal">
    
           <com.example.courseexamplev2.NewsCard
               android:id="@+id/card01"
               android:layout_width="0dp"
               android:layout_marginTop="2dp"
               android:layout_marginLeft="2dp"
               android:layout_height="match_parent"
               android:layout_weight="1"
               app:card_id="1"
               app:text="国内"
               app:src="@drawable/news01">
    
           </com.example.courseexamplev2.NewsCard>
    
            <com.example.courseexamplev2.NewsCard
               android:id="@+id/card02"
               android:layout_width="0dp"
               android:layout_marginTop="2dp"
               android:layout_marginLeft="2dp"
               android:layout_height="match_parent"
               android:layout_weight="1"
               app:card_id="2"
               app:text="国际"
               app:src="@drawable/news02">  
           </com.example.courseexamplev2.NewsCard>
    
            <com.example.courseexamplev2.NewsCard
               android:id="@+id/card03"
               android:layout_width="0dp"
               android:layout_marginTop="2dp"
               android:layout_marginLeft="2dp"
               android:layout_marginRight="2dp"
               android:layout_height="match_parent"
               android:layout_weight="1"
               app:card_id="3"
               app:text="社会"
               app:src="@drawable/news03"> 
           </com.example.courseexamplev2.NewsCard>
    
        </LinearLayout>
    
        <LinearLayout 
            android:baselineAligned="false"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:background="@color/background_blue"
            android:orientation="horizontal">
    
            <com.example.courseexamplev2.NewsCard
               android:id="@+id/card04"
               android:layout_width="0dp"
               android:layout_marginTop="2dp"
               android:layout_marginLeft="2dp"
               android:layout_height="match_parent"
               android:layout_weight="1"
               app:card_id="4"
               app:text="财经"
               app:src="@drawable/news04">  
           </com.example.courseexamplev2.NewsCard>
    
            <com.example.courseexamplev2.NewsCard
               android:id="@+id/card05"
               android:layout_width="0dp"
               android:layout_marginTop="2dp"
               android:layout_marginLeft="2dp"
               android:layout_height="match_parent"
               android:layout_weight="1"
               app:card_id="5"
               app:text="体育"
               app:src="@drawable/news05">  
           </com.example.courseexamplev2.NewsCard>
    
            <com.example.courseexamplev2.NewsCard
               android:id="@+id/card06"
               android:layout_width="0dp"
               android:layout_marginTop="2dp"
               android:layout_marginLeft="2dp"
               android:layout_marginRight="2dp"
               android:layout_height="match_parent"
               android:layout_weight="1"
               app:card_id="6"
               app:text="科技"
               app:src="@drawable/news06">  
           </com.example.courseexamplev2.NewsCard>
    
        </LinearLayout>
    
        <LinearLayout 
            android:baselineAligned="false"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:background="@color/background_blue"
            android:orientation="horizontal">
    
            <com.example.courseexamplev2.NewsCard
               android:id="@+id/card07"
               android:layout_width="0dp"
               android:layout_marginTop="2dp"
               android:layout_marginLeft="2dp"
               android:layout_height="match_parent"
               android:layout_weight="1"
               app:card_id="7"
               app:text="播客"
               app:src="@drawable/news07">
            </com.example.courseexamplev2.NewsCard>
    
            <com.example.courseexamplev2.NewsCard
               android:id="@+id/card08"
               android:layout_width="0dp"
               android:layout_marginTop="2dp"
               android:layout_marginLeft="2dp"
               android:layout_height="match_parent"
               android:layout_weight="1"
               app:card_id="8"
               app:text="股市"
               app:src="@drawable/news08">
            </com.example.courseexamplev2.NewsCard>
    
             <RelativeLayout
                 android:id="@+id/news09"
                 android:layout_width="0dp"
                 android:layout_height="match_parent"
                 android:layout_marginTop="2dp"
                 android:layout_marginLeft="2dp"
                 android:layout_marginRight="2dp"
                 android:background="@color/white"
                 android:layout_weight="1" >
    
                <ImageView 
                    android:src="@drawable/icon_add"
                    android:contentDescription="@string/news_image"
                    android:layout_height="wrap_content"
                    android:layout_width="wrap_content"
                    android:layout_centerInParent="true"/>
    
            </RelativeLayout>
    
        </LinearLayout>
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:background="@color/background_blue"
            android:baselineAligned="false"
            android:orientation="horizontal" >
    
            <RelativeLayout
                android:id="@+id/news10"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_marginTop="2dp"
                android:layout_marginLeft="2dp"
                android:layout_marginBottom="2dp"
                android:background="@color/white"
                android:layout_weight="1" >
    
                <ImageView 
                    android:src="@drawable/icon_add"
                    android:contentDescription="@string/news_image"
                    android:layout_height="wrap_content"
                    android:layout_width="wrap_content"
                    android:layout_centerInParent="true"/>
            </RelativeLayout>
    
            <RelativeLayout
                android:id="@+id/news11"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_marginTop="2dp"
                android:layout_marginLeft="2dp"
                android:layout_marginBottom="2dp"
                android:background="@color/white"
                android:layout_weight="1" >
    
                <ImageView 
                    android:src="@drawable/icon_add"
                    android:contentDescription="@string/news_image"
                    android:layout_height="wrap_content"
                    android:layout_width="wrap_content"
                    android:layout_centerInParent="true"/>
            </RelativeLayout>
    
            <RelativeLayout
                android:id="@+id/news12"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_margin="2dp"
                android:background="@color/white"
                android:layout_weight="1" >
    
                <ImageView 
                    android:src="@drawable/icon_add"
                    android:contentDescription="@string/news_image"
                    android:layout_height="wrap_content"
                    android:layout_width="wrap_content"
      android:layout_centerInParent="true"/>
            </RelativeLayout>
    
        </LinearLayout>
    
    </LinearLayout>

    注意,
    必须在表头注明命名空间:xmlns:app=http://schemas.android.com/apk/res/com.example.courseexamplev2

    四、自定义控件的类

    package com.example.courseexamplev2;
    
    import android.content.Context;
    import android.content.res.TypedArray;
    import android.graphics.drawable.Drawable;
    import android.util.AttributeSet;
    import android.view.LayoutInflater;
    import android.widget.ImageView;
    import android.widget.RelativeLayout;
    import android.widget.TextView;
    
    public class NewsCard extends RelativeLayout{ 
    //  private RelativeLayout layout;
        private ImageView cardView;
        private TextView cardText;
        private String text;
        private Drawable src;
        int cardId;
    
        public NewsCard(Context context) {
            super(context);
        }
    
        public NewsCard(Context context, AttributeSet attrs) {  
            super(context, attrs);  
      //在构造函数中将Xml中定义的布局解析出来。
            LayoutInflater.from(context).inflate(R.layout.news_card, this, true);
    
            cardView = (ImageView)findViewById(R.id.card_image);
            cardText = (TextView)findViewById(R.id.card_text);
            TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.newsCard);  
    
            text = a.getString(R.styleable.newsCard_text);
                if(text != null)
                    cardText.setText(text);
    
            src = a.getDrawable(R.styleable.newsCard_src);
                if(src != null)
                    cardView.setImageDrawable(src);
    
            cardId = a.getInt(R.styleable.newsCard_card_id, 0);
    
            a.recycle();
    
       }  
    
        public void setImageResource(int resId){
            cardView.setImageResource(resId);
        }
        public void setTextViewText(String text){
            cardText.setText(text);
        }
    
     }
    

    在自定义控件的构造方法中,利用:

    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.newsCard);  

    来获取自定义控件的属性集合,这样就可以利用a调用各种属性了。
    当然,为了简便,我没有在示例中添加点击事件。来看看最终效果吧:
    最终效果

  • 相关阅读:
    【sqlalchemy】使用正确的DB_URI却报错密码错误-密码中包含特殊符号导致
    为什么只调用了1次函数,但是该函数却被执行了2次呢?
    【flask】使用类组织配置-使用工厂函数创建程序实例
    【python3】configparser读取ini配置文件
    【flask】使用配置类管理app测试环境-demo版
    【flask】flask项目配置 app.config
    【flask】环境配置-python-dotenv的使用
    从pip+requirements.txt+virtualenv管理依赖到使用pipenv管理依赖-修改布署方式
    【MAC】安装chrome浏览器
    【MAC】图片编辑工具-合成图片
  • 原文地址:https://www.cnblogs.com/jscitlearningshare/p/4457938.html
Copyright © 2011-2022 走看看