android常用控件和布局

幽映每白日,清辉照衣裳。这篇文章主要讲述android常用控件和布局相关的知识,希望能为你提供帮助。
目录

  • 控件
    • TextView
    • Button
    • EditText
    • ImageView
    • ProgressBar
    • AlertDialog
    • ProgressDialog
    • ListView
      • ListView的简单用法
      • 定制ListView界面
    • RecyclerView
  • 布局
    • 线性布局LinearLayout
    • 相对布局RelativeLayout
    • 帧布局FrameLayout
    • 百分比布局PercentFrameLayout和PercentRelativeLayout
    • 表格布局TableLayout
  • 创建自定义控件
    • 引入布局
    • 自定义控件
新建一个UIWidgetDemo来测试android中的控件和布局。
控件 TextView??android中所有控件都有android:layout_width和android:layout_height这两个属性。这两个属性的可选值有3个:match_parent,fill_parent和wrap_parent。其中,match_parent和fill_parent意义相同,官方更推荐使用match_parent。
< ?xml version=" 1.0" encoding=" utf-8" ?> < LinearLayout xmlns:android=" http://schemas.android.com/apk/res/android" android:orientation=" vertical" android:layout_width=" match_parent" android:layout_height=" match_parent" > < !-- gravity属性为文字的对齐方式,可选值有top,bottom,left,right和center,可以使用' |' 来分隔多个值 --> < TextView android:id=" @+id/text_view" android:layout_width=" match_parent" android:layout_height=" wrap_content" android:textColor=" #00FFEA" android:gravity=" center" android:textSize=" 24sp" android:text=" This is a TextView!" /> < /LinearLayout>

android常用控件和布局

文章图片

Button??默认情况下,系统会将button内的英文自动转换为大写,如果这不是你想要的效果,可以将textAllCaps属性设为false。
< ?xml version=" 1.0" encoding=" utf-8" ?> < LinearLayout xmlns:android=" http://schemas.android.com/apk/res/android" android:orientation=" vertical" android:layout_width=" match_parent" android:layout_height=" match_parent" > < Button android:id=" @+id/button" android:layout_width=" match_parent" android:layout_height=" wrap_content" android:text=" I am a button." android:textAllCaps=" false" android:textColor=" #ff0000" /> < /LinearLayout>

android常用控件和布局

文章图片

可以为button控件的点击事件注册一个监听器:
import android.view.View; import android.widget.Button; import android.widget.Toast; public class MainActivity extends AppCompatActivity {@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button = (Button)findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(MainActivity.this, " You clicked the button" , Toast.LENGTH_SHORT).show(); } }); } }

android常用控件和布局

文章图片

??当然了,如果觉得使用匿名内部类的方式来注册监听器不是很直观,也可以使用实现View.OnClickListener接口的方法来注册事件监听。
import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.Toast; public class MainActivity extends AppCompatActivity implements View.OnClickListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button = (Button) findViewById(R.id.button); button.setOnClickListener(this); }@Override public void onClick(View v) { switch (v.getId()) { case R.id.button: Toast.makeText(MainActivity.this, " You clicked the button" , Toast.LENGTH_SHORT).show(); break; default: break; } } }

android常用控件和布局

文章图片

EditText
< ?xml version=" 1.0" encoding=" utf-8" ?> < LinearLayout xmlns:android=" http://schemas.android.com/apk/res/android" android:orientation=" vertical" android:layout_width=" match_parent" android:layout_height=" match_parent" > < !-- hint表示输入框中的一段提示性文本 --> < EditText android:id=" @+id/edit_text" android:layout_width=" match_parent" android:layout_height=" wrap_content" android:hint=" Type something here!" android:maxLines=" 2" /> < !-- maxLines表示输入框中可向下拓展的最大行数,超过这个行数则会产生滚动 --> < /LinearLayout>

android常用控件和布局

文章图片

