关于自定义控件和属性时TypedArray.getDimension应当注意的问题
关于自定义控件以及自定义属性的文章,可以查看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 1Retrieve a dimensional for a particular resource ID. Unit conversions are based on the currentDisplayMetrics
associated 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)
单位的转换是基于当前资源显示分比率的。
因此我们要慎重使用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);
更多相关文章
- android jni 学习笔记2
- 三种形式的hello world
- android录音功能的实现
- Android修改源代码控制永不锁屏
- android为ImageView使用蒙层
- Storyboard的爱与恨
- Android简单实现app每月签到功能
- Android(安卓)Studio使用教程(三):常用快捷键
- android在代码中设置margin属性