View组件及UI界面控制方法

View及ViewGroup类介绍

简介

Android应用的所有UI组件都继承了View类,View组件非常类似于Swing编程中的JPanel,它代表了一个空白的矩形区域,View组件没有任何内容。对于Android应用的其它UI组件来说,它们都继承了View组件,然后在View组件提供的空白区域上绘制外观

Android采用了”组合器“设计模式来设计View和ViewGroup,ViewGroup作为View的重要子类,通用作为其它组件的容器使用


自定义组件的方法

当Android系统提供的UI组件不足以满足项目需要时,开发者可以通过继承View来派生自定义组件。在自定义组件时,通常被重写的方法(实际开发中只重写部分)如下:

  • 构造器。重写构造器是定制View的最基本方式,当Java代码创建一个View实例或根据XML布局文件加载并构建界面时将需要调用该构造器。
  • onFinishInflate()。当应用从XML布局文件加载该组件并利用它来构建界面之后,该方法就会被回调
  • onMeasure(int, int)。该方法用来检测View组件及它所包含的所有子组件的大小。
  • onLayout(boolean, int, int, int, int)。当该组件需要分配其子组件的位置、大小时,该方法就会被回调
  • onSizeChanged(int, int, int, int)。当该组件的大小被改变时回调该方法。
  • onDraw(Canvas)。当该组件将要绘制它的内容时回调该方法进行绘制。
  • onKeyDown(int, KeyEvent)。当某个键被按下时触发该方法。
  • onKeyUp(int, KeyEvent)。当松开某个键时触发该方法。
  • onTrackballEvent(MotionEvent)。当发生轨迹球事件时触发该方法
  • onTouchEvent(MotionEvent)。当发生触摸屏事件时触发该方法
  • onWindowFocusChanged(boolean)。当该组件得到、失去焦点时触发该方法。
  • onAttachedToWindow()。当把该组件放入某个窗口时触发该方法。
  • onDetachedFromWindow()。当把该组件从某个窗口上分离时触发该方法。
  • onWindowVisibilityChanged(int)。当包含该组件的窗口的可见性发生变化时触发该方法。

UI界面控制方法

Android推荐使用XML布局文件来定义用户界面,而不是使用Java代码来开发用户界面。Android中控制组件的方式有如下两种:

  • 在XML布局文件中通过XML属性进行控制。
  • 在Java程序代码中通过调用方法进行控制。

上述两种方法控制Android用户界面行为的本质是一样的,通常情况下,控制UI组件的XML属性还有对应的方法。下面就对这两种方法进行简单介绍:


使用XML布局文件控制UI界面

Android推荐使用XML布局文件来控制视图,这样不仅简单、明了,而且可以将应用的视图控制逻辑从Java代码中分离出来,更好地体现了MVC原则

当应用在res/layout目录下定义一个主文件名任意的XML布局文件之后,R.java会自动收录此布局资源。

setContentView(R.layout.<资源文件名字>) //在Activity中显示该视图

findViewById(R.id.<android.id属性值>) //通过ID获取UI组件,之后就可以通过代码来控制此UI组件的外观行为了(如为UI组件绑定事件监听器等)。

在代码中控制UI界面

如果希望代码中控制UI界面,我们可以完全抛弃XML布局文件 ,而将所有的UI组件都通过new关键字创建出来,然后以合适的方式”搭建“在一起即可。

public class CodeView extends Activity {
    //当第一次创建该Activity时回调该方法
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //创建一个线性布局管理器
        LinearLayout layout = new LinearLayout(this);
        //设置该Activity显示layout
        super.setContentView(layout);
        layout.setOrientation(LinearLayout.VERTICAL);
        //创建一个TextView
        final TextView show = new TextView(this);
        //创建一个按钮
        Button bn = new Button(this);
        bn.setText(R.string.ok);
        bn.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT));
        //向Layout容器中添加TextView
        layout.addView(show);
        //向Layout容器中添加按钮
        layout.addView(bn);
        //为按钮绑定一个事件监听器
        bn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                show.setText("Hello, Android, " + new java.util.Date());
            }
        });
    }
}

完全在代码中控制UI界面不仅不利于高层次的解耦,而且由于通过new关键字来创建UI组件,需要调用方法来设置UI组件的行为,因此代码也显得十分臃肿。相反,如果通过XML文件来控制UI界面,开发者只要在XML布局文件中使用标签即可创建UI组件,而且只要配置简单的属性即可控制UI组件的行为,因此要简单得多。


使用XML布局文件和Java代码混合控制UI界面

完全使用代码来控制UI界面不仅烦琐,而且不利于解耦;而完全利用XML布局文件来控制UI界面虽然方便、便捷,但难免有失灵活

当混合使用XML布局文件和代码来控制UI界面时,习惯上把变化 小、行为比较固定的组件放在XML布局文件中管理而那些变化较多、行为控制比较复杂的组件则交给Java代码来管理

我们可以通过先在布局文件中定义一个简单的线性布局容器,然后在程序获取该容器,并往该容器中添加组件。此程序的功能是周期性展示定义在drawable下面的图片,展示中触发切换的操作是点击当前图片。具体代码如下:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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="miss.picturewall.PictureWall">

    <LinearLayout
        android:id="@+id/root"
        android:layout_width="368dp"
        android:layout_height="495dp"
        android:orientation="vertical"
        tools:layout_editor_absoluteX="8dp"
        tools:layout_editor_absoluteY="8dp"></LinearLayout>
</android.support.constraint.ConstraintLayout>
public class PictureWall extends AppCompatActivity {
    //定义一个访问图片的数组
    int[] images = new int[]{
            R.drawable.jiajia,
            R.drawable.jiajia1,
            R.drawable.jiajia2,
            R.drawable.jiajia3,
            R.drawable.jiajia4,
            R.drawable.jiajia5
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        //获取LinearLayout布局容器
        LinearLayout main = (LinearLayout)findViewById(R.id.root);
        //程序创建ImageView组件
        final ImageView image = new ImageView(this);
        //将ImageView组件添加到LinearLayout布局容器中
        main.addView(image);
        //初始化时显示第一张图片
        image.setImageResource(images[0]);
        image.setOnClickListener(new View.OnClickListener() {
            int currentImg = 0;
            @Override
            public void onClick(View v) {
                currentImg = (currentImg + 1) % images.length;
                //改变ImageView里显示的图片
                image.setImageResource(images[currentImg]);
            }
        });
    }
}

自定义组件实例

一个小球跟随手指的程序。主要有以下三个文件

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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="miss.fingerball.CustomView">

    <LinearLayout
        android:id="@+id/root"
        android:layout_width="368dp"
        android:layout_height="495dp"
        android:orientation="vertical"
        tools:layout_editor_absoluteX="8dp"
        tools:layout_editor_absoluteY="8dp"></LinearLayout>
</android.support.constraint.ConstraintLayout>
public class BallView extends View {
    public float currentX = 40;
    public float currentY = 50;
    public BallView(Context context) {
        super(context);
    }
    @Override
    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //创建画笔
        Paint p = new Paint();
        //设置画笔颜色
        p.setColor(Color.RED);
        //绘制一个小球
        canvas.drawCircle(currentX, currentY, 15, p);
    }
}
public class CustomView extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        LinearLayout root = (LinearLayout)findViewById(R.id.root);
        //创建BallView组件
        final BallView ball = new BallView(this);
        //设置自定义组件的最小宽度、高度
        ball.setMinimumWidth(root.getWidth());
        ball.setMinimumHeight(root.getHeight());
        //为ball组件绑定Touch事件
        ball.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                //修改ball组件的currentX、currentY两个属性
                ball.currentX = event.getX();
                ball.currentY = event.getY();
                //通知ball组件重绘
                ball.invalidate();
                return true;
            }
        });
        root.addView(ball);
    }
}

摘自《疯狂Android讲义》

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值