第二章 UI控件
一、视图组件View
View类:是Android所有UI组件的父类,它代表了屏幕上一块空白的矩形区域。
ViewGroup类:作为其它UI组件的容器使用,ViewGroup是View的子类。
应用界面的组成
Android 的所有UI组件都是建立在View、ViewGroup的基础之上。对于一个Android应用的图形用户界面来说,ViewGroup作为容器来盛装其他组件,ViewGroup里除了可以包含普通View组件之外,还可以再次包含ViewGroup组件。
视觉上的层次关系
逻辑层次关系
控制UI控件行为的方式
- 在xml布局文件中通过xml属性进行控制
- 在Java程序代码中通过调用set等方法控制
实际上不管使用哪种方式,它们控制用户界面行为的本质是完全一样的,大部分时候,控制UI组件的XML属性还有对应的方法。
View类是所有UI组件的基类,因经它包含的XML属性和方法是所有组件都可使用的
二、文本控件TextView
TextView : 直接继承自View,它的作用就是在界面上显示文本。
为什么SDK把它设计为EditText、Button两个UI控件的父类?
答:EditText、Button都可以界面上显示文本,不同的是EditText里的文本是可以给用户编辑的,而Button只是多了一个点击事件而已
match_parent 充满
wrap_content 正好
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="#00f">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="校园报修系统登录"
android:textColor="#ffffff"
android:textSize="30dp" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:background="@null"
android:text="注册"
android:textColor="#ffffff"
android:textSize="30dp" />
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="账号:"
android:textSize="25dp"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入你的账号"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="密码:"
android:textSize="25dp"
/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPassword"
android:hint="请输入密码"/>
</LinearLayout>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="登录"
android:textSize="25dp"
android:layout_marginTop="20dp"
android:layout_marginRight="20dp"
android:layout_marginLeft="20dp"/>
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="43dp"
android:text="齐鲁工业大学软件设计大赛"
android:layout_gravity="right"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="by:Hello World!"
android:layout_marginRight="43dp"
android:layout_gravity="right"/>
</LinearLayout>
三、图片控件ImageView
ImageView : 直接继承自View,它的作用就是在界面上显示图片。
实际上这个说法不太严谨,因为它能显示的不仅仅是图片,任何Drawable对象都可以使用ImageView来显示。
语句举例
<ImageView
android:layout_width="60dp"
android:layout_height="60dp"
android:background="#f00"
android:scaleType="centerCrop"
android:src="@android:drawable/abc"/>
四、多选框控件CheckBox单选框控件RadioButton
CheckBox : 直接继承自Button,它的作用就是在界面提供一组选项,可以多选。
比如:我的喜欢的颜色: 红色 蓝色 绿色 紫色
RadioButton : 直接继承自Button,它的作用就是在界面提供一组选项,只能单选。
比如:性别: 男 女
实验记录
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".Order">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="选择你喜欢的颜色:"/>
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="蓝色"/>
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="绿色"/>
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="黄色"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RadioGroup
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="男"/>
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="女"/>
</RadioGroup>
</LinearLayout>
</LinearLayout>
五、拖动条控件SeekBar进度条控件ProgressBar日期、时间选择控件DatePicter、TimePicker
SeekBar:允许用户拖动滑块来改变值,因此拖动条通常用于对系统的某种数值进行调节,比如音量
Android:thumb指定一个Drawable对象,该对象将作为自定义滑块.
进度条控件ProgressBar
ProgressBar :通常用于向用户显示某个耗时操作完成的百分比。
日期、时间选择控件DatePicter、TimePicker
DatePicker:供用户选择日期,从FrameLayout派生而来
TimePicker:供用户选择时间,也是从FrameLayout派生而来
可通过为DatePicker添加OnDateChangedListener进行监听,为TimePicker添加OnTimerChangedListener进行监听来实现。
Order.java
package me.cyning.uilesson2;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.DatePicker;
import android.widget.ProgressBar;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.TimePicker;
public class Order extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_order);
SeekBar seekBar=findViewById(R.id.myseekbar);
final TextView textView=findViewById(R.id.tv_seekbar);
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
textView.setText(String.valueOf(progress-200));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
final ProgressBar progressBar=findViewById(R.id.progress);
findViewById(R.id.add).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
progressBar.setProgress(progressBar.getProgress()+1);
}
});
findViewById(R.id.dec).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
progressBar.setProgress(progressBar.getProgress()-1);
}
});
DatePicker datePicker=findViewById(R.id.mydate);
datePicker.getYear();
datePicker.getMonth();
datePicker.getDayOfMonth();
TimePicker timePicker=findViewById(R.id.myTime);
timePicker.getCurrentHour();
timePicker.getCurrentMinute();
//timePicker.getHour();//android6.0以上
}
}
activity_order.xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".Order">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".Order">
<SeekBar
android:id="@+id/myseekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="800"
android:thumb="@mipmap/ic_launcher"/>
<TextView
android:id="@+id/tv_seekbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="0"/>
<ProgressBar
android:id="@+id/progress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100"
android:progress="50"
style="?android:attr/progressBarStyleHorizontal"/>
<Button
android:id="@+id/add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="增加"/>
<Button
android:id="@+id/dec"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="减少"/>
<DatePicker
android:id="@+id/mydate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TimePicker
android:id="@+id/myTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
</ScrollView>
六、列表选择控件Spinner
作用
弹出一个列表选择框,供用户选择。
继承自ViewGroup,因为它可以容纳很多列表项,
因此它也是一个容器控件
第一种创建方式
使用数组资源设置下拉列表的列表项目
actvity_ui5.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".UI5">
<Spinner
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:entries="@array/grade">
</Spinner>
</RelativeLayout>
在res/value下新建arrays.xml文件
arrays.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="grade">
<item>小学二年级</item>
<item>小学一年级</item>
<item>小学三年级</item>
<item>小学四年级</item>
<item>小学五年级</item>
</string-array>
</resources>
第二种创建方式
使用ArrayAdapter适配器创建
public ArrayAdapter(Context context, @LayoutRes int resource, @IdRes int textViewResourceId, @NonNull T[] objects)
context:当前所在Activity
resource:每一项的布局结构
textViewResourceId:包含textview
cobjects:每一项显示内容
activity_ui5.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".UI5">
<Spinner
android:id="@+id/my_spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
</Spinner>
</RelativeLayout>
UI5.java
package me.cyning.uilesson2;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
public class UI5 extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ui5);
Spinner spinner=findViewById(R.id.my_spinner);
ArrayAdapter<String> adapter=new ArrayAdapter<String>(this,android.R.layout.simple_spinner_dropdown_item,android.R.id.text1,new String[]{"小学一年级","小学二年级","小学三年级"});
spinner.setAdapter(adapter);
}
}
七、列表控件ListView
ListView :列表控件,以垂直的形式显示所有的列表项。
android:divider="#f00" 设置分割行的颜色
android:dividerHeight="10dp" 设置分隔符的宽度
android:scrollbars="none" 是否显示滚动条
android:overScrollMode="never" 是否显示系统默认滚到头的UI效果
第一种创建方法
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:entries="@array/grade"/>
</RelativeLayout>
array.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="grade">
<item>大学一年级</item>
<item>大学二年级</item>
<item>大学三年级</item>
<item>中学一年级</item>
</string-array>
</resources>
第二种创建方法-ArrayAdapter数组适配器
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ListView
android:id="@+id/demo_list_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
MainActivity.java
package me.cyning.ui6;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class MainActivity extends AppCompatActivity {
String[] strings={
"小学一年级","小学一年级","小学一年级","小学一年级","小学一年级","小学一年级","小学一年级","小学一年级","小学一年级","小学一年级","小学一年级","小学一年级","小学一年级","小学一年级","小学一年级",
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listView=findViewById(R.id.demo_list_view);
ArrayAdapter<String> adapter=new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1,android.R.id.text1,strings);
listView.setAdapter(adapter);
}
}
第三种方法-SimpleAdapter简单适配器
构造方法:SimpleAdapter(Context context, List<? extends Map
context:上下文
data:数据源,是一个map对象列表
resource:每一项的布局资源id
from:在map对象中存储的key
to: 每一项布局资源中的需要显示文本的TextView的id数组
优点使用简单、方便
缺点只适合用于列表每一项中只需要动态加载文本的ListView
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ListView
android:id="@+id/demo_list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</RelativeLayout>
item_user.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">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher"/>
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_sex"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_age"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
MainActivity.java
package me.cyning.ui6;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listView=findViewById(R.id.demo_list_view);
List<Map<String,?>> datalist=new ArrayList<>();
for(int i=0;i<50;i++){
Map<String,String> map=new HashMap<>();
map.put("name","张三"+i);
map.put("sex",i%2==0?"男":"女");
map.put("age",10+i+"");
datalist.add(map);
}
String[] from={"name","age","sex"};
int[] to={R.id.tv_name,R.id.tv_age,R.id.tv_sex};
SimpleAdapter adapter=new SimpleAdapter(this,datalist,R.layout.item_user,from,to);
listView.setAdapter(adapter);
}
}
第四种方法-BaseAdapter适配器
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ListView
android:id="@+id/demo_list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</RelativeLayout>
item_user.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">
<ImageView
android:id="@+id/image_sex"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_sex"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_age"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
MainActivity.java
package me.cyning.ui6;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MainActivity extends AppCompatActivity {
List<UserInfo> datalis;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化数据
datalis=new ArrayList<>();
for(int i=0;i<50;i++){
UserInfo userInfo=new UserInfo();
userInfo.age=10+i;
userInfo.sex=i%2==0?"男":"女";
userInfo.name="张三"+i;
datalis.add(userInfo);
}
//为ListView设置适配器
ListView listView=findViewById(R.id.demo_list_view);
UserInfoListAdapter userInfoListAdapter=new UserInfoListAdapter();
listView.setAdapter(userInfoListAdapter);
}
//写一个继承BaseAdapter的类
class UserInfoListAdapter extends BaseAdapter{
@Override
public int getCount() {
return datalis.size();
}
@Override
public Object getItem(int position) {
return datalis.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View itemRootView= LayoutInflater.from(parent.getContext()).inflate(R.layout.item_user,null);
TextView tvName=itemRootView.findViewById(R.id.tv_name);
tvName.setText(datalis.get(position).name);
TextView tvAge=itemRootView.findViewById(R.id.tv_age);
tvAge.setText(datalis.get(position).age+"");//默认数字代表资源ID
TextView tvSex=itemRootView.findViewById(R.id.tv_sex);
tvSex.setText(datalis.get(position).sex);
ImageView imageView=itemRootView.findViewById(R.id.image_sex);
if(datalis.get(position).sex.equals("男"))
imageView.setBackgroundResource(R.drawable.male);
if(datalis.get(position).sex.equals("女"))
imageView.setBackgroundResource(R.drawable.femal);
return itemRootView;
}
}
//自定义内部类
class UserInfo{
String name;
int age;
String sex;
}
}
[
八、网络控件GridView
**GridView :**用于在界面上按行、列分布的方式来显示多个组件。
用SimpleAdapter创建
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<GridView
android:id="@+id/grid_view_menu"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:numColumns="3"/>
</RelativeLayout>
grid.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="wrap_content"
android:orientation="vertical"
android:gravity="center"><!-- 能让图标居中显示 -->
<ImageView
android:id="@+id/image_view"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@mipmap/ic_launcher" />
<TextView
android:id="@+id/tv_menu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="菜单" />
</LinearLayout>
MainActivity.java
package me.cyning.ui9;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.GridView;
import android.widget.SimpleAdapter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//数据初始化
List<Map<String,String>> dataList=new ArrayList<>();
for(int i=0;i<12;i++){
Map<String,String> map=new HashMap<>();
map.put("menu_name","菜单"+i);
dataList.add(map);
}
String[] from= {"menu_name"};
int[] to={R.id.tv_menu};
GridView gridView=findViewById(R.id.grid_view_menu);
SimpleAdapter simpleAdapter=new SimpleAdapter(this,dataList,R.layout.grid,from,to);
gridView.setAdapter(simpleAdapter);
}
}
用BaseAdapter创建
activity_main.xml和grid.xml与上一题相同
package me.cyning.ui9;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MainActivity extends AppCompatActivity {
List<MenuItem> datalist;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
GridView gridView=findViewById(R.id.grid_view_menu);
datalist=new ArrayList<>();
datalist.add(new MenuItem("菜单1",R.drawable.ec));
datalist.add(new MenuItem("菜单2",R.drawable.mind));
datalist.add(new MenuItem("菜单4",R.drawable.qq));
datalist.add(new MenuItem("菜单5",R.drawable.sl));
MenuAdapter menuAdapter=new MenuAdapter();
gridView.setAdapter(menuAdapter);
}
class MenuAdapter extends BaseAdapter{
@Override
public int getCount() {
return datalist.size();
}
@Override
public Object getItem(int position) {
return datalist.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View menu= LayoutInflater.from(parent.getContext()).inflate(R.layout.grid,null);
TextView textView=menu.findViewById(R.id.tv_menu);
textView.setText(datalist.get(position).menuName);
ImageView imageView=menu.findViewById(R.id.image_view);
imageView.setImageResource(datalist.get(position).menuDrawable);
return menu;//不要忘记将你配置的View返回
}
}
class MenuItem{
String menuName;
int menuDrawable;
MenuItem(String menuName,int menuDrawable){
this.menuDrawable=menuDrawable;
this.menuName=menuName;
}
}
}
九、ExpandableListView(可展开的ListView )
ExpandableListVivew是ListView的子类,它在普通ListView的基础上进行了扩展,它把应用中的列表项分为几组,每组里又可包含多个列表项。ExpandableListVivew的用法与普通ListView的用法非常相似,只是ExpandableListVivew显示的列表项应该由ExpandableAdapter提供
实现ExpandableAdapter的两种方式
- 使用SimpleExpandableListAdpater将两个List集合包装成ExpandableAdapter
- 扩展BaseExpandableListAdpter实现ExpandableAdapter
1.使用SimpleExpandableListAdapter实现
public SimpleExpandableListAdapter(Context context,List<? extends Map<String, ?>> groupData, int groupLayout,String[]groupFrom, int[] groupTo,List<? extends List<? extends Map<String, ?>>> childData, int childLayout,String[]childFrom, int[] childTo)
- context 与SimpleExpandableListAdapter关联的ExpandableListView的上下文。
- groupData 一个Maps列表(List)。集合中的每个字典项与可折叠列表中的每个组元素一致。字典项提供了组元素包含的所有数据,并包含所有在"groupFrom"中指定的记录。
- groupLayout 显示组元素的资源文件。该资源文件定义了如何显示组元素。该布局文件必须至少包括groupTo中所定义的View。(即groupTo中的View id数组必须都在该布局文件中找到
- groupFrom 一个键值列表。对应与组相关联的Map中的键值。
- grouptTo 组View应当显示groupFrom参数中的所有列数据。这些数据应当都用TextView来显示。列表中的前N个View从前N个groupFrom参数获得列元素的数据。
- childData 一个Map列表的列表。外部列表中的每个实体对应一个组(按照组的位置编号)。在内部列表的每个实体对应某个组的子元素(按照子元素的位置编号)。该Map对应了子元素的数据。(按照childFrom数组中的值编号)。该Map包含了每个子元素的数据,并且应当包括所有在childFrom中指定的实体。
- childLayout 显示子元素的资源文件。该资源文件定义了如何显示子元素。布局文件至少应该包括所有在childTo中定义的View。(即childTo中的view id数组必须都在该布局文件中找到)
- childFrom 定义显示子元素的列名。该列名与childData中的子元素属性(字典键值)对应。
- childTo 子View应当显示childFrom参数中的所有列数据。这些数据应当都用TextView来显示。列表中的前N个View从前N个childFrom参数获得列元素的数据。
2.使用BaseExpandableListAdpter实现
class BaseAdapter extends BaseExpandableListAdapter{
@Override
public int getGroupCount() {
return 0;
}
@Override
public int getChildrenCount(int groupPosition) {
return 0;
}
@Override
public Object getGroup(int groupPosition) {
return null;
}
@Override
public Object getChild(int groupPosition, int childPosition) {
return null;
}
@Override
public long getGroupId(int groupPosition) {
return 0;
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return 0;
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
return null;
}
@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
return null;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return false;
}
}
实验记录:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ExpandableListView
android:id="@+id/listview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
item_groud.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="50dp"
android:orientation="vertical"
android:layout_gravity="center_vertical">
<TextView
android:id="@+id/tv_groud"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
item_child.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="50dp"
android:orientation="vertical"
android:layout_gravity="center_vertical"
android:paddingLeft="50dp"
>
<TextView
android:id="@+id/tv_child"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
MainActivity.java
package me.cyning.ui10;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ExpandableListView;
import android.widget.SimpleExpandableListAdapter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MainActivity extends AppCompatActivity {
String[] groupString={"腾讯","阿里","百度"};
String[][] childString={
{"QQ","微信","gfdsg"},
{"百度搜索","外卖","gdsf"},
{"淘宝","gdsf","dsfg"}
};
List<Map<String,?>> groudData=new ArrayList<>();//不要忘记初始化
List<List<Map<String,?>>> childdata=new ArrayList<>();//不要忘记初始化
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ExpandableListView expandableListView=findViewById(R.id.listview);
for(int i=0;i<groupString.length;i++){
Map<String,String> map=new HashMap<>();
map.put("groudname",groupString[i]);
groudData.add(map);
List<Map<String,?>> itemLis=new ArrayList<>();
for(int j=0;j<childString[i].length;j++){
Map<String,String> map1=new HashMap<>();
map1.put("itemName",childString[i][j]);
itemLis.add(map1);
}
childdata.add(itemLis);
}
SimpleExpandableListAdapter adapter=new SimpleExpandableListAdapter
(this,groudData,R.layout.item_group,new String[]{"groudname"},new int[]{R.id.tv_groud},childdata,R.layout.item_child,
new String[]{"itemName"} ,new int[]{R.id.tv_child});
expandableListView.setAdapter(adapter);
}
}
十、容器控件-LinearLayout
概念:盛放基础UI控件的容器,用来自动控制容器内部每个组件的位置、大小
gravity子元素布置方向
layout_gravity相对于父布局的布置方向
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:gravity="center"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="居中"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="居中"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="居中"/>
</LinearLayout>
十一、容器控件-相对布局RelativeLayout
概念:相对布局容器内的子组件的位置总是相对兄弟组件、或父容器来决定的,这种布局方式也被称为相对布局。
以下属性只能设置在子组件中
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/btn_lonin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="菜单"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="音量+"
android:layout_above="@+id/btn_lonin"
android:layout_centerHorizontal="true"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="音量-"
android:layout_below="@+id/btn_lonin"
android:layout_centerHorizontal="true"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="频道+"
android:layout_toLeftOf="@+id/btn_lonin"
android:layout_centerVertical="true"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="频道-"
android:layout_toRightOf="@+id/btn_lonin"
android:layout_centerVertical="true"/>
</RelativeLayout>
十二、帧布局FrameLayout
概念:帧布局给每个加入其中的组件创建一个空白的区域(称为一帧),每个子组件占据一帧。
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ImageView
android:layout_width="200dp"
android:layout_height="200dp"
android:background="#e0f0"/>
<ImageView
android:layout_width="160dp"
android:layout_height="160dp"
android:layout_margin="20dp"
android:background="#0a0"/>
<ImageView
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_margin="40dp"
android:background="#080"/>
<ImageView
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_margin="60dp"
android:background="#050"/>
<!--先出现的控件新绘制在上面,后出现绘制在先绘制的上面-->
</FrameLayout>
十三、绝对布局AbsoluteLayout
概念:由开发人员通过X、Y坐标来控制控件的显示位置
<?xml version="1.0" encoding="utf-8"?>
<AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_x="104dp"
android:layout_y="63dp"
android:text="码子" />
</AbsoluteLayout>
十四、表格布局TableLayout
概念:表格布局模型以行列的形式管理子控件,每一行为一个TableRow的对象,当然也可以是一个View的对象。TableRow可以添加子控件,每添加一个为一列。
TableLayout属性
**android:collapseColumns:**将TableLayout里面指定的列隐藏,若有多列需要隐藏,请用逗号将需要隐藏的列序号隔开。
**android:stretchColumns:**设置指定的列为可伸展的列,以填满剩下的多余空白空间,若有多列需要设置为可伸展,请用逗号将需要伸展的列序号隔开。
**android:shrinkColumns:**设置指定的列为可收缩的列。当可收缩的列太宽(内容过多)不会被挤出屏幕。当需要设置多列为可收缩时,将列序号用逗号隔开。
<?xml version="1.0" encoding="utf-8"?>
<TableLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:stretchColumns="1,2"
android:shrinkColumns="1">
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="安卓"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="安卓543534534534535353523563555543634253452345"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="安卓3"/>
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:layout_width="100dp"
android:layout_height="wrap_content"/>
<Button
android:layout_width="wrap_content"
android:layout_height="match_parent"/>
</TableRow>
<Button
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="单独一行"/>
</TableLayout>
十五、ViewPager翻页控件
概念:ViewPager是android扩展包v4包中的类,这个类可以让用户左右切换当前的view
作用:安装后的第一次运行的新特性引导页
activity_main.java
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.v4.view.ViewPager
android:id="@+id/my_view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v4.view.ViewPager>
</RelativeLayout>
item_view_pager.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">
<ImageView
android:id="@+id/item_image_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@mipmap/ic_launcher"/>设置背景为启动图标
</LinearLayout>
MainActivity.java
package me.cyning.ui16;
import android.graphics.Color;
import android.support.annotation.NonNull;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
List<View> viewList=new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewPager viewPager=findViewById(R.id.my_view_pager);
{
View view = LayoutInflater.from(this).inflate(R.layout.item_view_pager, null);
ImageView imageView=view.findViewById(R.id.item_image_view);
imageView.setImageResource(R.drawable.wrre);//设置第一页的图片
viewList.add(view);
}
{
View view = LayoutInflater.from(this).inflate(R.layout.item_view_pager, null);
ImageView imageView=view.findViewById(R.id.item_image_view);
imageView.setImageResource(R.drawable.wrre);
viewList.add(view);
}
{
View view = LayoutInflater.from(this).inflate(R.layout.item_view_pager, null);
ImageView imageView=view.findViewById(R.id.item_image_view);
imageView.setImageResource(R.drawable.wrre);
viewList.add(view);
}
viewPager.setAdapter(new PagerAdapter() {
@Override
public int getCount() {
return viewList.size();
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object o) {
return view==o;
}
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
container.addView(viewList.get(position));
return viewList.get(position);
}
@Override
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
container.removeView(viewList.get(position));
}
});
}
}
十六、Menu菜单
概念:当我们按下Menu的硬件按钮时,Option Menu将被触发显示。
Menu有两种形式,Option menu和Context menu。 Option menu是按下设备的Menu硬件按钮弹出
MainActivity.java
package me.cyning.ui17;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.Toast;
import java.lang.reflect.Method;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
//1.第一种方法
new MenuInflater(this).inflate(R.menu.main_menu,menu);
//2.第二种方法
// menu.add("菜单1");
// menu.add("菜单2");
// menu.add("菜单3");
// menu.add("菜单4");
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case R.id.menu1:
Toast.makeText(this,"用户点击了"+item.getTitle(),Toast.LENGTH_SHORT).show();
break;
case R.id.menu2:
Toast.makeText(this,"用户点击了"+item.getTitle(),Toast.LENGTH_SHORT).show();
break;
case R.id.menu3:
Toast.makeText(this,"用户点击了"+item.getTitle(),Toast.LENGTH_SHORT).show();
break;
case R.id.menu4:
Toast.makeText(this,"用户点击了"+item.getTitle(),Toast.LENGTH_SHORT).show();
break;
default:break;
}
return super.onOptionsItemSelected(item);
}
}
man_menu.xml(在menu文件夹下创建)
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/menu1"
android:title="菜单一"/>
<item android:id="@+id/menu2"
android:title="菜单一"/>
<item android:id="@+id/menu3"
android:title="菜单一"/>
<item android:id="@+id/menu4"
android:title="菜单一"/>
</menu>
十七、PopupWindow弹出框
概念: PopupWindow这个类用来实现一个弹出框,可以使用任意布局的View作为其内容,这个弹出框是悬浮在当前activity之上的。 PopupWindow的位置可以随意。
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/btn_pow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="弹出"/>
</RelativeLayout>
pop_windows.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"
android:background="#bbbb">
<TextView
android:id="@+id/tv_tile"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_mes"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/btn_can"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="取消"/>
<Button
android:id="@+id/btn_ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="确认"/>
</LinearLayout>
</LinearLayout>
Main_activity.java
package me.cyning.ui18;
import android.graphics.drawable.BitmapDrawable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.PopupWindow;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
PopupWindow popupWindow;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.btn_pow).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//让popupWindow默认显示
// popupWindow.showAsDropDown(v);
//让popupWindow显示在中间
popupWindow.showAtLocation(MainActivity.this.getWindow().getDecorView(), Gravity.CENTER,0,0);
}
});
//设计popupWindow的View
View view= LayoutInflater.from(this).inflate(R.layout.pop_windows,null);
((TextView)view.findViewById(R.id.tv_tile)).setText("标题");
((TextView)view.findViewById(R.id.tv_mes)).setText("显示消息内容");
view.findViewById(R.id.btn_can).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(v.getContext(),"你点击里取消",Toast.LENGTH_SHORT).show();
popupWindow.dismiss();
}
});
view.findViewById(R.id.btn_ok).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(v.getContext(),"你点击里确认",Toast.LENGTH_SHORT).show();
popupWindow.dismiss();
}
});
//设置popupWindow的View
popupWindow=new PopupWindow(view, WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT);
//弹出popupWindow后点外部,popupWindow消失
popupWindow.setBackgroundDrawable(new BitmapDrawable());
popupWindow.setFocusable(true);
}
}
十八、Fragment碎片(片段)
概念:fragment在应用的扮演的是模块化、可重用的角色。Fragment定义了自己的布局,以及通过它自己的生命周期回调方法定义了它自己的行为,你可以将fragment包含在多个activity中。
Activity和Fragment的关系:
Activity------ Fragment
房子 ------ 房间
1、fragment可以作为activity界面的一部分组成出现
2、一个activity中可以放置多个fragment,而且一个fragment也可以在多个activity中复用
3、可以在activity运行时动态的添加、删除、替换fragment
4、fragment有自己的生命周期,它的生命周期和所在activity的生命周期有一定的关联
onCreateView()方法
Fragment第一次绘制它的用户界面的时候,系统会调用此方法,为了绘制fragment的UI,此方法必须返回一个view,如果不显示UI,返回null即可。
加载方式
静态加载:在activity的xml文件中声明fragment,并且在fragment标签中通过name指定其实例化的fragment类。
动态加载:通过fragment事务来添加、删除、替换fragment。
静态加载
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<fragment
android:id="@+id/maizifragent"
android:layout_width="match_parent"
android:layout_height="200dp"
android:name="me.cyning.ui19.MaiziFragment"/>
</RelativeLayout>
fragment_maizi.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"
android:background="#f00">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="这是MaiziFragment的界面"/>
</LinearLayout>
MaiziFragment.java
package me.cyning.ui19;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class MaiziFragment extends Fragment {
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view=inflater.inflate(R.layout.fragment_maizi,null);//此处第二个参数是null
return view;
}
}
MainActivity.java
package me.cyning.ui19;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
动态加载
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:id="@+id/btn_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="增加"/>
<Button
android:id="@+id/btn_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="减少"/>
<FrameLayout
android:id="@+id/frame_layout"
android:layout_width="match_parent"
android:layout_height="200dp"/>
</LinearLayout>
fragment_maizi.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"
android:background="#f00">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="这是MaiziFragment动态加载的界面"/>
</LinearLayout>
MaiziFragment.java
与静态加载相同
MainActivity.java
package me.cyning.ui19;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends FragmentActivity {
MaiziFragment maiziFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
maiziFragment=new MaiziFragment();
findViewById(R.id.btn_add).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
FragmentManager fm=getSupportFragmentManager();
FragmentTransaction ft=fm.beginTransaction();
ft.add(R.id.frame_layout,maiziFragment);
ft.commit();
}
});
findViewById(R.id.btn_delete).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
FragmentManager fm=getSupportFragmentManager();
FragmentTransaction ft=fm.beginTransaction();
ft.remove(maiziFragment);
ft.commit();
}
});
}
}
使用场景
1、需要重用的界面(可以使用自定义view)
2、需要重用,但是包括多个View组合的界面(也可以使用自定义view)
3、需要重用,但是又和生命周期有关联的界面(只能使用fragment)
fragement_top.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">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="上面显示用户信息"/>
</LinearLayout>
TopFragment.java
package me.cyning.ui20;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class TopFragment extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View rootView=inflater.inflate(R.layout.fragement_top,null);
return rootView;
}
}
fragment_bottom.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"
android:layout_gravity="center">
<Button
android:id="@+id/btn_bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="注销登录"
/>
</LinearLayout>
BottomFragment.java
package me.cyning.ui20;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class BottomFragment extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View rootView=inflater.inflate(R.layout.fragment_bottom,null);
rootView.findViewById(R.id.btn_bottom).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(getContext(),SecondActivity.class);
startActivity(intent);
}
});
return rootView;
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<FrameLayout
android:id="@+id/fram_layout_top"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<FrameLayout
android:id="@+id/fram_layout_bottom"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
实现两个组件界面平分
</LinearLayout>
MainActivity.java
package me.cyning.ui20;
import android.content.Intent;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentManager fm=getSupportFragmentManager();
FragmentTransaction ft=fm.beginTransaction();
ft.replace(R.id.fram_layout_top,new TopFragment());
ft.replace(R.id.fram_layout_bottom,new BottomFragment());
ft.commit();
}
}
activity_second.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:id="@+id/fram_layout_top"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
SecondActivity.java
package me.cyning.ui20;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class SecondActivity extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
FragmentManager fm=getSupportFragmentManager();
FragmentTransaction ft=fm.beginTransaction();
ft.replace(R.id.fram_layout_top,new TopFragment());
ft.commit();
}
}
点击注册登录之后
第一个图中有两个平分布局的Fragment,点击下面的按钮后,第二个Activity是重新利用了上面的Fragment
图一实现一个Activity中实现多个Fragment
图二实现了一个Fragment在不同Activity中重复使用
Fragment与Activity通信
1、fragment直接调用getActivity(),activity直接调用fragment的方法
2、在Fragment中设置回调接口
3、通过handler通信
4、通过广播通信,系统广播、应用内广播
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:id="@+id/btn_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="增加"/>
<Button
android:id="@+id/btn_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="减少"/>
<FrameLayout
android:id="@+id/frame_layout"
android:layout_width="match_parent"
android:layout_height="200dp"/>
<Button
android:id="@+id/btn_motify"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="修改Fragment的几面"/>
<TextView
android:id="@+id/tv_in_activity"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
MainActivity.java
package me.cyning.ui19;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends FragmentActivity {
MaiziFragment maiziFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
maiziFragment=new MaiziFragment();
maiziFragment.setOnBtnClickListener(new MaiziFragment.OnBtnClickListener() {
@Override
public void onBtnClick() {
TextView textView=findViewById(R.id.tv_in_activity);
textView.setText("回调的方式从Fragment修改activity");
}
});
findViewById(R.id.btn_add).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
FragmentManager fm=getSupportFragmentManager();
FragmentTransaction ft=fm.beginTransaction();
ft.add(R.id.frame_layout,maiziFragment);
ft.commit();
}
});
findViewById(R.id.btn_delete).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
FragmentManager fm=getSupportFragmentManager();
FragmentTransaction ft=fm.beginTransaction();
ft.remove(maiziFragment);
ft.commit();
}
});
findViewById(R.id.btn_motify).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
maiziFragment.modify();
}
});
}
// public void modify(){
// TextView textView=findViewById(R.id.tv_in_activity);
// textView.setText("从Fragment修改activity");
// }
}
fragment_maizi.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"
android:background="#f00">
<TextView
android:id="@+id/tv_in_fragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="这是MaiziFragment动态加载的界面"/>
<Button
android:id="@+id/btn_in_fragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
MaiziFragment.java
package me.cyning.ui19;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class MaiziFragment extends Fragment {
public void setOnBtnClickListener(OnBtnClickListener onBtnClickListener) {
this.onBtnClickListener = onBtnClickListener;
}
private OnBtnClickListener onBtnClickListener;
public interface OnBtnClickListener{
void onBtnClick();
}
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view=inflater.inflate(R.layout.fragment_maizi,null);
view.findViewById(R.id.btn_in_fragment).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// MainActivity mainActivity= (MainActivity) getActivity();
// mainActivity.modify();
if(onBtnClickListener!=null){
onBtnClickListener.onBtnClick();
}
}
});
return view;
}
public void modify(){
TextView textView=getView().findViewById(R.id.tv_in_fragment);
textView.setText("已经修改里面元素的值");
}
}
十九、SwipeRefreshLayout下拉刷新
SwipeRefreshLayout是v4包下的一个下拉刷新控件
注意SwipRefreshLayout只能包含一个直接子view
SwipeRefreshLayout是v4包下的一个下拉刷新控件
1、setOnRefreshListener(OnRefreshListener listener) 设置下拉监听,当用户下拉的时候会去执行回调
2、setColorSchemeColors(int… colors) 设置 进度条的颜色变化,最多可以设置4种颜色
3、setProgressViewOffset(boolean scale, int start, int end) 调整进度条距离屏幕顶部的距离
4、setRefreshing(boolean refreshing) 设置SwipeRefreshLayout当前是否处于刷新状态,一般是在请求数据的时候设置为true,在数据被加载到View中后,设置为false。
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/swipe_refresh"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ListView
android:id="@+id/my_list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.v4.widget.SwipeRefreshLayout>
MainActiviy.java
package me.cyning.ui21;
import android.graphics.Color;
import android.os.Handler;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
SwipeRefreshLayout swipeRefreshLayout;
ListView listView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
swipeRefreshLayout=findViewById(R.id.swipe_refresh);
listView=findViewById(R.id.my_list_view);
final List<String> datalst=new ArrayList<>();
for(int i=0;i<30;i++){
datalst.add(i+"");
}
final ArrayAdapter<String> adapter=new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,android.R.id.text1,datalst);
listView.setAdapter(adapter);
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
swipeRefreshLayout.setRefreshing(false);
Toast.makeText(MainActivity.this,"加载完成",Toast.LENGTH_SHORT).show();
for(int i=0;i<20;i++){
datalst.add("新加数据"+i);
}
adapter.notifyDataSetChanged();
}
}, 5000);
}
});
swipeRefreshLayout.setColorSchemeColors(Color.RED,Color.GREEN,Color.CYAN);
swipeRefreshLayout.setProgressViewOffset(false,50,100);
}
}
二十、DrawerLayout侧滑菜单控件
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<!--第一个子view会作为内容显示区-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="显示内容"/>
</LinearLayout>
<!--第二子View会作为侧滑菜单-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:layout_gravity="left">
<ListView
android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
<!--第二子View会作为侧滑菜单-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:layout_gravity="right"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="用户信息"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="退出登录"/>
</LinearLayout>
</android.support.v4.widget.DrawerLayout>
MainActivity.java
package me.cyning.ui22;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listView=findViewById(R.id.list_view);
ArrayAdapter<String> adapter=new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1
,new String[]{"菜单1","菜单2","菜单3","菜单4"});
listView.setAdapter(adapter);
}
}
二十一、RecyclerView循环复用控件
优点:提供了一种插拔式的体验,高度的解耦,异常的灵活。
用法:
1、通过布局管理器LayoutManager,控制其显示的方式
2、通过ItemDecoration控制Item间的间隔(可绘制)
3、通过ItemAnimator控制Item增删的动画
横向布局
如果想要一个横向的List只要设置LinearLayoutManager如下就行,注意要声明mLayoutManager的类型是LinearLayoutManager而不是父类LayoutManager:
mLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
Grid布局
如果想要一个Grid布局的列表,只要声明LayoutManager为GridLayoutManager即可:
mLayoutManager = new GridLayoutManager(context,columNum);
mRecyclerView.setLayoutManager(mLayoutManager);
注意,在Grid布局中也可以设置列表的Orientation属性,来实现横向和纵向的Grid布局。