关于自定义控件以及自定义属性的文章,可以查看Android高手进阶教程(四)之----Android 中自定义属性(attr.xml,TypedArray)的使用!。本文主要在其基础之上结合实际开发当中遇到的问题,举例分析一下在使用TypedArray.getDimension时应当注意的问题。

一、主要代码以及不同手机显示图片

主要显示代码main.xml关键代码

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:test="http://schemas.android.com/apk/res/com.yang"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:orientation="vertical"     android:background="@color/background">    <TextView android:layout_height="wrap_content"        android:layout_width="wrap_content"         android:textColor="@android:color/black"        android:textSize="18sp"        android:text="@string/shiyan"/>    <com.yang.widget.TextViewAndSpaner        android:layout_width="fill_parent"        android:layout_height="wrap_content"        test:item_content_text="@string/shiyan"        test:item_content_textsize="18sp"        test:item_content_textcolor="@android:color/black"        test:item_option_prompt="@string/please_select"        test:item_option_values="@array/tureorfalse" /></LinearLayout>
text_spaner_view.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:orientation="vertical" >    <LinearLayout        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:orientation="horizontal" >        <LinearLayout            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_weight="1.33"            android:orientation="vertical" >            <TextView                android:id="@+id/item_content"                android:layout_width="240dip"                android:layout_height="wrap_content"                android:singleLine="false"                android:textSize="15sp" />                        <TextView                android:id="@+id/item_remark_str"                android:layout_width="240dip"                android:layout_height="wrap_content"                android:singleLine="false"                android:textSize="10sp"                 android:visibility="gone"/>        </LinearLayout>        <LinearLayout            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_gravity="center"            android:orientation="vertical" >            <Button                android:id="@+id/item_option"                android:layout_width="80dip"                android:layout_height="45dip"                android:text="@string/please_select"                 android:textSize="13sp"                />            <TextView                android:id="@+id/item_option_ps"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:singleLine="false"                android:textSize="10sp"                android:layout_gravity="center"                android:visibility="gone" />            <Button                android:id="@+id/item_remark"                android:layout_width="80dip"                android:layout_height="30dip"                android:text="备注"                android:textSize="10sp"                android:visibility="gone"               />                    </LinearLayout>    </LinearLayout>    <View        android:layout_width="fill_parent"        android:layout_height="1dp"        android:background="@android:color/white" /></LinearLayout>
TextViewAndSpaner.java

