Android开发笔记(三十六)展示类控件

View/ViewGroup

View是单个视图,所有的控件类都是从它派生出来;而ViewGroup是个视图组织,所有的布局视图类都是从它派生出来。由于View和ViewGroup是基类,因此很少会直接使用,偶尔用到的场景,主要有如下几个: 1、页面上需要单独显示一条横线或者竖线。如果填充图片显然不够经济,最简单的做法,就是在xml布局中增加一个View控件,高度或宽度设置为1dp,背景颜色设置为线条颜色,这样便实现了单独显示线条的需求。 2、点击事件的处理函数onClick(View v),这里面我们要调用View的getId方法获取发生点击事件的控件id,从而进行该控件对应的点击处理。 3、在代码中设置某控件为可见或不可见或消失,此时需要使用View类的三个变量,分别是View.VISIBLE、View.INVISIBLE和View.GONE。

TextView

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

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

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());
					}
				}
			}
		}
	 }
}

点此查看Android开发笔记的完整目录

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券