Android 之自定义组件

1、如何在一个按钮上放上一张图片?
把按钮和图片套在一个FrameLayout中

<!-- 必须将button和ImageView分别嵌套在两个LinearLayout中才能 实现将图片放在按钮上 -->
   <FrameLayout
    android:orientation="horizontal"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">
    <LinearLayout
     android:layout_width="wrap_content"
     android:layout_height="wrap_content">
     <Button
      style="@style/menu_btn_style"
      android:id="@+id/fan_us"
      android:text="@string/mainmenu_facebook_fan_us" />
    </LinearLayout>
    <LinearLayout
     android:layout_width="wrap_content"
     android:layout_height="wrap_content">
     <ImageView
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_marginLeft="16dp"
      android:layout_marginTop="13dp"
      android:src="@drawable/facebookicon" />
    </LinearLayout>
   </FrameLayout>
   
   
   
2、如何自定义组件
自定义一个下划线形式的输入框

第一:确定要画多少条下划线
第二:每条线的宽度
第三:下划线的间距

(1)自定义文本输入框
package com.heima.guesswho.util;

import com.heima.android.guesswho.R;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.widget.EditText;

public class DashlineEditText extends EditText {
 /*
  * 假设下划线总长100个单位,要画7条下划线,每条下划线间距为2个单位
  * 具体算法如下:
  * 每条下划线的长度:(100+2)/7-2
  * for(int i = 0;i<7,i++){
  *     第i条线
  *   x1 = ((100+2)/7)*i
  *   y1 = getHeight()
  *   x2 = ((100+2)/7)*i+(100+2)/7-2
  *   y2 = getHeight()
  * }
  *
  */
 
 private Paint linePaint = new Paint();
 private  int segmentCount = 8;//总共画8条分割线,可以作为默认值
 private  int distance = 5;//每个分割线的间距为4个单位,可以作为默认值
 
 /*
  * 从布局文件中得到对应属性的值
  */
 public DashlineEditText(Context context, AttributeSet attrs) {
  super(context, attrs);
  setBackgroundDrawable(null);//消除文本框效果的作用
  //linePaint.setColor(Color.RED);//设置画笔的颜色
  
  TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.DashLineET);
  segmentCount = array.getInt(R.styleable.DashLineET_segment_count, segmentCount);//从指定属性中拿到对应的值,若没设置,则用默认值
  distance = array.getInt(R.styleable.DashLineET_distance, distance);
  int color = array.getInt(R.styleable.DashLineET_dashline_color, Color.RED);
  linePaint.setColor(color);
 }

 @Override
 protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);
  int width = getWidth();//自定义控件的宽度
  int height = getHeight()-3;//必须减去数才能显示出下划线
  
  //画出每一条下划线
  for(int i = 0; i < segmentCount; i++){
   int oneSegmentWidth = (width+distance)/segmentCount - distance;//每条下划线的长度
   int startX = (segmentCount+distance)*i ;//每条下划线的起点位置
   int stopX = startX+oneSegmentWidth ;//每条下划线的终点位置
   canvas.drawLine(startX, height, stopX, height, linePaint);
  }  
 }
}


(2)布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:orientation="vertical"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent">
 <TextView
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:text="@string/debug_name" />

 <com.heima.guesswho.util.DashlineEditText
  android:layout_width="100dp"
  android:layout_height="12dp"
  android:text="test" />
</LinearLayout>


定义自定义组件的属性

第一步:在string.xml文件中配置declare-styleable

   <!-- 定义DashLineEditText的属性 -->
 <declare-styleable
  name="DashLineET">
  <attr
   name="segments_cnt"
   format="integer" />
  <attr
   name="distance"
   format="dimension" />
  <attr
   name="dashline_color"
   format="color" />
  <attr
   name="hint_msg"
   format="reference" />
  <attr
   name="hint_color"
   format="color" />
 </declare-styleable>
 
第二步:在自定义组件中复写构造方法,用来获取布局文件中属性的值

 
 /*
  * 从布局文件中得到对应属性的值
  */
 public DashlineEditText(Context context, AttributeSet attrs) {
  super(context, attrs);
  setBackgroundDrawable(null);//消除文本框效果的作用
  //linePaint.setColor(Color.RED);//设置画笔的颜色
  
  TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.DashLineET);
  segmentCount = array.getInt(R.styleable.DashLineET_segment_count, segmentCount);//从指定属性中拿到对应的值,若没设置,则用默认值
  distance = array.getInt(R.styleable.DashLineET_distance, distance);
  int color = array.getInt(R.styleable.DashLineET_dashline_color, Color.RED);
  linePaint.setColor(color);
 }


第三步:在使用自定义组件的布局文件中加入命名空间

如xmlns:heima="http://schemas.android.com/apk/res/com.heima.android.guesswho"


heima 为我们使用属性时使用的前缀,相当于使用Android属性时要使用android前缀一样
其中com.heima.android.guesswho,为清单文件标识应用的包名

布局文件如下


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:heima="http://schemas.android.com/apk/res/com.heima.android.guesswho"
 android:orientation="vertical"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent">
 <TextView
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:text="@string/debug_name" />

 <com.heima.guesswho.util.DashlineEditText
  android:layout_width="100dp"
  android:layout_height="12dp"
  heima:segment_count="10"
  heima:distance="3"
  android:text="test" />
</LinearLayout>
  


 <com.heima.guesswho.util.DashlineEditText
    android:layout_width="210dip"
   heima:segment_count="9"
    heima:distance="4dip"
    heima:dashline_color="@color/font_white"
    android:layout_height="wrap_content"
    android:textColor="#FF0000"
    android:hint="@string/input_name_prompt"
    android:text="" />

原文地址:https://www.cnblogs.com/csj007523/p/2097510.html