有以下常用xml属性
android:completionHint用于为弹出的下拉菜单指定标题
android:completionThreshold指定用户输入至少几个字符开始提示
android:dropDownHeigh/Weightt指定下拉菜单高度和宽度
android:popupBackground指定下拉菜单的背景
xml文件如下
java代码如下
package com.thundersoft.chapter2;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.Toast;
import androidx.annotation.Nullable;
import com.thundersoft.session1.R;
public class AutoViewActivity extends Activity {
static final String[] strings = new String[]{"aadfdfdf","aawerwewe","aaxcxx","aawerw","aadfcv","aa123123"};
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.autocompletetextview);
AutoCompleteTextView textView = findViewById(R.id.autoview);
Button get = findViewById(R.id.get);
ArrayAdapter adapter = new ArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line, strings);
textView.setAdapter(adapter);
get.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(AutoViewActivity.this, textView.getText().toString(), Toast.LENGTH_SHORT).show();
}
});
}
}
java代码中,定义了一个static final类的字符串,接着在oncreate中定义数组适配器,将字符串放进适配器并且加载,就可完成提示
2.进度条ProgressBar虚拟机可以增加中文语言,也可以输入中文字符串测试
后台进行前台现实,引出进度条
进度条的xml属性
android:max 一般为100,即进度条的最大值
android:progress 指定进度条的值,通常在java里和线程相关联
android:progressDrawable 设置进度条的轨道形式
进度条的style风格
?android:attr/progressBarStyleHorizontal细长条
?android:attr/progressBarStyleLarge/Small大/小圆形
@android:style/Widget.ProgressBar.Large/Small大/小跳远、旋转画面的进度条
@android:style/Widget.ProgressBar.Horizontal粗长条
xml代码如下
java代码如下
package com.thundersoft.chapter2;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.thundersoft.session1.R;
public class ProgressBarActivity extends Activity {
private int status = 0;
private Handler handler;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.progressbar);
ProgressBar bar1 = findViewById(R.id.bar1);
ProgressBar bar2 = findViewById(R.id.bar2);
handler = new Handler(){
@Override
public void handleMessage(Message msg) {
if (msg.what==0x111){
// 更新进度
bar1.setProgress(status);
bar2.setProgress(status);
}else {
Toast.makeText(ProgressBarActivity.this, "操作完成", Toast.LENGTH_SHORT).show();
// 进度条完成后消失并且不占用空间
bar1.setVisibility(View.GONE);
bar2.setVisibility(View.GONE);
}
}
};
new Thread(new Runnable() {
@Override
public void run() {
while (true){
// 得到完成耗时工作的百分比
status = doWork();
Message message = new Message();
if (status<100){
message.what=0x111;
// 发送信息
handler.sendMessage(message);
}else {
message.what=0x110;
handler.sendMessage(message);
break;
}
}
}
int doWork(){
// 改变完成进度
status += Math.random()*10;
try{
// 休眠200mx
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
return status;
}
// 线程开启
}).start();
}
}
定义一个处理消息的handler对象,在oncreate方法中,利用匿名内部类来实例化处理消息的handler对象,重写了其中的handleMessage方法,实现了耗时操作没有完成的时候就更新进度,否则就进度条不显示
message.what=0x111相当于一个case,what即为case的条件,它是为了判断what的值来进行相应操作,相当于一个判断中间值
线程方面,每一次dowork方法status都会增加0~1乘以10,接着暂停0.2s,当status小于100时就会发送0x111的消息,否则发送0x110的消息,如果是0x111就通过setProgress操作更新progressbar,否则就让进度条消失并且显示toast
不过我们可以使用AsyncTask来更加好的控制进程
下面演示了进度条完成后加载图片的一系列操作
package com.thundersoft.chapter2;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.frameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import androidx.annotation.Nullable;
import com.thundersoft.session1.R;
public class Test1Activity extends Activity {
private int image[] = new int[]{R.drawable.jpg1,R.drawable.jpg2,R.drawable.jpg3,R.drawable.jpg4,R.drawable.jpg5};
private LinearLayout linearLayout;
private ProgressBar progressBar;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_PROGRESS);
setContentView(R.layout.test1);
linearLayout = findViewById(R.id.linearlayout);
progressBar = findViewById(R.id.bartest);
new MyTack().execute();
}
// 三个参数应该分别是,启动任务前输入的参数、后台任务完成的进度值类型,执行完成后返回的结果类型
class MyTack extends AsyncTask{
// 耗时操作前被调用,通常用来初始化一些操作
// @Override
// protected void onPreExecute() {
显示进度条
progressBar.setProgress(0);
// super.onPreExecute();
// }
// 要执行的任务
@Override
protected LinearLayout doInBackground(Void... params) {
LinearLayout layout = new LinearLayout(Test1Activity.this);
for (int i = 1; i < image.length+1; i++) {
ImageView imageView = new ImageView(Test1Activity.this);
imageView.setLayoutParams(new ViewGroup.LayoutParams(200,200));
imageView.setImageResource(image[i-1]);
try {
layout.addView(imageView);
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
publishProgress(i);
}
return layout;
}
// publishProgress
@Override
protected void onProgressUpdate(Integer... values) {
progressBar.setProgress(values[0]*20);
super.onProgressUpdate(values);
}
@Override
protected void onPostExecute(LinearLayout result) {
progressBar.setVisibility(View.GONE);
// setProgressBarVisibility(false);
linearLayout.addView(result);
super.onPostExecute(result);
}
}
}
可以见得,这里通过了建立了一个内部类的匿名对象来调用execute方法执行AsyncTask里的内容
而这个内部类继承了AsyncTask需要传入几个参数,重写几个方法
查看AsyncTask源码,可以看到它的形参是AsyncTask
Params代表着启动任务执行的输入参数的类型,在这里,直接启动不需要任务执行则为void
Progress代表着后台完成的进度条类型,这里是int的包装类
Result是结束后返回的类型,返回给了线性布局
参数解决了,接下来是方法,这里重写了四个方法,分别是onPreExecute,doInBackground,onProgressUpdate和onPostExecute
onPreExecute指的是在线程启动前被调用,里面写一些初始化的方法,因为这里使用的是xml的progressbar,所以可以不用重写这个方法(自带的propressbar看不清,实在是太小了)
doInBackground在AsyncTask中是abstract方法,一定要被实现,它的内容是后台线程将要完成的任务。这里的任务就是循环图片数组,然后放进imageview中,每放一张sleep一段时间,但是这个过程需要被观察到,于是就要通过publishProgress(i);来更新进度条
onProgressUpdate就是每次publishProgress(i)来执行的代码,每次更新就更新进度条进度
onPostExecute是线程完成时自动启用的方法,这里的进度条完成后将进度条给取消显示,接着显示图片内容
最后通过new MyTack().execute();来执行这四个步骤方法完成显示
需要注意的是,异步任务只能被执行一次
不过这个进度条是在标题栏外面的,如果想让标题栏在进度条里面需要用到自定义标题栏
写一个自定义的标题xml,把之前另外一个线性布局的进度条剪贴过来
需要自定义一下主题还有在清单文件里更改主题
android:theme="@style/titlestyle" >
java更改如下代码即可
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
setContentView(R.layout.test1);
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE,R.layout.title);
linearLayout = findViewById(R.id.linearlayout);
progressBar = findViewById(R.id.bartest);
new MyTack().execute();
}
拖动条的xml和java代码如下
package com.thundersoft.chapter2;
import android.app.Activity;
import android.os.Bundle;
import android.widget.SeekBar;
import android.widget.TextView;
import androidx.annotation.Nullable;
import com.thundersoft.session1.R;
public class SeekRatingBarActivity extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.seekratingbar);
SeekBar seekBar=findViewById(R.id.seekbar);
TextView info1=findViewById(R.id.info1);
TextView info2=findViewById(R.id.info2);
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
// 发生滑动执行方法
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
String s = String.valueOf(progress);
info1.setText(s);
}
@Override
// 开始改变时执行方法
public void onStartTrackingTouch(SeekBar seekBar) {
info2.setText("开始滑动");
}
@Override
// 结束改变时执行方法
public void onStopTrackingTouch(SeekBar seekBar) {
info2.setText("停止滑动");
}
});
}
}
Seekbar空间的监听器方法需要重写三个方法
值得注意的是Textview里不能传入int否则会报错,需要转换为Sring类型
星级评分条xml如下
nubStars为星星数量,rating是初始星星,isindicator设置为false表示可以更改
RatingBar ratingBar = findViewById(R.id.ratingbar);
Button submit = findViewById(R.id.submit);
submit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ratingBar.setStepSize(1);
float rating = ratingBar.getRating();
String s1 = String.valueOf((int)rating);
Toast.makeText(SeekRatingBarActivity.this, s1, Toast.LENGTH_SHORT).show();
}
});
注意转换为String
另外ratingBar还有getProgress获取进度方法,getStepSize获取每个最少改变多少个星级
ratingBar.setStepSize(1);可以放在oncreate当中
4.选项卡TabHosttabhost的xml有几点需要注意
TabHost作为总标签,且TabHost和TabWidget与frameLayout的id必须固定,且一定要是@android的这种写法
java代码如下
package com.thundersoft.chapter2;
import android.app.Activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.widget.TabHost;
import androidx.annotation.Nullable;
import com.thundersoft.session1.R;
public class TableHostActivity extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tabhost);
TabHost tabhost = findViewById(android.R.id.tabhost);
// 初始化
tabhost.setup();
LayoutInflater from = LayoutInflater.from(this);
from.inflate(R.layout.tab1,tabhost.getTabContentView());
from.inflate(R.layout.tab2,tabhost.getTabContentView());
tabhost.addTab(tabhost.newTabSpec("tab1")
.setIndicator("第一个页面")
.setContent(R.id.l1));
tabhost.addTab(tabhost.newTabSpec("tab2")
.setIndicator("第二个页面")
.setContent(R.id.l2));
}
}
其中,tab1和tab2是两个页面中的xml文件,l1和l2是这两个xml的布局id
5.图像切换器ImageSwitche图像切换器需要建立图像工厂,xml文件如下
java代码如下
package com.thundersoft.chapter2;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.ImageSwitcher;
import android.widget.ImageView;
import android.widget.ViewSwitcher;
import androidx.annotation.Nullable;
import com.thundersoft.session1.R;
public class ImageSwitcherActivity extends Activity {
int index = 0;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
int[] image = new int[]{R.drawable.jpg1,R.drawable.jpg2,R.drawable.jpg3,R.drawable.jpg4,R.drawable.jpg5};
super.onCreate(savedInstanceState);
setContentView(R.layout.imageswitcher);
ImageSwitcher imageSwitcher = findViewById(R.id.imageswitcher);
imageSwitcher.setInAnimation(AnimationUtils.loadAnimation(ImageSwitcherActivity.this, android.R.anim.fade_in));
imageSwitcher.setOutAnimation(AnimationUtils.loadAnimation(ImageSwitcherActivity.this, android.R.anim.fade_out));
imageSwitcher.setFactory(
new ViewSwitcher.ViewFactory() {
@Override
public View makeView() {
ImageView imageView = new ImageView(ImageSwitcherActivity.this);
imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
imageView.setLayoutParams(new ImageSwitcher.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_ConTENT
));
return imageView;
}
}
);
// 默认显示的图片
imageSwitcher.setImageResource(image[index]);
Button before = findViewById(R.id.before);
Button after = findViewById(R.id.after);
before.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (index > 0 ){
index --;
}else {
index = image.length - 1;
}
imageSwitcher.setImageResource(image[index]);
}
});
after.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (index < image.length - 1 ){
index ++;
}else {
index = 0;
}
imageSwitcher.setImageResource(image[index]);
}
});
}
}
优先定义image的图片数组,以及一个为0的index坐标,找到imageSwitcher的id并且新建对象,设置它的渐入渐出的动画
并且设置它的工厂对象,新建一个ViewFactory的工厂对象重写makeView方法,在方法里实例化一个imageview对象,为这个对象设置位置的大小,并返回
设置默认显示的图片,并且设置点击事件,每一次点击重设显示图像功能
6.网格视图GridView网格视图有以下xml属性
android:columnWidth用于设置每一列的宽度
android:verticalSpacing/horizontalSpacing用于设置各元素之间的垂直/水平间距
android:numColumns设置列数,通常大于一,如果为一建议使用ListView
android:stretchMode设置拉伸模式
none不拉伸
spacingWidth仅拉伸元素之间的间距
columnWidth仅拉伸表格元素本身
spacingWidthUniform表格元素本身和元素之间的间距一起拉伸
演示xml如下
同时还要设置每一个格子的view
java代码如下
package com.thundersoft.chapter2;
import android.app.Activity;
import android.os.Bundle;
import android.widget.GridView;
import android.widget.SimpleAdapter;
import androidx.annotation.Nullable;
import com.thundersoft.session1.R;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class GridViewActivity extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gridview);
GridView gridView = findViewById(R.id.gridview);
int[] image = new int[]{R.drawable.jpg1,R.drawable.jpg2,R.drawable.jpg3,R.drawable.jpg4,R.drawable.jpg5};
String[] title = {"头像1", "头像2", "头像3", "头像4", "头像5"};
ArrayList
使用simpleAdapter适配器配置图片和文字,以上内容见上一篇的列表视图的适配器解释
也可以使用baseAdapter适配器
baseAdapter baseAdapter = new baseAdapter(){
@Override
public int getCount() {
return image.length;
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView==null){
imageView = new ImageView(com.thundersoft.chapter2.GridViewActivity.this);
imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
imageView.setPadding(5,0,5,0);
}else {
imageView=(ImageView) convertView;
}
imageView.setImageResource(image[position]);
return imageView;
}
};
gridView.setAdapter(baseAdapter);
通过new一个baseAdapter对象,重写其中的方法
getView方法中,如果convertView为空的话,就是这imageview,为它设置缩放方式和内边距,并且设置显示图片
getItemId是获得当前选项id的方法
getItem是获得当前选项的方法
getCount是获得当前数量方法
也就是说,baseAdapter自己通过java代码的方式新建了每一个网格布局
7.画廊视图Gallery画廊视图有点类似于一个看图片的软件,可以左右切换,它有一下主要的xml属性
android:animationDuration用于设置列表项切换时的动画时间
android:spacing用于设置列表项之间的间距
android:unselectedAlpha用于设置没有选中的列表项的透明度
示例xml如下
java代码如下
package com.thundersoft.chapter2;
import android.app.Activity;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.baseAdapter;
import android.widget.Gallery;
import android.widget.GridLayout;
import android.widget.ImageView;
import android.widget.Toast;
import androidx.annotation.Nullable;
import com.thundersoft.session1.R;
public class GalleryActivity extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gallery);
int[] image = new int[]{R.drawable.jpg1,R.drawable.jpg2,R.drawable.jpg3,R.drawable.jpg4,R.drawable.jpg5};
Gallery gallery = findViewById(R.id.gallery);
baseAdapter baseAdapter = new baseAdapter(){
@Override
public int getCount() {
return image.length;
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView==null){
imageView = new ImageView(com.thundersoft.chapter2.GalleryActivity.this);
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
imageView.setPadding(5,0,5,0);
// 新加的
imageView.setLayoutParams(new Gallery.LayoutParams(400,350));
TypedArray typedArray = obtainStyledAttributes(R.styleable.Gallery);
imageView.setBackgroundResource(typedArray.getResourceId(
R.styleable.Gallery_android_galleryItemBackground,0
));
}else {
imageView=(ImageView) convertView;
}
imageView.setImageResource(image[position]);
return imageView;
}
};
gallery.setAdapter(baseAdapter);
gallery.setSelection(image.length/2);
gallery.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView> parent, View view, int position, long id) {
Toast.makeText(GalleryActivity.this, String.valueOf(position+1), Toast.LENGTH_SHORT).show();
}
});
}
}
这里使用的baseAdapter和网格视图的相同,不过新增了几个设置,setLayoutParams可以设置imageView的宽高,typeArray可以指定它的样式,需要在values里新建attr.xml
另外,gallery不要忘记了配置适配器和选中的图片,这里选择的中间的图片
画廊视图可以和图像切换器结合做成幻灯片选择播放
还是得通过imageSwitcher.setFactory的方法初始化is,通过gallery.setAdapter(baseAdapter);的方式初始化gallery
最后设置
gallery.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView> parent, View view, int position, long id) {
imageSwitcher.setImageResource(image[position]);
}
});
效果如下