可以结合按钮和输入框来做一些事情:
public class MainActivity extends AppCompatActivity implements View.OnClickListener { private EditText editText; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button = (Button) findViewById(R.id.button); editText = (EditText) findViewById(R.id.edit_text); button.setOnClickListener(this); }@Override public void onClick(View v) { switch(v.getId()) { case R.id.button: // 在按钮的点击事件处理函数中得到输入框的输入并以toast的形式显示出来 String inputText = editText.getText().toString(); Toast.makeText(MainActivity.this, inputText, Toast.LENGTH_SHORT).show(); break; default: break; } } }

android常用控件和布局

文章图片

ImageView
< ?xml version=" 1.0" encoding=" utf-8" ?> < LinearLayout xmlns:android=" http://schemas.android.com/apk/res/android" android:orientation=" vertical" android:layout_width=" match_parent" android:layout_height=" match_parent" > < ImageView android:id=" @+id/img1" android:layout_width=" wrap_content" android:layout_height=" wrap_content" android:src=https://www.songbingjia.com/android/" @drawable/img_1" /> < Button android:id=" @+id/button" android:layout_width=" match_parent" android:layout_height=" wrap_content" android:text=" I am a button." android:textAllCaps=" false" android:textColor=" #ff0000" /> < /LinearLayout>

android常用控件和布局

文章图片

可以在程序中通过代码动态的更改ImageView中的图片,修改MainActivity的代码:
public class MainActivity extends AppCompatActivity implements View.OnClickListener { private ImageView img1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button = (Button) findViewById(R.id.button); img1= (ImageView) findViewById(R.id.img1); button.setOnClickListener(this); }@Override public void onClick(View v) { switch(v.getId()) { case R.id.button: // 点击按钮后改变图片 img1.setImageResource(R.drawable.img_2); break; default: break; } } }

android常用控件和布局

文章图片

ProgressBar
< ?xml version=" 1.0" encoding=" utf-8" ?> < LinearLayout xmlns:android=" http://schemas.android.com/apk/res/android" android:orientation=" vertical" android:layout_width=" match_parent" android:layout_height=" match_parent" > < Button android:id=" @+id/button" android:layout_width=" match_parent" android:layout_height=" wrap_content" android:text=" I am button." android:textAllCaps=" false" android:textColor=" #ff0000" /> < ProgressBar android:id=" @+id/progress_bar" android:layout_width=" match_parent" android:layout_height=" wrap_content" /> < /LinearLayout>

android常用控件和布局

文章图片

??这时我们可能会注意到一个问题,旋转的进度条表示程序正在加载数据,而数据总会有加载完的时候,如何让进度条在数据加载完成后就消失呢?

??这就需要用到android:visibility控件可见属性进行指定,它的可选值有3种:visible,invisible和gone。visible表示控件是可见的,是默认值;invisible表示控件不可见,但它仍然会占据着原来的位置,可以理解为控件变为全透明状态了;gone则表示控件不仅不可见,而且不会在占用任何屏幕控件。

??除了可以直接设置控件的xml属性android:visibility来指定控件的可见性,还可以在代码中使用setVisibility()方法指定控件的可见与否,可以向它传入View.VISIBLE,View.INVISIBLE和View.GONE这3个值。
接下来我们就来实现当数据加载完成后进度条消失的效果:
public class MainActivity extends AppCompatActivity implements View.OnClickListener { private Button button; private ProgressBar progressBar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button = (Button) findViewById(R.id.button); progressBar = (ProgressBar) findViewById(R.id.progress_bar); button.setOnClickListener(this); }@Override public void onClick(View v) { switch (v.getId()) { case R.id.button: // 通过getVisibility()来判断当前进度条是否可见 if(progressBar.getVisibility() == View.GONE) { progressBar.setVisibility(View.VISIBLE); } else { progressBar.setVisibility(View.GONE); } break; default: break; } } }

android常用控件和布局

文章图片

另外,默认情况下,进度条是圆形样式,可以使用style属性将它指定为水平进度条:
< LinearLayout xmlns:android=" http://schemas.android.com/apk/res/android" android:orientation=" vertical" android:layout_width=" match_parent" android:layout_height=" match_parent" > ...< ProgressBar android:id=" @+id/progress_bar" android:layout_width=" match_parent" android:layout_height=" wrap_content" style=" ?android:attr/progressBarStyleHorizontal" android:max=" 100" /> < !-- 给进度条指定max最大值100 --> < /LinearLayout>

android常用控件和布局

文章图片

将进度条改为水平进度条后,我们就可以在程序中动态的更新进度条的进度值:
public class MainActivity extends AppCompatActivity implements View.OnClickListener { private Button button; private ProgressBar progressBar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button = (Button) findViewById(R.id.button); progressBar = (ProgressBar) findViewById(R.id.progress_bar); button.setOnClickListener(this); }@Override public void onClick(View v) { switch (v.getId()) { case R.id.button: // 使用getProgress()获取当前的进度值 int progress = progressBar.getProgress(); progress = progress + 10; progressBar.setProgress(progress); break; default: break; } } }

android常用控件和布局

文章图片

AlertDialog??AlertDialog可以在当前的界面中弹出一个对话框,这个对话框是置顶于所有界面元素之上的,能够屏蔽掉其他控件的交互能力(模态窗口)。因此AlertDialog一般用于提示一些非常重要的内容或警告信息。
下面我们来看看怎么使用AlertDialog控件:
import android.content.DialogInterface; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.*; public class MainActivity extends AppCompatActivity implements View.OnClickListener {@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button = (Button) findViewById(R.id.button); button.setOnClickListener(this); }@Override public void onClick(View v) { switch (v.getId()) { case R.id.button:// 点击事件是由R.id.button发起的 // 首先构造一个AlertDialog控件对象 AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this); dialog.setTitle(" This is a 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(); break; default: break; } } }

android常用控件和布局

文章图片

ProgressDialog??ProgressDialog和AlertDialog有点类似,都可以在界面上弹出一个对话框并屏蔽其他控件的交互能力。但不同的是,ProgressDialog会在对话框中显示一个进度条,一般用于表示当前操作比较耗时,让用户耐心的等待。
它的用法和AlertDialog很类似:
import android.app.ProgressDialog; import android.content.DialogInterface; import android.os.Bundle; import android.view.View; import android.widget.*; public class MainActivity extends AppCompatActivity implements View.OnClickListener {@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button = (Button) findViewById(R.id.button); button.setOnClickListener(this); }@Override public void onClick(View v) { switch (v.getId()) { case R.id.button: // 首先构造一个AlertDialog控件对象 ProgressDialog progressDialog = new ProgressDialog(MainActivity.this); progressDialog.setTitle(" This is a Dialog" ); progressDialog.setMessage(" Something important." ); progressDialog.setCancelable(true); // 允许取消progressDialog.setOnDismissListener(new DialogInterface.OnDismissListener() { @Override public void onDismiss(DialogInterface dialog) { Toast.makeText(MainActivity.this, " 你点击了取消" , Toast.LENGTH_SHORT).show(); } }); // 显示对话框 progressDialog.show(); break; default: break; } } }

android常用控件和布局

文章图片

ListView??ListView应该可以算是Android中最常用的控件之一,几乎所有的应用程序都会用到它。
??由于手机屏幕空间是有限的,所以能够一次性在屏幕上显示的内容并不多,当我们的程序中有大量的数据需要展示的时候,就可以借助ListView来实现。

??ListView允许用户通过手指上下滑动的方式将屏幕外的数据滚动到屏幕内,同时屏幕上原有的数据则会滚动出屏幕。事实上,我们几乎每天都在接触这个控件,比如查看QQ聊天记录,翻阅微博最新消息,等等。
ListView的简单用法
首先给程序一个布局:
< LinearLayout xmlns:android=" http://schemas.android.com/apk/res/android" android:layout_width=" match_parent" android:layout_height=" match_parent" > < ListView android:id=" @+id/list_view" android:layout_width=" match_parent" android:layout_height=" match_parent" /> < /LinearLayout>

在xml布局中加入ListView还算简单,下面看一看MainActivity中的代码:
public class MainActivity extends AppCompatActivity { private String[] data = https://www.songbingjia.com/android/{ " Apple" , " Banana" , " Orange" , " Watermelon" , " Pear" , " Grape" , " Pineapple" , " Strawberry" , " Cherry" , " Mango" , " Apple" , " Banana" , " Orange" , " Watermelon" , " Pear" , " Grape" , " Pineapple" , " Strawberry" , " Cherry" , " Mango" }@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 定义一个数组适配器adapter(上述数组中的元素都是字符串) ArrayAdapter< String> adapter = new ArrayAdapter< String> (MainActivity.this, android.R.layout.simple_list_item_1, data); // 使用android.R.layout.simple_list_item_1, data作为ListView子项布局的id,这是一个Android内置的布局文件,里面只有一个TextView,可用于简单地显示一段文本 ListView listView = (ListView) findViewById(R.id.list_view); // listView应用这个适配器 listView.setAdapter(adapter); } }

??ListView中的展示数据可以是从数据库中读取出来的,也可以是从网上下载下来的,这里我们就简单使用一个data数组来测试。
android常用控件和布局

文章图片

定制ListView界面
只能显示一段文本的ListView实在是太单调了,我们可以对ListView做一些个性化的定制。
下面的例子中,我们要在每个列表项前面加上一张图片。
首先创建一个实体类,作为ListView适配器的适配类型。新建类Fruit:
public class Fruit { private String name; // 水果的名称 private int imageId; // 对应的图片的资源idpublic Fruit(String name, int imageId) { this.name = name; this.imageId = imageId; }public String getName() { return name; }public int getImageId() { return imageId; } }

然后需要为ListView子项指定一个我们自定义的布局,新建fruit_item.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" > < !-- ListView中的每一项都对应有一个固定的布局文件,前面我们使用的是内置的android.R.layout.simple_list_item_1.xml, 这里为了将图片和水果名称字符串都放在ListView中的一项中,我们使用自定义布局文件 --> < 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_vertical" android:layout_marginLeft=" 10dp" /> < /LinearLayout>

接下来就是最重要的,我们要创建自定义的适配器,当前,它要继承ArrayAdapter。新建类FruitAdapter:
import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.TextView; import java.util.List; public class FruitAdapter extends ArrayAdapter< Fruit> { private int resourceId; public FruitAdapter(Context context,int textViewResourceId,List< Fruit> objects) { // 可见,我们的自定义适配器FruitAdapter,在真正的适配部分其实还是调用的ArrayAdapter父类的构造方法 super(context, textViewResourceId, objects); resourceId = textViewResourceId; }@Override // 重写ArrayAdapter的getView()方法,这个方法在每个子项滚动到屏幕内时会自动调用 public View getView(int position,View convertView,ViewGroup parent) { Fruit fruit = getItem(position); // 获取当前项的Fruit实例 // 为每个子项加载我们传入的布局 View view = LayoutInflater.from(getContext()).inflate(resourceId, parent, false); 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; } }

最后一步,就是更改MainActivity中的代码了:
import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; 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 {private List< Fruit> fruitList = new ArrayList< Fruit> (); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initFruits(); // 初始化水果数据,初始化fruitList[ ] FruitAdapter adapter = new FruitAdapter(MainActivity.this, R.layout.fruit_item, fruitList); ListView listView = (ListView) findViewById(R.id.list_view); listView.setAdapter(adapter); // 设定适配器 // 为ListView中的每一项都添加一个点击事件监听器 listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView< ?> parent, View view, int position, long id) { Fruit fruit = fruitList.get(position); // 得到点击位置处显示的对应fruitList中的元素 Toast.makeText(MainActivity.this, fruit.getName(), Toast.LENGTH_SHORT).show(); } }); }private void initFruits() { // fruitList列表中的每一项内容都是Fruit类型 for (int i = 0; i < 2; i++) {// 添加两遍(凑数) Fruit apple = new Fruit(" Apple" , R.drawable.apple_pic); fruitList.add(apple); Fruit banana = new Fruit(" Banana" , R.drawable.banana_pic); fruitList.add(banana); Fruit orange = new Fruit(" Orange" , R.drawable.orange_pic); fruitList.add(orange); Fruit watermelon = new Fruit(" Watermelon" , R.drawable.watermelon_pic); fruitList.add(watermelon); Fruit pear = new Fruit(" Pear" , R.drawable.pear_pic); fruitList.add(pear); Fruit grape = new Fruit(" Grape" , R.drawable.grape_pic); fruitList.add(grape); Fruit pineapple = new Fruit(" Pineapple" , R.drawable.pineapple_pic); fruitList.add(pineapple); Fruit strawberry = new Fruit(" Strawberry" , R.drawable.strawberry_pic); fruitList.add(strawberry); Fruit cherry = new Fruit(" Cherry" , R.drawable.cherry_pic); fruitList.add(cherry); Fruit mango = new Fruit(" Mango" , R.drawable.mango_pic); fruitList.add(mango); } } }

android常用控件和布局

文章图片

android常用控件和布局

文章图片

RecyclerView??ListView的功能是非常强大的,但也并不是没有缺点,如果我们不使用一些技巧来提示它的运行效率,那么它的性能会非常差。还有,ListView的扩展性也不够好,它只能实现纵向滚动的效果,如果想实现横向滚动的话,ListView就无能为力了。
??为此,Android提供了一个更强大的滚动控件——RecycleView
布局 线性布局LinearLayout线性布局内控件按水平或垂直方向顺次排布。
< !-- android命名空间只需要在最顶层的布局中声明一次 --> < LinearLayout xmlns:android=" http://schemas.android.com/apk/res/android" android:layout_width=" match_parent" android:layout_height=" match_parent" android:orientation=" vertical" > < Button android:id=" @+id/btn1" android:layout_width=" match_parent" android:layout_height=" wrap_content" android:text=" I am btn1." android:textAllCaps=" false" android:textColor=" #ff0000" /> < Button android:id=" @+id/btn2" android:layout_width=" match_parent" android:layout_height=" wrap_content" android:text=" I am btn2." android:textAllCaps=" false" android:textColor=" #ff0000" /> < Button android:id=" @+id/btn3" android:layout_width=" match_parent" android:layout_height=" wrap_content" android:text=" I am btn3." android:textAllCaps=" false" android:textColor=" #ff0000" /> < Button android:id=" @+id/btn4" android:layout_width=" match_parent" android:layout_height=" wrap_content" android:text=" I am button4." android:textAllCaps=" false" android:textColor=" #ff0000" /> < LinearLayout xmlns:android=" http://schemas.android.com/apk/res/android" android:layout_width=" match_parent" android:layout_height=" match_parent" android:orientation=" horizontal" android:gravity=" center" > < !-- 嵌套布局 --> < Button android:id=" @+id/btn5" android:layout_width=" wrap_content" android:layout_height=" wrap_content" android:text=" I am btn5" android:textAllCaps=" false" android:textColor=" #0000ff" /> < Button android:id=" @+id/btn6" android:layout_width=" wrap_content" android:layout_height=" wrap_content" android:text=" I am btn6" android:textAllCaps=" false" android:textColor=" #0000ff" /> < Button android:id=" @+id/btn7" android:layout_width=" wrap_content" android:layout_height=" wrap_content" android:text=" I am btn7" android:textAllCaps=" false" android:textColor=" #0000ff" /> < Button android:id=" @+id/btn8" android:layout_width=" wrap_content" android:layout_height=" wrap_content" android:text=" I am btn8" android:textAllCaps=" false" android:textColor=" #0000ff" /> < /LinearLayout> < /LinearLayout>

android常用控件和布局

文章图片

相对布局RelativeLayout相对布局可以通过相对定位的方式让控件出现在布局的任意位置上。
< ?xml version=" 1.0" encoding=" utf-8" ?> < RelativeLayout xmlns:android=" http://schemas.android.com/apk/res/android" xmlns:tools=" http://schemas.android.com/tools" android:layout_width=" match_parent" android:layout_height=" match_parent" > < Button android:id=" @+id/btn1" android:layout_width=" wrap_content" android:layout_height=" wrap_content" android:layout_alignParentLeft=" true" android:layout_alignParentTop=" true" android:text=" button 1" /> < Button android:id=" @+id/btn2" android:layout_width=" wrap_content" android:layout_height=" wrap_content" android:layout_alignParentRight=" true" android:layout_alignParentTop=" true" android:text=" button 2" /> < Button android:id=" @+id/btn3" android:layout_width=" wrap_content" android:layout_height=" wrap_content" android:layout_centerInParent=" true" android:text=" button 3" /> < Button android:id=" @+id/btn4" android:layout_width=" wrap_content" android:layout_height=" wrap_content" android:layout_alignParentBottom=" true" android:layout_alignParentLeft=" true" android:text=" button 4" /> < !-- 其内控件可相对于其他控件或父容器排列 --> < /RelativeLayout>

android常用控件和布局

文章图片

帧布局FrameLayout帧布局内所有控件默认都会摆放在布局的左上角。
< FrameLayout xmlns:android=" http://schemas.android.com/apk/res/android" android:layout_width=" match_parent" android:layout_height=" match_parent" > < TextView android:id=" @+id/text" android:layout_width=" wrap_content" android:layout_height=" wrap_content" android:text=" This is TextView" /> < ImageView android:id=" @+id/img" android:layout_width=" wrap_content" android:layout_height=" wrap_content" android:src=https://www.songbingjia.com/android/" @mipmap/ic_launcher" /> < /FrameLayout>

android常用控件和布局

文章图片

百分比布局PercentFrameLayout和PercentRelativeLayout??前面提到的LinearLayout,RelativeLayout和FrameLayout都是从Android 1.0版本就开始支持了,一直沿用到现在,可以说是满足了绝大多数场景的界面设计需求。不过细心的你还是可以发现,除了LinearLayout支持使用layout_weight属性来实现按比例指定控件大小的功能外,其余两种布局都不支持。比如说如果要使用RelativeLayout来实现让两个按钮平分布局宽度的效果是很困难的。
??为此,Android引入了一种全新的布局方式来解决该问题——百分比问题。在这种布局中,我们可以不再使用wrap_content,match_parent等方式来指定控件的大小,而是允许直接指定控件在布局中所占的百分比,这样一来,就可以轻松实现平分布局甚至是任意比例分割布局的效果。
【android常用控件和布局】??由于LinearLayout本身已经支持按比例指定控件大小了,因此百分比布局只为FrameLayout和RelativeLayout进行了功能扩展,提供了PercentFrameLayout和PercentRelativeLayout这两个全新的布局。
??android团队将百分比布局定义在了support库中,只需在build.gradle中添加百分比布局库的依赖,就能保证百分比布局在所有系统版本上都可以使用。在build.gradle(Module:app)中添加一行:
dependencies { implementation ' com.android.support:percent:28.0.0' }

然后就可以使用百分比布局了,因为百分比布局不是直接内置在SDK中的,所以要写出完整的包名。
< android.support.percent.PercentFrameLayout xmlns:android=" http://schemas.android.com/apk/res/android" xmlns:app=" http://schemas.android.com/apk/res-auto" android:layout_width=" match_parent" android:layout_height=" match_parent" > < Button android:id=" @+id/button1" android:text=" Button 1" android:layout_gravity=" left|top" app:layout_widthPercent=" 50%" app:layout_heightPercent=" 50%" /> < Button android:id=" @+id/button2" android:text=" Button 2" android:layout_gravity=" right|top" app:layout_widthPercent=" 50%" app:layout_heightPercent=" 50%" /> < Button android:id=" @+id/button31" android:text=" Button 3" android:layout_gravity=" left|bottom" app:layout_widthPercent=" 50%" app:layout_heightPercent=" 50%" /> < Button android:id=" @+id/button4" android:text=" Button 4" android:layout_gravity=" right|bottom" app:layout_widthPercent=" 50%" app:layout_heightPercent=" 50%" /> < /android.support.percent.PercentFrameLayout>

android常用控件和布局

文章图片

表格布局TableLayout
< TableLayout xmlns:android=" http://schemas.android.com/apk/res/android" android:layout_width=" match_parent" android:layout_height=" match_parent" android:stretchColumns=" 1" > < !-- 如果某一行控件的总宽不能铺满父容器,则拉伸第一列以适应屏幕宽度 --> < TableRow> < !-- TableRow内无法为控件指定宽度 --> < TextView android:layout_height=" wrap_content" android:text=" Account:" /> < EditText android:id=" @+id/account" android:layout_height=" wrap_content" android:hint=" Input your account" /> < /TableRow> < TableRow> < TextView android:layout_height=" wrap_content" android:text=" Password:" /> < EditText android:id=" @+id/password" android:layout_height=" wrap_content" android:inputType=" numberPassword" /> < /TableRow> < TableRow> < CheckBox android:id=" @+id/remember_pass" android:layout_height=" wrap_content" /> < TextView android:layout_height=" wrap_content" android:text=" remember_password" /> < /TableRow> < TableRow> < Button android:id=" @+id/login" android:layout_height=" wrap_content" android:layout_span=" 2" android:text=" login" /> < /TableRow> < /TableLayout>

android常用控件和布局

文章图片

创建自定义控件??所有控件都是直接或间接继承View的,所用的所有部件都直接或间接继承ViewGroup。View是Android中最基本的一种UI组件,它可以在屏幕上绘制一块矩形区域,并能响应这块区域的各种事件。

??因此,我们平常所用的各种组件实际上就是在View的基础上有添加了各自特有的功能。而ViewGroup可以看做是一种特殊的View,它可以包含很多子View和子ViewGroup,是一个用于放置控件和布局的容器。
android常用控件和布局

文章图片

引入布局当系统自带的控件不能满足我们的需求时,可以根据上面的继承关系来实现我们的自定义控件。
下面我们来自定义一个标题栏。
首先新建一个布局title.xml,这是用于actionBar的布局文件。
< ?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: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=" 5dp" android:background=" @drawable/back_bg" android:text=" Back" android:textColor=" #fff" /> < TextView android:id=" @+id/title_text" android:layout_width=" 0dp" 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=" 5dp" android:background=" @drawable/edit_bg" android:text=" Edit" android:textColor=" #fff" /> < /LinearLayout>

然后将这个布局引入到主布局文件activity_main.xml中(使用include标签):
< ?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" > < include layout=" @layout/title" /> < /LinearLayout>

可以在app中的每一个布局中引入title.xml,这样每个页面就都拥有我们自定义的标题栏了。
另外,由于android系统自带有标题栏,所以要将自带的标题栏隐藏掉:
public class MainActivity extends AppCompatActivity {@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ActionBar titleBar = getSupportActionBar(); if(titleBar != null) titleBar.hide(); } }

android常用控件和布局

文章图片

back_bg.png edit_bg.png title_bg.png
android常用控件和布局

文章图片
android常用控件和布局

文章图片
android常用控件和布局

文章图片
自定义控件??上面的例子中,我们通过引入布局文件,创建了自定义的标题栏。但还是有一个问题,我们要在每个活动中为这些控件单独编写一次事件注册的代码。比如说标题栏返回按钮的Back功能,但事实上,这些功能在每个活动都是一样的实现逻辑。为了避免在每个活动中都注册一遍按钮的点击事件,我们最好使用自定义控件。
新建java类TitleLayout,继承自LinearLayout类:
android常用控件和布局

文章图片

public class TitleLayout extends LinearLayout {public TitleLayout(Context context, AttributeSet attrs) { // 将xml中设置的一堆属性全部传给父类LinearLayout的构造函数 super(context, attrs); // 使用from()加载布局title.xml,父布局是TitleLayout本身 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控件即返回按钮添加事件监听 titleBack.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { ((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中使用TitleLayout布局,由于TitleLayout是我们自定义的,没有内置在SDK中,所以我们在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" > < com.example.uiwidgetdemo.TitleLayout android:layout_width=" match_parent" android:layout_height=" wrap_content" > < /com.example.uiwidgetdemo.TitleLayout> < /LinearLayout>

android常用控件和布局

文章图片


    推荐阅读