目录
Android FrameLayout ( 帧布局 )
FrameLayout size 大小
FrameLayout 属性
Android GridLayout ( 网格布局 )
GridLayout 属性
计算器布局
Android AbsoluteLayout 绝对布局
AbsoluteLayout 四大控制属性
FrameLayout 是 Android 中的一个布局容器,用于在单个视图中显示一个子视图。它是一种简单的布局,所有的子视图都位于屏幕的左上角,并且彼此重叠。
FrameLayout 主要用于显示单个子视图或在子视图之间进行切换,例如用于片段(Fragments)的容器或者在底部显示一个浮动的按钮。
FrameLayout (帧布局) 有一个缺点就是没有任何的定位方式,所以应用的场景并不多。
在 FrameLayout 中,它的大小通常由其最大的子控件决定。如果子控件的大小相同,那么后面添加的子控件会覆盖在前面的子控件之上。这种特性使得 FrameLayout 适用于显示单一视图或在不同的子视图之间进行切换的场景。
另外,FrameLayout 默认将子控件放置在左上角。可以通过 android:layout_gravity 属性来指定子控件的位置,将其放置在不同的位置。
android:layout_gravity 是一个布局参数,用于指定一个视图在其父容器中的对齐方式或者在 FrameLayout 中的重叠方式。该属性的值是一个位掩码,可以同时指定多个对齐方式。
以下是一些常用的 android:layout_gravity 的属性值及其含义:
以下是一个简单的示例,演示了 FrameLayout 中使用 android:layout_gravity 属性的情况:
运行结果:
FrameLayout 只有两个自有属性,它们分别是:
1、android:foreground:
2、android:foregroundGravity:
范例
运行结果:
趣味实例
随手指点击而移动的图片
activity_main.xml
MainActivity.java
package com.example.myapplication;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.FrameLayout;
import android.app.Activity;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FrameLayout frame = (FrameLayout) findViewById(R.id.mylayout);
final MeiMeiView meimei = new MeiMeiView(MainActivity.this);
//为我们的妹子添加触摸事件监听器
meimei.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent event) {
//设置妹子显示的位置
meimei.bitmapX = event.getX() - 150;
meimei.bitmapY = event.getY() - 150;
//调用重绘方法
meimei.invalidate();
return true;
}
});
frame.addView(meimei);
}
}
MeiMeiView.java
package com.example.myapplication;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.view.View;
public class MeiMeiView extends View {
//定义相关变量,依次是妹子显示位置的X,Y坐标
public float bitmapX;
public float bitmapY;
public MeiMeiView(Context context) {
super(context);
//设置妹子的起始坐标
bitmapX = 0;
bitmapY = 200;
}
//重写View类的onDraw()方法
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//创建,并且实例化 Paint 的对象
Paint paint = new Paint();
//根据图片生成位图对象
Bitmap bitmap = BitmapFactory.decodeResource(this.getResources(), R.drawable.meimei);
//绘制妹子
canvas.drawBitmap(bitmap, bitmapX, bitmapY,paint);
//判断图片是否回收,木有回收的话强制收回图片
if(bitmap.isRecycled())
{
bitmap.recycle();
}
}
}
GridLayout 是 Android 中一种非常灵活的布局容器,允许您以网格形式排列子视图。相比于 TableLayout,GridLayout 提供了更多的灵活性和自定义性。
GridLayout 的主要特性:
1、排列方式:
2、设置网格布局的行和列:
3、设置组件所在的行或列:
4、设置组件跨越的行和列:
GridLayout 布局最经典的就是 计算器 了,这是一个天然的网格布局。
下面是具体代码:
activity_main.xml
MainActivity.java
package com.example.myapplication;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
private TextView displayTextView;
private StringBuilder currentInput;
private double operand1, operand2;
private char operator;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 初始化变量
displayTextView = findViewById(R.id.displayTextView);
currentInput = new StringBuilder();
// 为数字按钮设置点击侦听器
setNumberButtonClickListener(R.id.button0);
setNumberButtonClickListener(R.id.button1);
setNumberButtonClickListener(R.id.button2);
setNumberButtonClickListener(R.id.button3);
setNumberButtonClickListener(R.id.button4);
setNumberButtonClickListener(R.id.button5);
setNumberButtonClickListener(R.id.button6);
setNumberButtonClickListener(R.id.button7);
setNumberButtonClickListener(R.id.button8);
setNumberButtonClickListener(R.id.button9);
// 为操作按钮设置点击侦听器
setOperatorButtonClickListener(R.id.buttonPlus, '+');
setOperatorButtonClickListener(R.id.buttonMinus, '-');
setOperatorButtonClickListener(R.id.buttonMultiply, '*');
setOperatorButtonClickListener(R.id.buttonDivide, '/');
// 为清除按钮设置点击侦听器
findViewById(R.id.buttonClear).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
clearDisplay();
}
});
// 为退回按钮设置点击侦听器
findViewById(R.id.buttonBack).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
removeLastDigit();
}
});
// 设置等于按钮的点击监听器
findViewById(R.id.buttonEquals).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
performCalculation();
}
});
// 设置点按钮的点击监听器
findViewById(R.id.buttonDot).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
appendDot();
}
});
}
private void setNumberButtonClickListener(int buttonId) {
Button button = findViewById(buttonId);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
appendDigit(button.getText().toString());
}
});
}
private void setOperatorButtonClickListener(int buttonId, final char operator) {
Button button = findViewById(buttonId);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
setOperator(operator);
}
});
}
private void appendDigit(String digit) {
currentInput.append(digit);
updateDisplay();
}
private void appendDot() {
if (!currentInput.toString().contains(".")) {
currentInput.append(".");
updateDisplay();
}
}
private void setOperator(char op) {
if (currentInput.length() > 0) {
operand1 = Double.parseDouble(currentInput.toString());
operator = op;
clearDisplay();
}
}
private void performCalculation() {
if (currentInput.length() > 0) {
operand2 = Double.parseDouble(currentInput.toString());
double result = 0;
switch (operator) {
case '+':
result = operand1 + operand2;
break;
case '-':
result = operand1 - operand2;
break;
case '*':
result = operand1 * operand2;
break;
case '/':
if (operand2 != 0) {
result = operand1 / operand2;
} else {
// 处理除以零
clearDisplay();
displayTextView.setText("Error");
return;
}
break;
}
clearDisplay();
currentInput.append(result);
updateDisplay();
}
}
private void removeLastDigit() {
if (currentInput.length() > 0) {
currentInput.deleteCharAt(currentInput.length() - 1);
updateDisplay();
}
}
private void clearDisplay() {
currentInput.setLength(0);
updateDisplay();
}
private void updateDisplay() {
displayTextView.setText(currentInput.toString());
}
}
注意: 如果想要让某个组件填满横越过的行或列,需要添加属性: android:layout_gravity = "fill"。
在Android中,AbsoluteLayout 是一种布局方式,它允许你使用绝对坐标来指定子视图的位置。然而,需要注意的是,AbsoluteLayout 已经被弃用(deprecated)了,因为它存在一些问题,例如不同屏幕尺寸和密度可能导致布局混乱。
推荐使用更灵活的布局方式,如 RelativeLayout、LinearLayout、ConstraintLayout 等,以便更好地适应不同设备和屏幕尺寸。
在 Android 中,AbsoluteLayout 使用了四个主要的属性来控制子视图的位置和大小。这些属性如下:
例子:
尽管 AbsoluteLayout 已经被弃用,但还是可以提供一个示例,以演示其用法。请注意,为了更好的屏幕适应性和灵活性,强烈建议使用更现代的布局方式!!!!!!。如 ConstraintLayout 或 RelativeLayout。
运行结果: