Home | 简体中文 | 繁体中文 | 杂文 | Github | 知乎专栏 | Facebook | Linkedin | Youtube | 打赏(Donations) | About
知乎专栏

116.2. 样式布局

116.2.1. ConstraintLayout

116.2.1.1. 父容器定位

在相对布局中,可以通过以下的属性让的组合让控件处于父容器左上角、右上角、左下角、右下角、上下左右居中,正居中等九个位置。属性如下:

		
android:layout_alignParentLeft="true" 	父容器左边
android:layout_alignParentRight="true" 	父容器右边
android:layout_alignParentTop="true" 	父容器顶部
android:layout_alignParentBottom="true" 父容器底部
android:layout_centerHorizontal="true" 	水平方向居中
android:layout_centerVertical="true" 	垂直方向居中
android:layout_centerInParent="true" 	水平垂直都居中
		
			
		
android:layout_toLeftOf="@+id/button1" 	在button1控件左方
android:layout_toRightOf="@+id/button1" 在button1控件右方
android:layout_above="@+id/button1" 	在button1控件上方
android:layout_below="@+id/button1" 	在button1控件下方

android:layout_alignLeft="@+id/button1" 与button1控件左边平齐
android:layout_alignRight="@+id/button1" 	与button1控件右边平齐
android:layout_alignTop="@+id/button1" 	与button1控件上边平齐
android:layout_alignBottom="@+id/button1" 	与button1控件下边平齐		
		
			

116.2.1.2. 对齐布局

垂直/水平剧中

		
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />		
		
			

116.2.2. LinearLayout

116.2.2.1. 外边距设置

			
    android:layout_marginLeft="10dp"
    android:layout_marginTop="10dp"
    android:layout_marginRight="10dp"
    android:layout_marginBottom="10dp"
			
			

116.2.2.2. 内边距设置

			
    android:padding="10dp"
			
			

116.2.2.3. 水平剧中

android:gravity="center_horizontal"

			
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:gravity="center_horizontal"
                android:orientation="vertical">

                <TextView
                    android:id="@+id/textView"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="15dp"
                    android:text="唤醒词"
                    android:textColor="#70ffffff"
                    android:textSize="14sp" />

                <TextView
                    android:id="@+id/textView2"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="2dp"
                    android:text="小梅小梅"
                    android:textColor="#00F8C1"
                    android:textSize="24sp" />
            </LinearLayout>			
			
			

116.2.3. FrameLayout

116.2.3.1. FrameLayout 事件穿透

FrameLayout 浮动在另其他 UI 上方,点击 FrameLayout 某些问之,触发了下面的事件,解决方法是增加:

android:clickable="true"

			
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:RoundedCornerImageView="http://schemas.android.com/apk/res-auto"
    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"
    android:background="@color/transparent"
    tools:ignore="MissingDefaultResource"
    android:clickable="true">			
			
			

方法二

			
	mFrameLayout.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            return true;
        }
    });			
			
			

116.2.3.2. 叠加层

			
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
    android:foregroundGravity="left|top"
    tools:context=".BlankFragment">

    <TextView
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:background="@color/colorPrimary"
        android:gravity="bottom|right"
        android:text="第一层" />

    <TextView
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:background="@color/colorAccent"
        android:gravity="bottom|right"
        android:text="第二层" />

    <TextView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="@color/colorPrimaryDark"
        android:gravity="bottom|right"
        android:text="第三层" />

</FrameLayout>			
			
			

116.2.4. 动画

参数

  • android:oneshot 代表播放次数 true 只展示一遍,设置为false会不停的循环播放动画
  • android:duration 表示展示所用的该图片的时间长度
		
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="true">

    <item
        android:drawable="@drawable/hotel1"
        android:duration="150" />
    <item
        android:drawable="@drawable/hotel2"
        android:duration="150" />
    <item
        android:drawable="@drawable/hotel3"
        android:duration="150" />
    <item
        android:drawable="@drawable/hotel4"
        android:duration="150" />
    <item
        android:drawable="@drawable/hotel5"
        android:duration="150" />
</animation-list>
		
		

		
	<ImageView
    android:id="@+id/load_image"
    android:layout_width="25dp"
    android:layout_height="25dp"
    android:layout_gravity="center_vertical"
    android:scaleType="centerCrop"
    android:src="@drawable/loading_anim_image" />		
		
		

		
    ImageView imageView = findViewById(R.id.imageView);
    animationDrawable = (AnimationDrawable) imageView.getDrawable();
    //直接就开始执行,性能不是最佳的。
    animationDrawable.start();		
		
		

116.2.5. 声音波形图

		
package cn.netkiller.album.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;

public class SoundWaveView extends View {
    private Paint paint;
    private float[] amplitudes;

    public SoundWaveView(Context context) {
        super(context);
        init();
    }

    public SoundWaveView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        paint = new Paint();
        paint.setColor(Color.BLUE);
        paint.setStrokeWidth(2);
    }

    public void setAmplitudes(float[] amplitudes) {
        this.amplitudes = amplitudes;
        invalidate(); // 刷新视图
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (amplitudes == null) {
            return;
        }

        int width = getWidth();
        int height = getHeight();
        int centerY = height / 2;

        for (int i = 0; i < amplitudes.length; i++) {
            float x = width * i / amplitudes.length;
            float y = centerY + amplitudes[i] * centerY;
            canvas.drawLine(x, centerY, x, y, paint);
        }
    }
}
		
		
		

		
public class MainActivity extends AppCompatActivity {
    private SoundWaveView soundWaveView;
    private AudioRecord audioRecord;
    private boolean isRecording = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        soundWaveView = findViewById(R.id.sound_wave_view);
        int bufferSize = AudioRecord.getMinBufferSize(44100, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
        audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, 44100, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize);

        startRecording();
    }

    private void startRecording() {
        isRecording = true;
        audioRecord.startRecording();

        new Thread(new Runnable() {
            @Override
            public void run() {
                short[] buffer = new short[1024];
                while (isRecording) {
                    int read = audioRecord.read(buffer, 0, buffer.length);
                    if (read > 0) {
                        float[] amplitudes = new float[read];
                        for (int i = 0; i < read; i++) {
                            amplitudes[i] = buffer[i] / 32768f; // 归一化为[-1, 1]
                        }
                        soundWaveView.setAmplitudes(amplitudes);
                    }
                }
                audioRecord.stop();
            }
        }).start();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        isRecording = false;
    }
}		
		
		

		
<com.example.myapplication.SoundWaveView
    android:id="@+id/sound_wave_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />