8、控件
TextView:
android:gravity 来指定文字的对齐方式,可选值有 top、bottom、left、right、center等 , 可以用 “ | ” 来同时指定多个值,这里我们指定的 "center",效果等同于
"center_vertical|center_horizontal",表示文字在垂直和水平方向都居中对齐
android:textSize 属性可以指定文字的大小
android:textColor 属性可以指定文字的颜色
button:
方式1:
button = (Button) findViewById(R.id.button); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // 在此处添加逻辑 } });
方式2:
不喜欢使用匿名类的方式来注册监听器,也可以使用实现接口的方式来进行注册
活动实现OnClickListener接口,然后重载onClick方法。
public class MainActivity extends Activity implements OnClickListener{ @Override public void onClick(View v) { switch (v.getId()) { case R.id.button: // 在此处添加逻辑 break; default: break; } } }
EditText:
android:hint="Type something here" 提示文字
android:maxLines 指定了 EditText 的最大行数为两行
ImageView:
android:src="@drawable/ic_launcher"
drawable 文件夹下已经有一张ic_launcher.png图片
imageView.setImageResource(R.drawable.jelly_bean);
AlertDialog:
setCancelable(false);
setCancelable()方法将对话框设为不可取消,否则用户按一下 Back 键就可以关闭对话框继续使用程序了
setPositiveButton()
给对话框注册确定按钮
AlertDialog.Builder dialog = new AlertDialog.Builder(SecondActivity.this); dialog.setTitle("This is Dialog"); dialog.setMessage("Something important."); dialog.setCancelable(false); dialog.setPositiveButton("OK", new DialogInterface. OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }); dialog.setNegativeButton("Cancel", new DialogInterface. OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }); dialog.show();
ListView:
android.R.layout.simple_list_item_1 作为ListView 子项布局的 id,这是一个 Android 内置
的布局文件,里面只有一个 TextView,可用于简单地显示一段文本 ArrayAdapter 这种实现
ListView 是最容易实现,但最不容易扩展的实现方法 ArrayAdapter 的构造函数中依次传入
当前上下文、ListView 子项布局的 id,以及要适配的数据
ArrayAdapter<String> adapter = new ArrayAdapter<String>( MainActivity.this, android.R.layout.simple_list_item_1, data); ListView listView = (ListView) findViewById(R.id.list_view); listView.setAdapter(adapter);
定制 ListView 的界面
1、编写实体类Fruit
public class Fruit { private String name; private int imageId; public Fruit(String name, int imageId) { this.name = name; this.imageId = imageId; } public String getName() { return name; } public int getImageId() { return imageId; } }
2、新建fruit_item.xml 定义每一项的展示方式布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <ImageView android:id="@+id/fruit_image" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/fruit_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_marginLeft="10dip" /> </LinearLayout>
3、创建一个自定义的适配器,这个适配器继承自 ArrayAdapter,并将泛型指定为 Fruit 类
public class FruitAdapter extends ArrayAdapter<Fruit> { private int resourceId; //textViewResourceId:ListView 子项布局的 id public FruitAdapter(Context context, int textViewResourceId,List<Fruit> objects) { super(context, textViewResourceId, objects); resourceId = textViewResourceId; } @Override public View getView(int position, View convertView, ViewGroup parent) { Fruit fruit = getItem(position); // 获取当前项的Fruit实例 View view = LayoutInflater.from(getContext()).inflate(resourceId, null); ImageView fruitImage = (ImageView) view.findViewById(R.id.fruit_image); TextView fruitName = (TextView) view.findViewById(R.id.fruit_name); fruitImage.setImageResource(fruit.getImageId()); fruitName.setText(fruit.getName()); return view; } }
FruitAdapter 重写了父类的一组构造函数,用于将上下文、ListView 子项布局的 id 和数据都传递进来。
另外又重写了 getView()方法,这个方法在每个子项被滚动到屏幕内的时候会被调用。
在 getView 方法中,首先通过 getItem()方法得到当前项的 Fruit 实例,然后使用LayoutInflater 来为这个子项加载我们传入的布局,接着调用 View 的 findViewById()方法分别获取到 ImageView 和 TextView 的实例,并分别调用它们的 setImageResource()和 setText()方法来设置显示的图片和文字,最后将布局返回
4、主活动中添加list_view
initFruits(); // 初始化水果数据 FruitAdapter adapter = new FruitAdapter(MainActivity.this, R.layout.fruit_item, fruitList); ListView listView = (ListView) findViewById(R.id.list_view); listView.setAdapter(adapter); private List<Fruit> fruitList = new ArrayList<Fruit>(); private void initFruits() { Fruit apple = new Fruit("Apple", R.drawable.apple_pic); fruitList.add(apple) Fruit mango = new Fruit("Mango", R.drawable.mango_pic); fruitList.add(mango); }
提升 ListView 的运行效率
目前我们 ListView的运行效率是很低的,因为在 FruitAdapter的 getView()方法中每次都将布局重新加载了一遍,当 ListView 快速滚动的时候这就会成为性能的瓶颈
getView()方法中还有一个 convertView 参数,这个参数用于将之前加载好的布局进行缓存,以便之后可以进行重用
public View getView(int position, View convertView, ViewGroup parent) { Fruit fruit = getItem(position); View view; if (convertView == null) { view = LayoutInflater.from(getContext()).inflate(resourceId, null); } else { view = convertView; } ImageView fruitImage = (ImageView) view.findViewById(R.id.fruit_image); TextView fruitName = (TextView) view.findViewById(R.id.fruit_name); fruitImage.setImageResource(fruit.getImageId()); fruitName.setText(fruit.getName()); return view; } }虽然现在已经不会再重复去加载布局,但是每次在 getView()方法中还是会调用 View的 findViewById()方法来获取一次控件的实例。
我们可以借助convertView.setTag(obj)来对这部分性能进行优化
public View getView(int position, View convertView, ViewGroup parent) { Fruit fruit = getItem(position); View view; ViewHolder viewHolder; if (convertView == null) { view = LayoutInflater.from(getContext()).inflate(resourceId, null); viewHolder = new ViewHolder(); viewHolder.fruitImage = (ImageView) view.findViewById(R.id.fruit_image); viewHolder.fruitName = (TextView) view.findViewById(R.id.fruit_name); view.setTag(viewHolder); // 将ViewHolder存储在View中 } else { view = convertView; viewHolder = (ViewHolder) view.getTag(); // 重新获取ViewHolder } viewHolder.fruitImage.setImageResource(fruit.getImageId()); viewHolder.fruitName.setText(fruit.getName()); return view; } class ViewHolder { ImageView fruitImage; TextView fruitName; } //点击每项时: listView.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Fruit fruit = fruitList.get(position); Toast.makeText(MainActivity.this, fruit.getName(),Toast.LENGTH_SHORT) .show(); } });...
9、布局
LinearLayout :
又称作线性布局,是一种非常常用的布局。
这个布局会将它所包含的控件在线性方向上依次排列
android:orientation="horizontal"
当LinearLayout 的排列方向是 horizontal 时,只有垂直方向上的对齐方式才会生效,因为此时水平方向上的长度是不固定的,每添加一个控件,水平方向上的长度都会改变,因而无法指定该方向上的对齐方式。同样的道理,
当 LinearLayout 的排列方向是 vertical 时,只有水平方向上的对齐方式才会生效。
android:layout_height="150px"
RelativeLayout:
又称作相对布局,也是一种非常常用的布局。它可以通过相对定位的方式让控件出现在布局的任何位置。
相对于父布局定位
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_alignParentBottom="true
android:layout_centerInParent="true"
相对于控件定位
android:layout_above 属性可以让一个控件位于另一个控件的上方,需要为这个属性指定相对控件 id 的引用,这里我们填入了 @id/button3,表示让该控件位于Button 3的上方 。
android:layout_below 表示让一个控件位于另一个控件的下方
android:layout_toLeftOf 表示让一个控件位于另一个控件的左侧
android:layout_toRightOf 表示让一个控件位于另一个控件的右侧。
注意,当一个控件去引用另一个控件的 id 时,该控件一定要定义在引用控件的后面,
不然会出现找不到 id 的情况
android:layout_alignLeft="@id/btn1" 表示让一个控件跟另一个控件左侧对齐
FrameLayout:
所有的控件都会摆放在布局的左上角
它的应用场景并不多
TableLayout:
使用表格的方式来排列控件
这种布局也不是很常用
android:layout_span="2" 合并单元格,让登录按钮占据两列的空间
android:stretchColumns 的值指定为 1,表示如果表格不能完全占满屏幕宽度,将第二列进行拉伸。没错!指定成 1 就是拉伸第二列,指定成 0 就是拉伸第一列
TableRow 中无法指定控件的宽度。这时使用android:stretchColumns 属性就可以很好地解决这个问题,它允许将 TableLayout 中的某一列进行拉伸,以达到自动适应屏幕宽度的作用
控件中:
android:gravity 是用于指定文字在控件中的对齐方式,
android:layout_gravity 是用于指定控件在布局中的对齐方式 。
android:background 用于为布局或控件指定一个背景
android:layout_width="0dp"
android:layout_weight="1"
由于我们使用了 android:layout_weight 属性,此时控件的宽度就不应该再由 android:layout_width 来决定,这里指定成 0 是一种比较规范的写法。
然后我们在 EditText 和 Button 里都将 android:layout_weight 属性的值指定为 1,这表示EditText 和 Button 将在水平方向平分宽度
为什么将 android:layout_weight 属性的值同时指定为 1 就会平分屏幕宽度呢?其实原理也很简单,系统会先把 LinearLayout 下所有控件指定的 layout_weight 值相加,得到一个总值,然后每个控件所占大小的比例就是用该控件的 layout_weight 值除以刚才算出的总值。
因此如果想让 EditText 占据屏幕宽度的 3/5,Button 占据屏幕宽度的 2/5,只需要将 EditText 的layout_weight 改成 3,Button 的 layout_weight 改成 2 就可以了。
我们仅指定了 EditText 的 android:layout_weight=1 属性,并将 Button 的宽度改回wrap_content。这表示 Button 的宽度仍然按照 wrap_content 来计算,而 EditText 则会占满屏幕所有的剩余空间。
android:layout_margin 可以指定控件在上下左右方向上偏移的距离
android:layout_marginLeft 或 android:layout_marginTop 等属性来单独指定控件在某个方向上偏移的距离
自定义控件
我们所用的所有控件都是直接或间接继承自 View 的,所用的所有布局都是直接或间接继承自 ViewGroup 的。
View 是 Android 中一种最基本的 UI 组件,它可以在屏幕上绘制一块矩形区域,并能响应这块区域的各种事件,因此,我们使用的各种控件其实就是在 View 的基础之上又添加了各自特有的功能。
ViewGroup 则是一种特殊的 View,它可以包含很多的子 View 和子 ViewGroup,是一个用于放置控件和布局的容器。
新建标题头布局文件title.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/title_bg" > <Button android:id="@+id/title_back" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_margin="5dip" android:background="@drawable/back_bg" android:text="Back" android:textColor="#fff" /> <TextView android:id="@+id/title_text" android:layout_width="0dip" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_weight="1" android:gravity="center" android:text="Title Text" android:textColor="#fff" android:textSize="24sp" /> <Button android:id="@+id/title_edit" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_margin="5dip" android:background="@drawable/edit_bg" android:text="Edit" android:textColor="#fff" /> </LinearLayout>
在主布局文件activity_main.xml引入控件title.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <include layout="@layout/title" /> </LinearLayout>
创建自定义控件
如果布局中有一些控件要求能够响应事件,我们还是需要在每个活动中为这些控件单独编写一次事件注册的代码。
比如说标题栏中的返回按钮,其实不管是在哪一个活动中,这个按钮的功能都是相同的,即销毁掉当前活动。而如果在每一个活动中都需要重新注册一遍返回按钮的点击事件,无疑又是增加了很多重复代码,这种情况最好是使用自定义控件的方式来解决
LayoutInflater
动态加载布局文件
通过 LayoutInflater 的 from()方法可以构建出一个 LayoutInflater对象,然后调用 inflate()方法就可
以动态加载一个布局文件,inflate()方法接收两个参数,第一个参数是要加载的布局文件的 id,这里我们传入
R.layout.title,第二个参数是给加载好的布局再添加一个父布局,这里我们想要指定为 TitleLayout,于是直接
传入 this。
public class TitleLayout extends LinearLayout { public TitleLayout(Context context, AttributeSet attrs) { super(context, attrs); //动态加载title.xml布局文件 LayoutInflater.from(context).inflate(R.layout.title, this); Button titleBack = (Button) findViewById(R.id.title_back); Button titleEdit = (Button) findViewById(R.id.title_edit); titleBack.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { ((Activity) getContext()).finish(); } }); titleEdit.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Toast.makeText(getContext(), "You clicked Edit button", Toast.LENGTH_SHORT).show(); } }); } }
在布局文件中添加这个自定义控件,修改activity_main.xml 中的代码,添加自定义控件:
<com.example.uicustomviews.TitleLayout android:layout_width="match_parent" android:layout_height="wrap_content"> </com.example.uicustomviews.TitleLayout>
添加自定义控件和添加普通控件的方式基本是一样的,只不过在添加自定义控件的时候我们需要指明控件的完整类名,包名在这里是不可以省略的
在实际开发中LayoutInflater这个类还是非常有用的,它的作用类似于findViewById()。不同点是LayoutInflater是用来找res/layout/下的xml布局文件,并且实例化;而findViewById()是找xml布局文件下的具体widget控件(如Button、TextView等)。
具体作用:
1、对于一个没有被载入或者想要动态载入的界面,都需要使用LayoutInflater.inflate()来载入;
2、对于一个已经载入的界面,就可以使用Activiyt.findViewById()方法来获得其中的界面元素。
LayoutInflater 是一个抽象类,在文档中如下声明:
public abstract class LayoutInflater extends Object
获得 LayoutInflater 实例的三种方式
1. LayoutInflater inflater = getLayoutInflater();//调用Activity的getLayoutInflater()
2. LayoutInflater inflater = LayoutInflater.from(context);
3. LayoutInflater inflater = (LayoutInflater)context.getSystemService
(Context.LAYOUT_INFLATER_SERVICE);
结论:所以这三种方式最终本质是都是调用的Context.getSystemService()。
inflater(resId, null )的确不能正确处理宽高的值
inflater(resId,parent,false)可以看出完美的显示了宽和高
而inflater(resId,parent,true)报错了
Android LayoutInflater深度解析 给你带来全新的认识
http://blog.csdn.net/lmj623565791/article/details/38171465
9、碎片
...
相关推荐
创建第一个Android应用程序通常是从一个简单的“Hello, World!”程序开始。这个过程涉及创建一个新的Android项目,理解项目目录结构,如src、res和AndroidManifest.xml文件。AndroidManifest.xml文件是每个应用的...
这里我们讨论的是第一种情况,即继承View。 2. **创建自定义View类**: 首先,我们需要创建一个新的Java类,让它继承自View。在这个类中,我们可以重写构造函数,设置初始属性,以及添加我们需要的额外功能。 3. ...
1. **自定义View**:自定义控件是实现特殊UI效果的常用手段,需要了解View的生命周期、onDraw()方法用于绘制界面,以及事件监听机制,如OnTouchListener,来处理用户的触摸操作。 2. **触摸事件处理**:通过...
"疯狂Android讲义第二版程序代码"是一份宝贵的资源,它包含了大量示例和实践项目,可以帮助初学者快速掌握Android应用程序开发的核心概念和技术。这些代码示例通常涵盖了从基础UI设计、数据存储、网络通信到多媒体...
《疯狂安卓讲义代码 第一部分》是一份涵盖了Android开发基础至进阶的代码集合,源自于教学光盘,旨在帮助学习者深入理解Android应用开发的各项技术。这份资源包含的六个子文件分别命名为04、01、05、02、03、10,...
5. **适配不同版本的Android**:考虑到Android系统的碎片化,一个完整的状态栏控件通常会处理好不同Android版本之间的兼容性问题。 6. **交互功能**:可能包含点击事件处理,允许用户通过点击状态栏执行特定操作。 ...
"60个Android经典入门程序源代码"提供了一个绝佳的学习资源,涵盖了各种核心概念和技术。这些源代码实例是初学者掌握Android编程的关键步骤,也是进阶开发者巩固基础的宝贵资料。下面将详细阐述这些源代码中可能包含...
1. 《第一行代码 Android 第 2 版》 2. 电子工程系《手机 APP 编程开发》课程标准 2020 年版本 Android 手机 APP 编程开发的教学计划表包括: 1. 第 1 周: Android 王国简介、手把手带你搭建开发环境 2. 第 2 周...
了解如何安装和配置Android Studio是学习Android开发的第一步。 2. **Hello World程序**:每个编程语言的学习都从"Hello, World!"开始。在Android中,这通常涉及创建一个简单的Activity,显示一个TextView控件来...
描述中提到的"listview"是指Android原生的ListView组件,这是一个常用的列表展示控件。然而,由于ListView的局限性(如滚动性能问题和对嵌套滚动支持不足),现代Android应用更倾向于使用RecyclerView。尽管如此,这...
实现底部菜单栏的第一步是创建Fragment的实例。通常,我们会根据菜单栏的选项创建相应的Fragment子类,比如`HomeFragment`, `MyWalletFragment`, `DiscoverFragment`, `MeFragment`等。每个Fragment对应一个功能模块...
《Android移动开发项目式教程(第2版)》是一本深度探讨Android应用程序开发的专业书籍,其源代码提供了丰富的实践案例,帮助读者通过实际操作来掌握Android开发的关键技术。以下是基于这个教程源代码所涵盖的一些...
第1章 Android Studio环境搭建 * Android Studio简介 * Android Studio的安装 * 运行小应用Hello World * App的工程结构 * 准备开始 第2章初级控件 * 屏幕显示 * 简单布局 * 简单控件 * 图形基础 * 实战项目:...
【Android代码-炫酷相册源码.zip】这个压缩包文件是关于Android平台上的一个炫酷相册应用的源代码。在Android开发中,相册功能是常见的需求,而这款相册源码提供了独特的视觉效果和用户体验。让我们深入探讨一下其中...
项目重要技术点: 1-绘制布局,掌握android基本view控件的属性和使用 2-熟练掌握Activity页面展示,跳转和传值 3-使用碎片加载界面,滑动视图切换页面 4-自定义对话框 5-自定义软键盘绘制和使用 6-列表视图以及网格...
2. **Hello World**:学习任何编程语言的第一步通常是打印"Hello, World!",在Android中,这涉及到创建一个新的Activity(应用程序的主要界面)和一个TextView,用于显示文本。 3. **布局设计**:Android使用XML...
项目重要技术点: 1-绘制布局,掌握android基本view控件的属性和使用 2-熟练掌握Activity页面展示,跳转和传值 3-使用碎片加载界面,滑动视图切换页面 4-自定义对话框 5-自定义软键盘绘制和使用 6-列表视图以及网格...
项目重要技术点: 1-绘制布局,掌握android基本view控件的属性和使用 2-熟练掌握Activity页面展示,跳转和传值 3-使用碎片加载界面,滑动视图切换页面 4-自定义对话框 5-自定义软键盘绘制和使用 6-列表视图以及网格...
1. **布局管理器(Layout Managers)**:如LinearLayout、RelativeLayout、GridLayout和ConstraintLayout等,它们用于组织和控制屏幕上控件的排列方式。 2. **自定义View**:讲解如何创建和扩展Android的内置视图类...
范例代码会展示如何使用不同的布局类型(如LinearLayout、RelativeLayout、ConstraintLayout等)和视图控件来创建复杂的UI。 6. **Intent和Intent Filter**:Intent是Android中用于启动Activity或Service的对象。...