package com.yang.widget;import com.yang.R;import com.yang.utils.Logger;import android.app.AlertDialog;import android.app.AlertDialog.Builder;import android.content.Context;import android.content.DialogInterface;import android.content.res.TypedArray;import android.text.TextUtils;import android.util.AttributeSet;import android.util.TypedValue;import android.view.LayoutInflater;import android.view.View;import android.widget.ArrayAdapter;import android.widget.Button;import android.widget.EditText;import android.widget.LinearLayout;import android.widget.TextView;public class TextViewAndSpaner extends LinearLayout {private TextView item_content;private Button item_remark;// 1、使用startActivityforResult或者// 2、设置Intent的Type属性// 但是使用后者时需要将原先的Activity传过来,在TextViewAndSpaner中添加代码。// 同时,要开启Activity当中设置判断条件。开发复杂。因此使用前者。private TextView item_remark_str;private Button item_option;public Button getItem_option() {return item_option;}public void setItem_option(Button item_option) {this.item_option = item_option;}private TextView item_option_ps;private Context mContext;private boolean isopposites;/** * 默认构造函数 */public TextViewAndSpaner(Context context, AttributeSet attrs) {super(context, attrs);// TODO Auto-generated constructor stubmContext = context;LayoutInflater.from(context).inflate(R.layout.text_spaner_view, this,true);item_content = (TextView) findViewById(R.id.item_content);item_remark = (Button) findViewById(R.id.item_remark);item_option = (Button) findViewById(R.id.item_option);item_remark_str = (TextView) findViewById(R.id.item_remark_str);item_option_ps = (TextView) findViewById(R.id.item_option_ps);TypedArray typeArray = context.obtainStyledAttributes(attrs,R.styleable.TextViewAndSpaner);setItemContext(typeArray);setItemRemark(typeArray);// 设置相关的点击选项setOption(typeArray);setRemark(typeArray);// 回收typeArray.recycle();}private void setRemark(TypedArray typeArray) {// TODO Auto-generated method stubboolean remarkFlag = typeArray.getBoolean(R.styleable.TextViewAndSpaner_is_remark_enable, false);if (remarkFlag) {item_remark.setVisibility(View.VISIBLE);item_remark.setOnClickListener(new OnClickListener() {public void onClick(View v) {// TODO Auto-generated method stubremarkDialog();}});}}private void setItemContext(TypedArray typeArray) {int contentColor = typeArray.getColor(R.styleable.TextViewAndSpaner_item_content_textcolor,0XFFFFFFFF);item_content.setTextColor(contentColor);Logger.d("getDimensionPixelOffset"+ typeArray.getDimensionPixelOffset(R.styleable.TextViewAndSpaner_item_content_textsize,15));Logger.d("getDimensionPixelSize"+ typeArray.getDimensionPixelSize(R.styleable.TextViewAndSpaner_item_content_textsize,15));Logger.d("getLayoutDimension"+ typeArray.getLayoutDimension(R.styleable.TextViewAndSpaner_item_content_textsize,15));float contentSize = typeArray.getDimension(R.styleable.TextViewAndSpaner_item_content_textsize, 15);Logger.d("contentSize is " + contentSize);item_content.setTextSize(TypedValue.COMPLEX_UNIT_SP, contentSize);String contentStr = typeArray.getString(R.styleable.TextViewAndSpaner_item_content_text);item_content.setText(contentStr);}private void setItemRemark(TypedArray typeArray) {boolean remarkFlag = typeArray.getBoolean(R.styleable.TextViewAndSpaner_is_remark_enable, false);if (remarkFlag) {int remarkColor = typeArray.getColor(R.styleable.TextViewAndSpaner_item_remark_textcolor,0XFFFFFFFF);item_remark_str.setTextColor(remarkColor);float remarkSize = typeArray.getDimension(R.styleable.TextViewAndSpaner_item_remark_textsize, 12);item_remark_str.setTextSize(remarkSize);}}private void setOption(TypedArray typeArray) {isopposites = typeArray.getBoolean(R.styleable.TextViewAndSpaner_is_item_option_opposites, false);boolean isResult = typeArray.getBoolean(R.styleable.TextViewAndSpaner_is_query_result, false);if (isResult)item_option.setEnabled(false);else {final CharSequence[] values = typeArray.getTextArray(R.styleable.TextViewAndSpaner_item_option_values);final String when_to_show_dialogue_item = typeArray.getString(R.styleable.TextViewAndSpaner_when_to_show_dialogue_item);final String prompt = typeArray.getString(R.styleable.TextViewAndSpaner_item_option_prompt);final ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>(mContext, android.R.layout.simple_spinner_dropdown_item,values);final CharSequence[] attrs = typeArray.getTextArray(R.styleable.TextViewAndSpaner_item_option_selected_dialogue_item);final String promptStr = typeArray.getString(R.styleable.TextViewAndSpaner_prompt_of_dialog);item_option.setOnClickListener(new OnClickListener() {public void onClick(View v) {// TODO Auto-generated method stubnew AlertDialog.Builder(mContext).setTitle(prompt).setAdapter(adapter,new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog,int which) {String selectedValue = values[which].toString();item_option.setText(values[which]);if (selectedValue.equals(when_to_show_dialogue_item)) {showDiag(attrs, promptStr);} else {item_option_ps.setText(null);item_option_ps.setVisibility(View.GONE);}dialog.dismiss();}}).create().show();}});}}private void showDiag(final CharSequence[] attrs, String promptStr) {AlertDialog.Builder builder = new Builder(mContext);builder.setTitle("请选择……");builder.setPositiveButton(attrs[0],new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog, int which) {// TODO Auto-generated method stubitem_option_ps.setVisibility(View.VISIBLE);item_option_ps.setText(attrs[0]);}});builder.setNegativeButton(attrs[1],new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog, int which) {// TODO Auto-generated method stubitem_option_ps.setVisibility(View.VISIBLE);item_option_ps.setText(attrs[1]);}});builder.setIcon(android.R.drawable.ic_dialog_info);builder.setMessage(promptStr);builder.show();}private void remarkDialog() {final EditText remark_text = new EditText(mContext);String oldRemark_text = (String) item_remark_str.getText();if (!TextUtils.isEmpty(oldRemark_text)) {remark_text.setText(oldRemark_text);}new AlertDialog.Builder(mContext).setTitle("添加备注").setIcon(android.R.drawable.ic_dialog_info).setView(remark_text).setPositiveButton("确定", new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog, int which) {// TODO Auto-generated method stubitem_remark_str.setVisibility(View.VISIBLE);item_remark_str.setText(remark_text.getText().toString().trim());}}).setNegativeButton("取消", null).show();}public String getKeyValue() {String optionResult = (String) item_option.getText();if (isopposites) {// 如果是反义,则在值后面加空格return optionResult + " ";}return optionResult;}public void setOptionDefaultValue() {item_option.setText("");}public String getRemarkValue() {String psStr = (String) item_option_ps.getText();String remarkStr = (String) item_remark_str.getText();if (psStr != null && remarkStr != null&& !TextUtils.isEmpty(psStr.trim())&& !TextUtils.isEmpty(remarkStr.trim())) {return item_content.getText() + "的备注:" + psStr + "," + remarkStr;}if (psStr != null && !TextUtils.isEmpty(psStr.trim())) {return item_content.getText() + "的备注:" + psStr;}if (remarkStr != null && !TextUtils.isEmpty(remarkStr.trim())) {return item_content.getText() + "的备注:" + remarkStr;}return null;}}
MainActivity.java

package com.yang;import android.app.Activity;import android.os.Bundle;public class MainActivity extends Activity {/** Called when the activity is first created. */@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);}}

例子图示如下:

摩托罗拉xt910

中兴 v880


中兴 n760


华为c8500

二、现象说明

我们看到根据屏幕大小的不同,两行文字中下行文字的大小也随之改变,其中摩托罗拉xt910和中兴 v880下面字体的都比上面字体大,而中兴 n760下面字体与上面字体大小是相同的,而华为c8500下面字体比上面字体小。我们再来看看main.xml代码:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:test="http://schemas.android.com/apk/res/com.yang"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:orientation="vertical"     android:background="@color/background">    <TextView android:layout_height="wrap_content"        android:layout_width="wrap_content"         android:textColor="@android:color/black"        android:textSize="18sp"        android:text="@string/shiyan"/>    <com.yang.widget.TextViewAndSpaner        android:layout_width="fill_parent"        android:layout_height="wrap_content"        test:item_content_text="@string/shiyan"        test:item_content_textsize="18sp"        test:item_content_textcolor="@android:color/black"        test:item_option_prompt="@string/please_select"        test:item_option_values="@array/tureorfalse" /></LinearLayout>
TextView设置的字体大小为18sp,而com.yang.widget.TextViewAndSpaner设置的字体大小也为18sp

com.yang.widget.TextViewAndSpaner读取字体大小的代码如下:

float contentSize = typeArray.getDimension(R.styleable.TextViewAndSpaner_item_content_textsize, 15);Logger.d("contentSize is " + contentSize);

四个手机打印出自定义属性来的字体大小为:

