View是单个视图,所有的控件类都是从它派生出来;而ViewGroup是个视图组织,所有的布局视图类都是从它派生出来。由于View和ViewGroup是基类,因此很少会直接使用,偶尔用到的场景,主要有如下几个: 1、页面上需要单独显示一条横线或者竖线。如果填充图片显然不够经济,最简单的做法,就是在xml布局中增加一个View控件,高度或宽度设置为1dp,背景颜色设置为线条颜色,这样便实现了单独显示线条的需求。 2、点击事件的处理函数onClick(View v),这里面我们要调用View的getId方法获取发生点击事件的控件id,从而进行该控件对应的点击处理。 3、在代码中设置某控件为可见或不可见或消失,此时需要使用View类的三个变量,分别是View.VISIBLE、View.INVISIBLE和View.GONE。
TextView是最基础的文本显示控件了,基本属性如text、textColor、textSize、textDirection、textStyle、textAlignment就不多说了(一般只需设置前三个属性,后面三个属性用得很少),下面只列出几个特殊场景在实际中的运用: 1、聊天室或者文字直播间效果。聊天室窗口的高度是固定的,新的文字消息总是加入到窗口末尾,同时窗口内部的文本整体向上滚动,而窗口的大小保持不变、位置也保持不变。 在XML布局文件中实现时,可设置如下属性: gravity : 指定文本的对齐方式,一般取值“left|bottom”,表示靠左对齐且靠下对齐。 lines : 指定文本的行数。 maxLines : 指定文本的最大行数。 scrollbars : 指定滚动条的方向,一般取值vertical,如不指定将不显示滚动条。注意该属性只能在xml中设置。 在代码中实现时,可调用如下方法: setGravity : 设置文本的对齐方式。 setLines : 设置文本的行数。 setMaxLines : 设置文本的最大行数。 setMovementMethod : 设置文本移动的方式,一般取值“new ScrollingMovementMethod()”,如不设置将无法拉动文本。注意该方法只能在代码中调用。 需要注意的是,scrollbars只能在xml中设置,而无法通过代码设置。反过来,setMovementMethod只能在代码中设置,而无法通过xml设置。所以要实现聊天室效果必须同时修改xml布局文件与代码。 2、在文字周围放置图片。通过在线性布局内部放置ImageView控件也能实现,但显然不如在TextView控件内部加入图片来得方便。 在XML布局文件中实现时,可设置如下属性: drawableTop : 指定文本上方的图形。 drawableBottom : 指定文本下方的图形。 drawableLeft : 指定文本左边的图形。 drawableRight : 指定文本右边的图形。 drawablePadding : 指定图形与文本的间距。 在代码中实现时,可调用如下方法: setCompoundDrawables : 设置文本周围的图形。该方法有四个参数,分别表示左边、上方、右边、下方的图形。 setCompoundDrawablePadding : 设置图形与文本的间距。 3、对该控件(或视图)截图。需要先设置绘图缓存可用,然后取出该控件的绘图缓存完成截图操作。 该操作必须通过代码完成,相关方法如下: setDrawingCacheEnabled : 设置绘图缓存的可用状态。true表示打开,false表示关闭。 isDrawingCacheEnabled : 判断该控件的绘图缓存是否可用。 setDrawingCacheQuality : 设置绘图缓存的质量。 getDrawingCache : 获取该控件的绘图缓存结果,返回值为Bitmap类型 setDrawingCacheBackgroundColor : 设置绘图缓存的背景颜色。可能大家很奇怪为何还要该方法,其实是因为绘图缓存默认背景色是黑色,如果不提前设置缓存的背景色的话,截图的结果就是黑乎乎一片,所以需要将背景色设置为默认颜色(通常是白色)。 其实截图操作适用于大多数控件和视图,因为这几个方法来自于View类,所以凡是继承自View的控件和视图都是可以截图的。
EditText是文本输入框,与输入有关的属性说明如下: 在XML布局文件中指定: inputType : 指定输入的文本类型。常用的取值说明包括:text表示普通文本,textPassword表示文本密码,textEmailAddress表示邮件地址,number表示数字,numberPassword表示数字密码,phone表示电话和手机号码。 maxLength : 指定文本允许输入的最大长度。该属性无法通过代码设置。 hint : 指定提示文本。 textColorHint : 指定提示文本的颜色。 在代码中设置: setInputType : 设置输入的文本类型。如果要隐藏密码注意要设置“InputType.TYPE_CLASS_TEXT|InputType.TYPE_TEXT_VARIATION_PASSWORD”,如果要显示密码则设置“InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD”。 setHint : 设置提示文本。 setHintTextColor : 设置提示文本的颜色。 在录入用户信息时(比如输入姓名、密码等等),EditText输入回车键,常常不要换行而是让光标直接跳到下一个编辑框。这个场景说起来简单,开发过程中就分解为三个功能: 1、监控用户当前输入了回车键。该功能有两种实现方式: 方式一:给编辑框注册一个OnKeyListener监听器(setOnKeyListener方法),当检测到回车键(keyCode == 66)时,触发光标跳转操作; 方式二:给编辑框注册一个TextWatcher监听器(addTextChangedListener方法),当检测到文本发生变化并找到回车换行符时,触发光标跳转操作; 2、保持当前控件不换行,依旧单行显示。该功能有两种实现方式: 方式一:在布局文件的EditText节点中加入singleLine属性,但该方式只在视觉上起作用,真正的字符串还是带有回车换行符; android:singleLine="true" 方式二:去掉编辑框文本中的回车符和换行符,示例代码如下: String str = et_this.getText().replace("\r", "").replace("\n", ""); et_this.setText(str); 3、光标跳到下个编辑框,并自动挪到编辑框文本末尾。该功能有两种实现方式: 方式一:使用EditText的setSelection方法,示例代码如下: et_next.requestFocus(); et_next.setSelection(et_next.getText().length()); 方式二:使用Selection的setSelection方法,示例代码如下: et_next.requestFocus(); Editable edit = et_next.getText(); Selection.setSelection(edit, edit.length()); 注意控件之间切换光标要使用requestFocus方法,不能使用setFocusable方法(该方法只能切换焦点,不能切换光标)。 EditText还有一个需要特殊处理的地方,就是自动关闭软键盘。一般我们希望点击其它控件时,原输入框的软键盘就要自动消失,可惜Android不是这样处理。于是我们得通过输入法工具类InputMethodManager来协助,该类的对象从系统服务Context.INPUT_METHOD_SERVICE中获取。下面是自动关闭软键盘的两种方法: 1、调用toggleSoftInput方法,该方法会关闭所有控件弹出的软键盘;
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
//软键盘如果已经打开则关闭之
if (imm.isActive() == true) {
imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
}
2、调用hideSoftInputFromWindow方法,该方法只关闭指定EditText控件弹出的软键盘;
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(et_server.getWindowToken(), 0);
ImageView是图形显示控件,与图形显示有关的属性说明如下: 在XML布局文件中指定: scaleType : 指定图形的拉伸类型。常用的取值说明包括:fitXY表示拉伸图片正好填满视图(图片可能被拉伸变形),fitStart表示拉伸图片使之位于视图上部,fitCenter表示拉伸图片使之位于视图中间,fitEnd表示拉伸图片使之位于视图下部,center表示保持图片原尺寸使之位于视图中间,centerCrop表示拉伸图片并使视图位于图片中间,centerInside表示使图片位于视图中间(只压不拉)。以上方式只有fitXY不按比例拉伸,其他都要按比例拉伸。另外注意centerInside,当图片尺寸大于视图时,centerInside等同于fitCenter;当图片尺寸小于视图时,centerInside等同于center。 src : 指定图形来源,src图形按照scaleType拉伸。 background : 指定图形背景。注意背景图不按比例拉伸,其实背景默认以fitXY方式拉伸。 在代码中设置: setScaleType : 设置图形的拉伸类型。 setImageAlpha : 设置图形的透明度。 setImageBitmap : 设置图形的Bitmap对象。 setImageDrawable : 设置图形的Drawable对象。 setImageResource : 设置图形的资源ID。
文字直播室的代码例子如下:
import com.example.exmsimplewidget.R;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.app.Activity;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class LiveTextActivity extends Activity implements OnClickListener {
private TextView tv_live;
private EditText et_news;
private Button btn_publish;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_live_text);
tv_live = (TextView) findViewById(R.id.tv_live);
et_news = (EditText) findViewById(R.id.et_news);
btn_publish = (Button) findViewById(R.id.btn_publish);
btn_publish.setOnClickListener(this);
tv_live.setGravity(Gravity.LEFT|Gravity.BOTTOM);
tv_live.setLines(20);
tv_live.setMaxLines(20);
tv_live.setMovementMethod(new ScrollingMovementMethod());
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.btn_publish) {
String desc = String.format("%s\n直播员 %s:%s",
tv_live.getText(), getNowDateTime(), et_news.getText());
tv_live.setText(desc);
}
}
private String getNowDateTime() {
SimpleDateFormat s_format = new SimpleDateFormat("HH:mm:ss");
Date d_date = new Date();
String s_date = "";
s_date = s_format.format(d_date);
return s_date;
}
}
编辑框回车跳转的代码例子如下:
import com.example.exmsimplewidget.R;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.text.Editable;
import android.text.InputType;
import android.text.Selection;
import android.text.TextWatcher;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnKeyListener;
import android.widget.Button;
import android.widget.EditText;
public class EnterInfoActivity extends Activity {
private final static String TAG = "EnterInfoActivity";
private EditText et_user, et_password, et_job;
private Button btn_cancel, btn_ok;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_enter_info);
et_user = (EditText) findViewById(R.id.et_user);
et_password = (EditText) findViewById(R.id.et_password);
et_job = (EditText) findViewById(R.id.et_job);
btn_cancel = (Button) findViewById(R.id.btn_cancel);
btn_ok = (Button) findViewById(R.id.btn_ok);
et_user.setInputType(InputType.TYPE_CLASS_TEXT);
et_password.setInputType(InputType.TYPE_CLASS_TEXT|InputType.TYPE_TEXT_VARIATION_PASSWORD);
et_job.setInputType(InputType.TYPE_CLASS_TEXT);
et_user.setOnKeyListener(new MyKeyListener(et_password, mUserRefresh));
et_password.addTextChangedListener(new MyTextWatcher(et_password, et_job));
et_job.addTextChangedListener(new MyTextWatcher(et_job, btn_ok));
}
private final Handler mHandler = new Handler();
private Runnable mUserRefresh = new Runnable() {
@Override
public void run() {
et_user.setText(et_user.getText().toString().replace("\r", "").replace("\n", ""));
}
};
class MyKeyListener implements OnKeyListener {
private View mNextView = null;
private Runnable mRun = null;
public MyKeyListener(View vNext, Runnable run) {
super();
if (vNext != null) {
mNextView = vNext;
}
mRun = run;
}
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if(keyCode == 66 && mNextView != null) {
mHandler.postDelayed(mRun, 50);
mNextView.requestFocus();
if (mNextView instanceof EditText) {
EditText et = (EditText)mNextView;
et.setSelection(et.getText().length());
}
}
return false;
}
}
class MyTextWatcher implements TextWatcher {
private EditText mThisView = null;
private View mNextView = null;
public MyTextWatcher(EditText vThis, View vNext) {
super();
mThisView = vThis;
if (vNext != null) {
mNextView = vNext;
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
Log.d(TAG, "et_user.getText()="+et_user.getText());
String str = s.toString();
if (str.indexOf("\r") >= 0 || str.indexOf("\n") >= 0) {
Log.d(TAG, "afterTextChanged mThisView.getId()="+mThisView.getId()
+", mNextView.getId()="+mNextView.getId());
mThisView.setText(str.replace("\r", "").replace("\n", ""));
if (mNextView != null) {
mNextView.requestFocus();
if (mNextView instanceof EditText) {
EditText et = (EditText)mNextView;
Editable edit = et.getText();
Selection.setSelection(edit, edit.length());
}
}
}
}
}
}