(一)Android常用控件及简单用法
1、如下图:
2、补充:
(1)margin:外边距;padding:内边距。
(2)gravity:子元素的位置;layout_gravity:子元素在父元素中的位置。
(3)当布局方向为横向时,不能指定子元素在横向上的对齐方式;竖向同理。
(二)四种布局
1、布局与控件的嵌套关系:
2、四种基本布局
(三)自定义控件的使用
1、Android中控件和布局的继承结构图:
2、在xml文件中引入布局
假如新建了一个名为title.xml的布局文件,作为标题栏,然后在activity_main.xml中可以用<include layout="@layout/title" />这样的方法引入title.xml的布局。
3、创建自定义控件并为控件中的元素添加点击事件:
(1)title_base.xml和color.xml(用于保存常用颜色)
title_base.xml:
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="wrap_content" 5 android:background="@drawable/TitleBaseBg" 6 android:orientation="horizontal" > 7 8 <LinearLayout 9 android:layout_width="0dp" 10 android:layout_height="wrap_content" 11 android:layout_gravity="center" 12 android:layout_weight="1" 13 android:gravity="left" 14 android:orientation="vertical" > 15 16 <ImageButton 17 android:id="@+id/title_base_left_ib" 18 android:layout_width="wrap_content" 19 android:layout_height="wrap_content" 20 android:background="@drawable/Transparent" 21 android:padding="5dp" 22 android:src="@drawable/back1_64" /> 23 </LinearLayout> 24 25 <LinearLayout 26 android:layout_width="0dp" 27 android:layout_height="wrap_content" 28 android:layout_gravity="center_vertical" 29 android:layout_weight="1" 30 android:gravity="center" 31 android:orientation="vertical" > 32 33 <TextView 34 android:id="@+id/title_base_middle_tv" 35 android:layout_width="wrap_content" 36 android:layout_height="wrap_content" 37 android:text="我的App" 38 android:textColor="@drawable/White" 39 android:textSize="20sp" /> 40 </LinearLayout> 41 42 <LinearLayout 43 android:layout_width="0dp" 44 android:layout_height="wrap_content" 45 android:layout_gravity="center" 46 android:layout_weight="1" 47 android:gravity="right" 48 android:orientation="vertical" > 49 50 <ImageButton 51 android:id="@+id/title_base_right_ib" 52 android:layout_width="wrap_content" 53 android:layout_height="wrap_content" 54 android:background="@drawable/Transparent" 55 android:padding="5dp" 56 android:src="@drawable/add4_64" /> 57 </LinearLayout> 58 59 </LinearLayout>
color.xml:
1 <?xml version="1.0" encoding="utf-8"?> 2 <resources> 3 4 <drawable name="TitleBaseBg">#ff272636</drawable> 5 <drawable name="Transparent">#00ffffff</drawable> 6 <drawable name="White">#ffffffff</drawable> 7 8 </resources>
(2)BaseTitleLayout.java,是个抽象类,继承自LinearLayout:
1 public abstract class BaseTitleLayout extends LinearLayout { 2 protected ImageButton titleBaseLeftIb; 3 protected TextView titleBaseMiddleTv; 4 protected ImageButton titleBaseRightIb; 5 6 public BaseTitleLayout(Context context, AttributeSet attrs) { 7 super(context, attrs); 8 LayoutInflater.from(context).inflate(R.layout.title_base, this); 9 10 titleBaseLeftIb = (ImageButton) findViewById(R.id.title_base_left_ib); 11 titleBaseMiddleTv = (TextView) findViewById(R.id.title_base_middle_tv); 12 titleBaseRightIb = (ImageButton) findViewById(R.id.title_base_right_ib); 13 14 changeUI(); 15 onLeftClick(); 16 onRightClick(); 17 } 18 19 // 改变标题栏按钮、文字、背景等 20 protected abstract void changeUI(); 21 22 // 标题栏左边按钮的点击事件 23 protected abstract void onLeftClick(); 24 25 // 标题栏右边按钮的点击事件 26 protected abstract void onRightClick(); 27 28 }
(3)MainActivityTitleLayout.java,继承自BaseTitleLayout:
1 public class MainActivityTitleLayout extends BaseTitleLayout { 2 3 public MainActivityTitleLayout(Context context, AttributeSet attrs) { 4 super(context, attrs); 5 6 } 7 8 @Override 9 protected void changeUI() { 10 titleBaseLeftIb.setVisibility(View.INVISIBLE); 11 } 12 13 @Override 14 protected void onLeftClick() { 15 16 } 17 18 @Override 19 protected void onRightClick() { 20 titleBaseRightIb.setOnClickListener(new OnClickListener() { 21 22 @Override 23 public void onClick(View v) { 24 Toast.makeText(getContext(), "点击了添加按钮", Toast.LENGTH_SHORT) 25 .show(); 26 } 27 }); 28 } 29 30 }
(4)activity_main.xml:
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 android:layout_width="match_parent" 3 android:layout_height="match_parent" 4 android:orientation="vertical" > 5 6 <com.easydo.layout.MainActivityTitleLayout 7 android:layout_width="match_parent" 8 android:layout_height="wrap_content" > 9 </com.easydo.layout.MainActivityTitleLayout> 10 11 </LinearLayout>
(5)MainActivity:
1 public class MainActivity extends Activity { 2 3 @Override 4 protected void onCreate(Bundle savedInstanceState) { 5 super.onCreate(savedInstanceState); 6 requestWindowFeature(Window.FEATURE_NO_TITLE); 7 setContentView(R.layout.activity_main); 8 } 9 }
(6)运行效果:
(四)ListView的用法
1、最简单的用法
(1)xml文件:
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 android:layout_width="match_parent" 3 android:layout_height="match_parent" 4 android:orientation="vertical" > 5 6 <ListView 7 android:id="@+id/content_lv" 8 android:layout_width="match_parent" 9 android:layout_height="match_parent" > 10 </ListView> 11 12 </LinearLayout>
(2)MainActivity(详细步骤见注释)
1 public class MainActivity extends Activity { 2 // 1.创建数据数组 3 private String[] animalList = { "猫", "狗", "狐狸", "小熊", "鱼", "老虎", 4 "长颈鹿", "象", "龙猫" }; 5 6 ListView listView; 7 8 @Override 9 protected void onCreate(Bundle savedInstanceState) { 10 super.onCreate(savedInstanceState); 11 setContentView(R.layout.activity_main); 12 13 // 2.创建以数据列表元素类型为泛型的适配器 14 // 构造函数:第一个参数为上下文;第二个参数为列表项的布局,这里用Android自带的布局;第三个参数为第1步中准备好的数据数组. 15 // simple_list_item_1:单行显示,其中只有一个TextView 16 // simple_list_item_2:双行显示,有两个TextView,两行字大小不一样 17 // two_line_list_item:双行显示,有两个TextView,两行字大小一样 18 ArrayAdapter<String> adapter = new ArrayAdapter<String>( 19 MainActivity.this, android.R.layout.simple_list_item_1, 20 animalList); 21 // 3.获取xml中的ListView实例 22 listView = (ListView) findViewById(R.id.content_lv); 23 24 // 4.用第2步创建好的适配器来设置ListView实例的内容 25 listView.setAdapter(adapter); 26 } 27 }
(3)运行结果:
2、定制的ListView界面
上面的ListView每个项只能显示一个文本,太单调了,下面通过定制的方式让它丰富起来。实现左边显示一个图片,右边显示动物名字的效果。
步骤如下:
(1)创建一个实体类Animal,作为ListView适配器的类型:
1 public class Animal { 2 private String name; 3 private int imageId; 4 5 public Animal(String name, int imageId) { 6 this.name = name; 7 // 对应的图片ID 8 this.imageId = imageId; 9 } 10 11 public String getName() { 12 return name; 13 } 14 15 public int getImageId() { 16 return imageId; 17 } 18 19 }
(2)创建animal_item.xml文件,其中包含一个ImageView和一个TextView:
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical" > 6 7 <ImageView 8 android:id="@+id/animal_img_iv" 9 android:layout_width="wrap_content" 10 android:layout_height="wrap_content" /> 11 12 <TextView 13 android:id="@+id/animal_name_tv" 14 android:layout_width="wrap_content" 15 android:layout_height="wrap_content" 16 android:layout_gravity="center" 17 android:layout_marginLeft="10dp" /> 18 19 </LinearLayout>
(3)创建自定义适配器类AnimalAdapter,以Animal类为泛型,继承自ArrayAdapter<Animal>,重写父类的构造方法和getView方法,getView方法会在每个子项被滚动到屏幕内的时候调用:
1 public class AnimalAdapter extends ArrayAdapter<Animal> { 2 3 private int resourceId; 4 5 public AnimalAdapter(Context context, int textViewResourceId, 6 List<Animal> objects) { 7 super(context, textViewResourceId, objects); 8 // textViewResourceId:ListView子项布局的id;objects:数据 9 resourceId = textViewResourceId; 10 } 11 12 // getView方法会在每个子项被滚动到屏幕内的时候调用 13 @Override 14 public View getView(int position, View convertView, ViewGroup parent) { 15 // 1.获取当前项的Animal实例 16 Animal animal = getItem(position); 17 18 // 2.为这个子项加载传入的布局 19 View view = LayoutInflater.from(getContext()).inflate(resourceId, null); 20 21 // 3.用view的findViewById方法获取到子项布局控件的实例 22 ImageView animalImage = (ImageView) view 23 .findViewById(R.id.animal_img_iv); 24 TextView animalName = (TextView) view.findViewById(R.id.animal_name_tv); 25 26 // 4.设置相应控件的内容 27 animalImage.setImageResource(animal.getImageId()); 28 animalName.setText(animal.getName()); 29 30 // 5.返回view 31 return view; 32 } 33 }
注:在getView方法里还可以为item的子控件添加点击事件。
(4)MainActivity:
1 public class MainActivity extends Activity { 2 // 1.创建动物名字数组和动物数据列表 3 private String[] animalNameList = { "猫", "狗", "狐狸", "小熊", "鱼", "老虎", "长颈鹿", 4 "象", "龙猫" }; 5 private List<Animal> animalList = new ArrayList<Animal>(); 6 // 为简单起见,把所有动物的图片都设置为ic_launcher 7 private int animalImageResourceId = R.drawable.ic_launcher; 8 9 ListView listView; 10 11 @Override 12 protected void onCreate(Bundle savedInstanceState) { 13 super.onCreate(savedInstanceState); 14 setContentView(R.layout.activity_main); 15 16 // 2.初始化动物数据 17 initAnimals(); 18 19 // 3.创建自定义的适配器实例 20 // 构造函数:第一个参数:当前上下文;第二个参数:子项布局xml文件;第三个参数:动物数据List 21 AnimalAdapter adapter = new AnimalAdapter(MainActivity.this, 22 R.layout.animal_item, animalList); 23 24 // 4.获取ListView实例 25 listView = (ListView) findViewById(R.id.content_lv); 26 27 // 5.设置适配器 28 listView.setAdapter(adapter); 29 30 } 31 32 private void initAnimals() { 33 for (int i = 0; i < animalNameList.length; i++) { 34 Animal animal = new Animal(animalNameList[i], animalImageResourceId); 35 animalList.add(animal); 36 } 37 } 38 }
(5)运行效果:
3、提升ListView的效率
在AnimalAdapter的getView方法中,每次都将布局重新加载一遍,当快速滚动屏幕时候就会带来性能问题,为此要做一些优化。修改如下:
1 public class AnimalAdapter extends ArrayAdapter<Animal> { 2 3 private int resourceId; 4 5 public AnimalAdapter(Context context, int textViewResourceId, 6 List<Animal> objects) { 7 super(context, textViewResourceId, objects); 8 // textViewResourceId:ListView子项布局的id;objects:数据
9 resourceId = textViewResourceId; 10 } 11 12 // getView方法会在每个子项被滚动到屏幕内的时候调用 13 @Override 14 public View getView(int position, View convertView, ViewGroup parent) { 15 Animal animal = getItem(position); 16 17 // 用于提升性能 18 View view; 19 ViewHolder viewHolder; 20 if (convertView == null) { 21 view = LayoutInflater.from(getContext()).inflate(resourceId, null); 22 viewHolder = new ViewHolder(); 23 viewHolder.animalImage = (ImageView) view 24 .findViewById(R.id.animal_img_iv); 25 viewHolder.animalName = (TextView) view 26 .findViewById(R.id.animal_name_tv); 27 28 // 将viewHolder存储在View中 29 view.setTag(viewHolder); 30 } else { 31 view = convertView; 32 33 // 重新获取viewHolder 34 viewHolder = (ViewHolder) view.getTag(); 35 } 36 37 viewHolder.animalImage.setImageResource(animal.getImageId()); 38 viewHolder.animalName.setText(animal.getName()); 39 40 return view; 41 } 42 43 // 创建内部类用于缓存,优化性能 44 class ViewHolder { 45 ImageView animalImage; 46 TextView animalName; 47 } 48 }
4、为ListView的子项添加点击事件
使用ListView对象的setOnItemClickListener方法,如:
1 ... 2 listView.setAdapter(adapter); 3 4 listView.setOnItemClickListener(new OnItemClickListener() { 5 6 @Override 7 public void onItemClick(AdapterView<?> parent, View view, 8 int position, long id) { 9 Animal animal = animalList.get(position); 10 Toast.makeText(MainActivity.this, animal.getName(), 11 Toast.LENGTH_SHORT).show(); 12 } 13 14 });
5、补充:
(1)xml中设置ListView的分割线颜色:android:divider="#000"
(2)将ListView定位到最后一行:listView.setSelection(dataList.size());
(五)单位和尺寸
1、像素密度:每英寸所包含的像素数,单位为dpi.
x方向像素密度值的获取方法:float xdpi = getResources().getDisplayMetrics().xdpi;
y方向像素密度值的获取方法:float ydpi = getResources().getDisplayMetrics().ydpi;
2、使用dp为单位来设置控件的宽和高,就可以保证控件在不同像素密度的屏幕上显示的比例是一致的。使用sp来设置字体大小同理。
(六)制作Nine-Patch图片
详见另一篇博文:Android制作和使用Nine-Patch图片