摩托罗拉xt91009-08 15:07:00.685: D/CustomWidget(4937): contentSize is 27.0中兴 v88009-08 15:15:04.685: D/CustomWidget(4937): contentSize is 27.0中兴 n76009-08 15:05:15.640: D/CustomWidget(31487): contentSize is 18.0华为c850009-08 15:22:48.565: D/CustomWidget(2018): contentSize is 13.5

三、注意事项

以上我们看到使用自定义属性的

typeArray.getDimension

是不靠谱的,字体的大小会根据不同屏幕的分辨率大小而改变字体的大小。我们再来看看关于getDimension

public floatgetDimension(int id)

Since: API Level 1

Retrieve a dimensional for a particular resource ID. Unit conversions are based on the currentDisplayMetricsassociated with the resources.

Parameters
id The desired resource identifier, as generated by the aapt tool. This integer encodes the package, type, and resource entry. The value 0 is an invalid identifier.
Returns
  • Resource dimension value multiplied by the appropriate metric.
Throws
Resources.NotFoundException Throws NotFoundException if the given ID does not exist.
See Also
  • getDimensionPixelOffset(int)
  • getDimensionPixelSize(int)
Unit conversions are based on the current DisplayMetrics associated with the resources.

单位的转换是基于当前资源显示分比率的。

因此我们要慎重使用getDimension定义的属性,不然我们的应用部署到不同的应用上,原先非常美丽的效果,会变得面目全非。

四、解决方案

使用时,默认将字体大小设定好,而在xml配置文件当中删除关于字体大小的设置。如

删除main.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:test="http://schemas.android.com/apk/res/com.yang"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:orientation="vertical"     android:background="@color/background">    <TextView android:layout_height="wrap_content"        android:layout_width="wrap_content"         android:textColor="@android:color/black"        android:textSize="18sp"        android:text="@string/shiyan"/>    <com.yang.widget.TextViewAndSpaner        android:layout_width="fill_parent"        android:layout_height="wrap_content"        test:item_content_text="@string/shiyan"        test:item_content_textsize="18sp"        test:item_content_textcolor="@android:color/black"        test:item_option_prompt="@string/please_select"        test:item_option_values="@array/tureorfalse" /></LinearLayout>
中的

 test:item_content_textsize="18sp"
配置,使其变成:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:test="http://schemas.android.com/apk/res/com.yang"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:orientation="vertical"     android:background="@color/background">    <TextView android:layout_height="wrap_content"        android:layout_width="wrap_content"         android:textColor="@android:color/black"        android:textSize="18sp"        android:text="@string/shiyan"/>    <com.yang.widget.TextViewAndSpaner        android:layout_width="fill_parent"        android:layout_height="wrap_content"        test:item_content_text="@string/shiyan"              test:item_content_textcolor="@android:color/black"        test:item_option_prompt="@string/please_select"        test:item_option_values="@array/tureorfalse" /></LinearLayout>

同时在读取自定义属性的java代码中设置好自己想要的字体大小即可,如下:

float contentSize = typeArray.getDimension(R.styleable.TextViewAndSpaner_item_content_textsize, 15);

更多相关文章

  1. android jni 学习笔记2
  2. 三种形式的hello world
  3. android录音功能的实现
  4. Android修改源代码控制永不锁屏
  5. android为ImageView使用蒙层
  6. Storyboard的爱与恨
  7. Android简单实现app每月签到功能
  8. Android(安卓)Studio使用教程(三):常用快捷键
  9. android在代码中设置margin属性

随机推荐

  1. 移动架构39_RxAndroid二(变换调用:map、fla
  2. android wifi scan and auto re-connect
  3. Android(安卓)数据存储(二) 共享参数存储
  4. 这是我见过有关Android(安卓)RecyclerVie
  5. 我的Android进阶之旅------>android Toas
  6. android UVC h264 ffmpeg软解码
  7. Smali动态调试方法
  8. Android特点
  9. Android(安卓)之 史上最细 Material Desi
  10. 史上最全的Android开发索引帖