Android突击:定制控件

继承,组合和绘制。
在安卓里,好多控件都是TextView的子控件
容器类:布局类,其实也是个控件,不过他可以包含其他的控件。

组合方式构建:
1,在控件类中定义TextView和EditText类中
2,在控件类的构造方法读取控件的属性
3,根据控件属性值设置TextView和EditText值及二者的相对位置。
这个例子是从线性布局中继承。这个是不用带命名空间的。
所有的控件类都会有context,所有的属性名值即放在res目录下的资源就是用AttributeSet里。
  1. public class LabelEditText extends LinearLayout
  2. {
  3. private TextView textView;
  4. private String labelText;
  5. private int labelFontSize;
  6. private String labelPosition;
  7. public LabelEditText(Context context, AttributeSet attrs)
  8. {
  9. super(context, attrs);
  10. // 读取labelText属性的资源ID
  11. int resourceId = attrs.getAttributeResourceValue(null, "labelText", 0);
  12. // 未获得资源ID,继续读取属性值
  13. if (resourceId == 0)
  14. labelText = attrs.getAttributeValue(null, "labelText");
  15. // 从资源文件中获得labelText属性的值
  16. else
  17. labelText = getResources().getString(resourceId);
  18. // 如果按两种方式都未获得labelTex属性的值,表示未设置该属性,抛出异常
  19. if (labelText == null)
  20. {
  21. throw new RuntimeException("必须设置labelText属性.");
  22. }
  23. // 获得labelFontSize属性的资源ID
  24. resourceId = attrs.getAttributeResourceValue(null, "labelFontSize", 0);
  25. // 继续读取labelFontSize属性的值,如果未设置该属性,将属性值设为14
  26. if (resourceId == 0)
  27. labelFontSize = attrs.getAttributeIntValue(null, "labelFontSize",
  28. 14);
  29. // 从资源文件中获得labelFontSize属性的值
  30. else
  31. labelFontSize = getResources().getInteger(resourceId);
  32. // 获得labelPosition属性的资源ID
  33. resourceId = attrs.getAttributeResourceValue(null, "labelPosition", 0);
  34. // 继续读取labelPosition属性的值
  35. if (resourceId == 0)
  36. labelPosition = attrs.getAttributeValue(null, "labelPosition");
  37. // 从资源文件中获得labelPosition属性的值
  38. else
  39. labelPosition = getResources().getString(resourceId);
  40. // 如果未设置labelPosition属性值,将该属性值设为left
  41. if (labelPosition == null)
  42. labelPosition = "left";
  43. String infService = Context.LAYOUT_INFLATER_SERVICE;
  44. LayoutInflater li;
  45. // 获得LAYOUT_INFLATER_SERVICE服务
  46. li = (LayoutInflater) context.getSystemService(infService);
  47. LinearLayout linearLayout = null;
  48. // 根据labelPosition属性的值装载不同的布局文件
  49. if("left".equals(labelPosition))
  50. linearLayout = (LinearLayout)li.inflate(R.layout.labeledittext_horizontal, this);
  51. else if("top".equals(labelPosition))
  52. linearLayout = (LinearLayout)li.inflate(R.layout.labeledittext_vertical, this);
  53. else
  54. throw new RuntimeException("labelPosition属性的值只能是left或top.");
  55. // 下面的代码从相应的布局文件中获得了TextView对象,并根据LabelTextView的属性值设置TextView的属性
  56. textView = (TextView) findViewById(R.id.textview);
  57. //textView.setTextSize((float)labelFontSize);
  58. textView.setTextSize(labelFontSize);
  59. textView.setText(labelText);
  60. }
  61. }

继承方式构建:
需要使用命名空间。
xmlns:android="http://schemas.android.com/apk/res/android"  这个是系统的命名空间值,在R类里。
  1. public class IconTextView extends TextView
  2. {
  3. // 命名空间的值
  4. private final String namespace = "http://cn.eoe.icon.textview";
  5. // 图像资源ID
  6. private int resourceId = 0;
  7. private Bitmap bitmap;
  8. public IconTextView(Context context, AttributeSet attrs)
  9. {
  10. super(context, attrs);
  11. resourceId = attrs.getAttributeResourceValue(namespace, "iconSrc", 0);
  12. if (resourceId > 0)
  13. bitmap = BitmapFactory.decodeResource(getResources(), resourceId);
  14. }
  15. @Override
  16. protected void onDraw(Canvas canvas)
  17. {
  18. if (bitmap != null)
  19. {
  20. // 从原图上截取图像的区域,在本例中为整个图像
  21. Rect src = new Rect();
  22. // 将截取的图像复制到bitmap上的目标区域,在本例中与复制区域相同
  23. Rect target = new Rect();
  24. src.left = 0;
  25. src.top = 0;
  26. src.right = bitmap.getWidth();
  27. src.bottom = bitmap.getHeight();
  28. int textHeight = (int) getTextSize();
  29. target.left = 0;
  30. // 计算图像复制到目录区域的纵坐标。由于TextView中文本内容并不是从最顶端开始绘制的,因此,需要重新计算绘制图像的纵坐标
  31. target.top = (int) ((getMeasuredHeight() - getTextSize()) / 2) + 1;
  32. target.bottom = target.top + textHeight;
  33. // 为了保证图像不变形,需要根据图像高度重新计算图像的宽度
  34. target.right = (int) (textHeight * (bitmap.getWidth() / (float) bitmap
  35. .getHeight()));
  36. // 开始绘制图像
  37. canvas.drawBitmap(bitmap, src, target, getPaint());
  38. // 将TextView中的文本向右移动一定的距离(在本例中移动了图像宽度加2个象素点的位置)
  39. canvas.translate(target.right + 2, 0);
  40. }
  41. super.onDraw(canvas);
  42. }
  43. }
安卓是不区分资源的ID类型的。





原文地址:https://www.cnblogs.com/zhuzhenfeng/p/4641365.html