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调用各种属性了。
    当然,为了简便,我没有在示例中添加点击事件。来看看最终效果吧:
    最终效果

  • 相关阅读:
    POJ1486 Sorting Slides 二分图or贪心
    POJ2060 Taxi Cab Scheme 最小路径覆盖
    POJ3083 Children of the Candy Corn 解题报告
    以前的文章
    POJ2449 Remmarguts' Date K短路经典题
    这一年的acm路
    POJ3014 Asteroids 最小点覆盖
    POJ2594 Treasure Exploration 最小路径覆盖
    POJ3009 Curling 2.0 解题报告
    POJ2226 Muddy Fields 最小点集覆盖
  • 原文地址:https://www.cnblogs.com/jscitlearningshare/p/4457938.html
Copyright © 2011-2022 走看看