"La primera línea de código" Capítulo 3: Desarrollo del diseño de la interfaz de usuario

1. Cómo usar los controles comunes

1, vista de texto

   <TextView
        android:id="@+id/text_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:textSize="24sp"
        android:textColor="#00ff00"
        android:text="文本"/>

Darse cuenta del efecto:
inserte la descripción de la imagen aquí

2, botón

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="按钮"
        android:textAllCaps="false"/>

Evento vinculante:

Button button1=(Button) findViewById(R.id.button);
button1.setOnClickListener(new View.OnClickListener() {
    
    
    @Override
    public void onClick(View view) {
    
    
        Intent intent=new Intent(FirstActivity.this,SecondActivity.class);
        startActivity(intent);
    }
});

3,Editar texto

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/edit_text"
        android:hint="请在这里输入字符"
        android:maxLines="2"/>

El botón muestra la ventana emergente de contenido:

        Button button1=(Button) findViewById(R.id.button);
        EditText editText=(EditText) findViewById(R.id.edit_text);
        button1.setOnClickListener(new View.OnClickListener() {
    
    
            @Override
            public void onClick(View view) {
    
    
                String inputText=editText.getText().toString();
                Toast.makeText(FirstActivity.this, inputText, Toast.LENGTH_SHORT).show();
            }
        });

4, vista de imagen

    <ImageView
        android:id="@+id/image_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/img_1"/>

Alternar imagen:

        Button button1=(Button) findViewById(R.id.button);
        ImageView imageView=(ImageView) findViewById(R.id.image_view);
        button1.setOnClickListener(new View.OnClickListener() {
    
    
            @Override
            public void onClick(View view) {
    
    
                    imageView.setImageResource(R.drawable.img_5);
            }
        });

La dirección del mapa:
inserte la descripción de la imagen aquí

5, barra de progreso ProgressBar

Barra de progreso circular:

    <ProgressBar
        android:id="@+id/progress_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

Controle la visibilidad de la barra de progreso circular:

 button1.setOnClickListener(new View.OnClickListener() {
    
    
     @Override
     public void onClick(View view) {
    
    
         //visible:可见,invisible,不可见但占位,gone不可见不占位
         //View.GONE是内置的常数
         if(progressBar.getVisibility()==View.GONE){
    
    
             progressBar.setVisibility(View.VISIBLE);
         }else{
    
    
             progressBar.setVisibility(View.GONE);
         }
     }
 });

Cambiar a una barra de progreso de barra larga:

    <ProgressBar
        android:id="@+id/progress_bar"
        style="?android:attr/progressBarStyleHorizontal"
        android:max="100"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

Establecer el progreso dinámicamente:

        ProgressBar progressBar=(ProgressBar) findViewById(R.id.progress_bar);
        button1.setOnClickListener(new View.OnClickListener() {
    
    
            @Override
            public void onClick(View view) {
    
    
                int progress=progressBar.getProgress();
                progress=progress+10;
                progressBar.setProgress(progress);
            }
        });

6, cuadro de diálogo AlertDialog

        button1.setOnClickListener(new View.OnClickListener() {
    
    
            @Override
            public void onClick(View view) {
    
    
                AlertDialog.Builder dialog=new AlertDialog.Builder(FirstActivity.this);
                dialog.setTitle("标题提示:");
                dialog.setMessage("信息内容");
                dialog.setPositiveButton("确认", new DialogInterface.OnClickListener() {
    
    
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
    
    
                        //点击确认执行的内容
                    }
                });
                dialog.setNegativeButton("取消", new DialogInterface.OnClickListener() {
    
    
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
    
    
                        //点击取消执行的内容
                    }
                });
                dialog.show();
            }
        });

Efecto logrado:
inserte la descripción de la imagen aquí

7,Diálogo de progreso

Al igual que AlertDialog, puede bloquear la capacidad de interacción de otros controles. La diferencia es que tiene una carga.

ProgressDialog progressDialog= new ProgressDialog(FirstActivity.this);
progressDialog.setTitle("标题设置");
progressDialog.setMessage("正在加载中……");
progressDialog.setCancelable(true);
progressDialog.show();

El efecto logrado:
inserte la descripción de la imagen aquí
Tenga en cuenta que si se pasa falso en setCancelable(), significa que el ProgressDialog no se puede cancelar a través de la tecla Atrás. En este momento, debe controlarlo en el código. Cuando se complete la carga de datos, debe llamar el método ProgressDialog dismiss() para cerrar el cuadro de diálogo; de lo contrario, ProgressDialog siempre existirá.

Dos, 4 diseños básicos

¿Qué es un diseño? El sistema front-end ya está muy claro, no es más que un medio o diseño para organizar mejor los elementos de la página.

1, diseño lineal LinearLayout

Los elementos de la página se organizan de forma lineal, horizontal o vertical. Vale la pena señalar que solo controla una fila o una columna, es decir, en el diseño vertical, el ancho de uno de los subelementos no se puede configurar al 100%, por lo que otros subelementos no tendrán lugar para arreglar.

<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/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="按钮1"
        android:textAllCaps="false"/>
    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="按钮2"
        android:textAllCaps="false"/>
    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="按钮3"
        android:textAllCaps="false"/>
</LinearLayout>

El efecto logrado:
inserte la descripción de la imagen aquí
si se establece en horizontal android:orientation="horizontal", se verá así:
inserte la descripción de la imagen aquí
[android:layout_gravity atributo]
Está escrito en los elementos del diseño y se usa para controlar la disposición de los subelementos en el eje transversal, y The item-self en el diseño flexible frontal tiene el mismo efecto.
Por ejemplo:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="按钮1"
        android:layout_gravity="top"
        android:textAllCaps="false"/>
    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="按钮2"
        android:layout_gravity="center"
        android:textAllCaps="false"/>
    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:text="按钮3"
        android:textAllCaps="false"/>
</LinearLayout>

El efecto logrado:
inserte la descripción de la imagen aquí
[android:layout_weight="1" atributo]
es similar a flex-grow en diseño flexible. Cuando usamos este valor, generalmente establecemos el android:layout_width="0dp" del elemento en 0dp, por lo que el ancho del elemento es solo controlado por layout_weight.
El método de cálculo de layout_weight es: primero obtener el ancho completo (la longitud total que se puede asignar a los elementos con el conjunto layout_weight) y luego asignarlo al elemento correspondiente en proporción.
Por ejemplo, hay un cuadro de entrada y un botón. El botón tiene un ancho fijo y el cuadro de entrada es adaptable. Entonces puedes escribir:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <EditText
        android:id="@+id/input_message"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:hint="请输入内容"/>
    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="按钮3"
        android:textAllCaps="false"/>
</LinearLayout>

inserte la descripción de la imagen aquí

2. Disposición relativa

Al hacer referencia a elementos principales seleccionados:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:text="左上按钮"
        android:textAllCaps="false"/>
    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="中间按钮"
        android:textAllCaps="false"/>
</RelativeLayout>

Efecto de logro:
inserte la descripción de la imagen aquí
al seleccionar elementos del mismo nivel que los objetos de referencia:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/button2"
        android:layout_toLeftOf="@id/button2"
        android:text="左上按钮"
        android:textAllCaps="false"/>
    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="中间按钮"
        android:textAllCaps="false"/>
    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/button2"
        android:layout_toLeftOf="@id/button2"
        android:text="左上按钮"
        android:textAllCaps="false"/>
</RelativeLayout>

inserte la descripción de la imagen aquí
También hay una alineación de borde con el mismo nivel como referencia. Este atributo es: layout_alignLeft, etc.

3. Diseño de marco FrameLayout

No existe un método de posicionamiento conveniente para este diseño, y todos los controles se colocarán en la esquina superior izquierda del diseño de forma predeterminada. Y están apilados uno encima del otro.
Por supuesto, se puede manejar con layout_gravity. Es similar al diseño flotante en la parte delantera.

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="left"
        android:text="左上按钮"
        android:textAllCaps="false"/>
    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        android:text="中间按钮"
        android:textAllCaps="false"/>
</FrameLayout>

inserte la descripción de la imagen aquí

4. Diseño de porcentaje

De hecho, este diseño ha quedado obsoleto.
Dado que linearLayout ya admite la proporcionalidad, el diseño de porcentaje es solo una extensión funcional para Frame-layout y RelativeLayout.
A diferencia de los tres diseños anteriores, el diseño de porcentaje es un nuevo diseño, entonces, ¿cómo se puede usar el nuevo diseño en todas las versiones de Android? Por esta razón, el equipo de Android define el diseño de porcentaje en la biblioteca de soporte. agregue la dependencia de la biblioteca de diseño porcentual en build.gradle del proyecto para garantizar la compatibilidad del diseño porcentual en todas las versiones del sistema Android.
Abra el archivo app/buildgradle y agregue el siguiente contenido en las dependencias:

implementation 'androidx.percentlayout:percentlayout:1.0.0'

Después de la modificación, aparecerá este mensaje en la parte superior de AS:
inserte la descripción de la imagen aquí
Haga clic en Sincronizar ahora y gradle comenzará a sincronizarse.
Código de diseño:

<?xml version="1.0" encoding="utf-8"?>
<androidx.percentlayout.widget.PercentFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <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/button3"
        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%"
        />


</androidx.percentlayout.widget.PercentFrameLayout>

Darse cuenta del efecto:
inserte la descripción de la imagen aquí

Tercero, cree un control personalizado

1. Personaliza e importa el diseño

Es solo diseño xml (solo ui), no la unidad funcional más pequeña en el front-end (con ui y eventos)

inserte la descripción de la imagen aquí
Por ejemplo, cuando queremos crear una barra de título:
el primer paso es crear un archivo de diseño title.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <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:textColor="#fff"
        android:text="返回" />
    <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="标题"
        android:textColor="#000000"
        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:textColor="#fff"
        android:text="编辑" />
</LinearLayout>

Paso 2: Presente el diseño 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>

Paso 3: Proteja la barra de título predeterminada:

    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.first_layout);
        ActionBar actionbar=getSupportActionBar();
        if(actionbar!=null){
    
    
            actionbar.hide();
        }
    }

Efecto logrado:
inserte la descripción de la imagen aquí

2. Controles personalizados

Como arriba, hemos creado un título en una actividad, pero si hay varias páginas que necesitan este título y tienen un evento de clic, escribir un evento de clic en cada actividad es más o menos redundante.
Queremos tener un manejo de eventos incorporado como los componentes públicos front-end. Esto requiere la creación de controles personalizados.
Paso 1: Cree un nuevo com.example.uicustomviews, en el que el nuevo TitleLayout herede de LinearLayout, convirtiéndolo en nuestro control de barra de título personalizado.

public class TitleLayout extends LinearLayout {
    
    
    //重写它的构造函数
    public TitleLayout(Context context, AttributeSet attrs){
    
    
        super(context,attrs);
        //对标题栏布局进行动态加载
        LayoutInflater.from(context).inflate(R.layout.title,this);
    }
}

Paso 2: agregue este control personalizado en el archivo de diseño:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <com.example.uicustomviews.TitleLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
</LinearLayout>

Después de compilar, encontrará que el efecto es el mismo que el método de escritura anterior.

Paso 3: Definir eventos en TitleLayout.

public class TitleLayout extends LinearLayout {
    
    
    //重写它的构造函数
    public TitleLayout(Context context, AttributeSet attrs){
    
    
        super(context,attrs);
        //对标题栏布局进行动态加载
        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 view) {
    
    
                ((Activity) getContext()).finish();
            }
        });
        titleEdit.setOnClickListener(new OnClickListener() {
    
    
            @Override
            public void onClick(View view) {
    
    
                Toast.makeText(getContext(), "点击编辑", Toast.LENGTH_SHORT).show();
            }
        });
    }
}

De esta forma, es lo mismo que los componentes del front-end, con ui y eventos correspondientes.
El proceso es el siguiente:
inserte la descripción de la imagen aquí

Cuatro, el control ListView más utilizado

En realidad es una lista larga.

1. Fácil de usar

El primer paso: usar en el diseño:

<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>

Paso 2: Pasar datos en la actividad

public class FirstActivity extends BaseActivity {
    
    
    //定义的数据,实际应该来自网络请求等
    private String [] data ={
    
    
"asda","adfsg","asda","adfsg","asda","adfsg","asda","adfsg","asda","adfsg","asda","adfsg","asda","adfsg","asda","adfsg","asda","adfsg","asda","adfsg","asda","adfsg","asda","adfsg","asda","adfsg","asda","adfsg","asda","adfsg","asda","adfsg",
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.first_layout);
        //使用ArrayAdapter适配器将数据格式转化成listView可以使用的格式
        ArrayAdapter<String> adapter =new ArrayAdapter<String>(FirstActivity.this,android.R.layout.simple_list_item_1,data);
        ListView listView=(ListView) findViewById(R.id.list_view);
        //将转化后的数据赋值给listView
        listView.setAdapter(adapter);
    }
}

Vale la pena señalar que android.R.layout.simple_list_item_1 es un archivo xml incorporado, que solo usa TextView para el uso simple de texto.
Efecto logrado:
inserte la descripción de la imagen aquí

Five, un RecyclerView más potente

Es un componente de lista larga más fuerte y se recomienda usarlo.

1. Paquete de importación

Recyclerview es un control basado en el paquete de soporte. Dado que androidx reemplazó al paquete de soporte, se recomienda que use el paquete de Androidx.
Introduce el siguiente código en el archivo build.gradle para importar el paquete RecyclerView:

dependencies {
    
    
    implementation 'androidx.recyclerview:recyclerview:1.1.0'
}

2, uso en la actividad principal

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
   <androidx.recyclerview.widget.RecyclerView
       android:id="@+id/list_main"
       android:layout_width="match_parent"
       android:layout_height="match_parent" />
</LinearLayout>

3. Escriba el adaptador

Cree una nueva clase FruitAdapter:

public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder> {
    
    
    private List<Fruit> mFruitList;
    //定义了内部类ViewHolder
    static class ViewHolder extends RecyclerView.ViewHolder{
    
    
        ImageView fruitImage;
        TextView fruitName;
        //构造函数传入view,通常是recyclerView子项的最外层布局
        public ViewHolder(View view){
    
    
            super(view);
            fruitImage=(ImageView) view.findViewById(R.id.fruit_image);
            fruitName=(TextView) view.findViewById(R.id.fruit_name);
        }
    }
    //构造函数,用于把要展示地数据源传进来,并赋值给一个全局变量mFruitList
    public FruitAdapter(List<Fruit> fruitList){
    
    
        mFruitList= fruitList;
    }
    //重写方法,用于创建ViewHoler实例,我们在这个方法中将fruit_item布局加载进来,然后创建一个ViewHolder实例。
    //并且把加载出来的布局传入到构造函数中,最后将ViewHolder的实例返回。
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    
    
        View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item,parent,false);
        ViewHolder holder=new ViewHolder(view);
        return holder;
    }
    //用于对RecyclerView子项的数据进行赋值的,会在每个子项被滚动到屏幕内的时候执行。
    //这里我们通过position参数得到当前项的Fruit实例
    //再将数据设置到ViewHolder的ImageView和TetxView当中
    @Override
    public void onBindViewHolder(@NonNull FruitAdapter.ViewHolder holder, int position) {
    
    
        Fruit fruit =mFruitList.get(position);
        holder.fruitImage.setImageResource(fruit.getImageId());
        holder.fruitName.setText(fruit.getName());
    }
    //它用于告诉RecyclerView一共有多少子项,直接返回数据源的长度就可以了。
    @Override
    public int getItemCount() {
    
    
        return mFruitList.size();
    }
}

4. Usa el adaptador

Una vez que el adaptador esté listo, podemos comenzar a usar RecyclerView y modificar el código en FirstActivity:

public class FirstActivity extends BaseActivity {
    
    
    //定义的数据,实际应该来自网络请求等
    private List<Fruit> fruitList=new ArrayList<Fruit>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.first_layout);
        initFruits();
        RecyclerView recyclerView=(RecyclerView) findViewById(R.id.recycler_view);
        //使用线性布局
        LinearLayoutManager layoutManager=new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);
        //将数据传入适配器,构造视图
        FruitAdapter adapter=new FruitAdapter(fruitList);
        recyclerView.setAdapter(adapter);
    }
    private void initFruits(){
    
    
        for (int i=0;i<5;i++){
    
    
            Fruit apple=new Fruit("Apple",R.drawable.img_1);
            fruitList.add(apple);
            Fruit banana=new Fruit("banana",R.drawable.img_2);
            fruitList.add(banana);
            Fruit orange=new Fruit("orange",R.drawable.img_3);
            fruitList.add(orange);
            Fruit pear=new Fruit("pear",R.drawable.img_4);
            fruitList.add(pear);
        }
    }
}

Entre ellos, la clase Fruit y fruit_item.xml son los códigos utilizados en el apartado anterior.

5. El efecto logrado

inserte la descripción de la imagen aquí

6. Implemente el desplazamiento horizontal y el diseño en cascada

En lo que respecta a lo anterior, si cambia al desplazamiento horizontal, debe modificar fruit_item a un diseño vertical:

Paso 1: modificar el diseño del elemento

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="100dp"
    android:layout_height="wrap_content">
    <ImageView
        android:id="@+id/fruit_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"/>
    <TextView
        android:id="@+id/fruit_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="10dp"
        />

</LinearLayout>

Paso 2: Modifique el diseño vertical predeterminado a un diseño horizontal

public class FirstActivity extends BaseActivity {
    
    
    //定义的数据,实际应该来自网络请求等
    private List<Fruit> fruitList=new ArrayList<Fruit>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.first_layout);
        initFruits();
        RecyclerView recyclerView=(RecyclerView) findViewById(R.id.recycler_view);
        //使用线性布局
        LinearLayoutManager layoutManager=new LinearLayoutManager(this);
        //将默认的纵向布局修改为横向布局
        layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
        recyclerView.setLayoutManager(layoutManager);
        //将数据传入适配器,构造视图
        FruitAdapter adapter=new FruitAdapter(fruitList);
        recyclerView.setAdapter(adapter);
    }
    private void initFruits(){
    
    
        for (int i=0;i<5;i++){
    
    
            Fruit apple=new Fruit("Apple",R.drawable.img_1);
            fruitList.add(apple);
            Fruit banana=new Fruit("banana",R.drawable.img_2);
            fruitList.add(banana);
            Fruit orange=new Fruit("orange",R.drawable.img_3);
            fruitList.add(orange);
            Fruit pear=new Fruit("pear",R.drawable.img_4);
            fruitList.add(pear);
        }
    }
}

Efecto logrado:
inserte la descripción de la imagen aquí

7. Diseño de cascada

Paso 1: modificar el diseño del elemento

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="5dp"
    >
    <ImageView
        android:id="@+id/fruit_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"/>
    <TextView
        android:id="@+id/fruit_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="left"
        android:layout_marginTop="10dp"
        />

</LinearLayout>

Paso 2: Modificar FirstActivity.xml

protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.first_layout);
        initFruits();
        RecyclerView recyclerView=(RecyclerView) findViewById(R.id.recycler_view);
        //修改为栅格布局
        StaggeredGridLayoutManager layoutManager=new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(layoutManager);
        //将数据传入适配器,构造视图
        FruitAdapter adapter=new FruitAdapter(fruitList);
        recyclerView.setAdapter(adapter);
    }

Efecto logrado:
inserte la descripción de la imagen aquí

8. Su evento de clic

Modifique el archivo del adaptador:

public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder> {
    
    
    private List<Fruit> mFruitList;
    //定义了内部类ViewHolder
    static class ViewHolder extends RecyclerView.ViewHolder{
    
    
        View fruitView;
        ImageView fruitImage;
        TextView fruitName;
        //构造函数传入view,通常是recyclerView子项的最外层布局
        public ViewHolder(View view){
    
    
            super(view);
            fruitView=view;
            fruitImage=(ImageView) view.findViewById(R.id.fruit_image);
            fruitName=(TextView) view.findViewById(R.id.fruit_name);
        }
    }
    //构造函数,用于把要展示地数据源传进来,并赋值给一个全局变量mFruitList
    public FruitAdapter(List<Fruit> fruitList){
    
    
        mFruitList= fruitList;
    }
    //重写方法,用于创建ViewHoler实例,我们在这个方法中将fruit_item布局加载进来,然后创建一个ViewHolder实例。
    //并且把加载出来的布局传入到构造函数中,最后将ViewHolder的实例返回。
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    
    
        View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item,parent,false);
        final ViewHolder holder=new ViewHolder(view);
        holder.fruitView.setOnClickListener(new View.OnClickListener(){
    
    
            @Override
            public void onClick(View v){
    
    
                int position=holder.getAdapterPosition();
                Fruit fruit =mFruitList.get(position);
                Toast.makeText(v.getContext(), fruit.getName(), Toast.LENGTH_SHORT).show();
            }
        });
        holder.fruitImage.setOnClickListener(new View.OnClickListener(){
    
    
            @Override
            public void onClick(View v){
    
    
                int position=holder.getAdapterPosition();
                Fruit fruit =mFruitList.get(position);
                Toast.makeText(v.getContext(), "点击了图片", Toast.LENGTH_SHORT).show();
            }
        });
        return holder;
    }
    //用于对RecyclerView子项的数据进行赋值的,会在每个子项被滚动到屏幕内的时候执行。
    //这里我们通过position参数得到当前项的Fruit实例
    //再将数据设置到ViewHolder的ImageView和TetxView当中
    @Override
    public void onBindViewHolder(@NonNull FruitAdapter.ViewHolder holder, int position) {
    
    
        Fruit fruit =mFruitList.get(position);
        holder.fruitImage.setImageResource(fruit.getImageId());
        holder.fruitName.setText(fruit.getName());
    }
    //它用于告诉RecyclerView一共有多少子项,直接返回数据源的长度就可以了。
    @Override
    public int getItemCount() {
    
    
        return mFruitList.size();
    }
}

6. Mejores prácticas para escribir páginas

1. Haz una imagen de Nine-Patch

Las imágenes en este formato pueden especificar qué áreas se pueden estirar y qué áreas no.
inserte la descripción de la imagen aquí

2, modifique la prueba firstLayout.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/message_left"
    >
</LinearLayout>

inserte la descripción de la imagen aquí

3. Comienza a escribir la interfaz de chat.

Primero use el mismo método para hacer la imagen message_right.
Debido a que necesitamos usar recyclerView, de acuerdo con el método anterior, primero debemos presentarlo.
Introduce el siguiente código en el archivo build.gradle para importar el paquete RecyclerView:

dependencies {
    
    
    implementation 'androidx.recyclerview:recyclerview:1.1.0'
}

Escriba el diseño de la página de la actividad principal:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#d8e0e8"
    >
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <EditText
            android:id="@+id/input_text"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:hint="请输入文本"
            android:maxLines="2"/>
        <Button
            android:id="@+id/send"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="发送"/>

    </LinearLayout>
</LinearLayout>

Luego crea una nueva clase Msg:

public class Msg {
    
    
    //表示是收到的信息
    public static final int TYPE_RECEIVED=0;
    //表示是发出的信息
    public static final int TYPE_SEND=1;
    public String content;
    private int type;
    public Msg(String content,int type){
    
    
        this.content=content;
        this.type=type;
    }
    public String getContent(){
    
    
        return content;
    }
    public int getType(){
    
    
        return type;
    }
}

A continuación, escriba el diseño del subelemento recyclerView y cree un nuevo archivo msg_item.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="10dp">

    <LinearLayout
        android:id="@+id/left_layout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="left"
        android:background="@drawable/message_left"
        android:orientation="horizontal">
        <TextView
            android:id="@+id/left_msg"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_margin="10dp"
            android:textColor="#000"/>
    </LinearLayout>
    <LinearLayout
        android:id="@+id/right_layout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="left"
        android:background="@drawable/message_right"
        android:orientation="horizontal">
        <TextView
            android:id="@+id/right_msg"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_margin="10dp"
            android:textColor="#000"/>
    </LinearLayout>
</LinearLayout>

A continuación, cree un adaptador y cree una nueva clase MsgAdapter:

public class MsgAdapter extends RecyclerView.Adapter<MsgAdapter.ViewHolder> {
    
    
    private List<Msg> mMsgList;
    //定义了内部类ViewHolder
    static class ViewHolder extends RecyclerView.ViewHolder{
    
    
        LinearLayout leftLayout;
        LinearLayout rightLayout;
        TextView leftMsg;
        TextView rightMsg;
        //构造函数传入view,通常是recyclerView子项的最外层布局
        public ViewHolder(View view){
    
    
            super(view);
            leftLayout=(LinearLayout) view.findViewById(R.id.left_layout);
            rightLayout=(LinearLayout) view.findViewById(R.id.right_layout);
            leftMsg=(TextView) view.findViewById(R.id.left_msg);
            rightMsg=(TextView) view.findViewById(R.id.right_msg);
        }
    }
    //构造函数,用于把要展示地数据源传进来,并赋值给一个全局变量mFruitList
    public MsgAdapter(List<Msg> msgList){
    
    
        mMsgList= msgList;
    }
    //重写方法,用于创建ViewHoler实例,我们在这个方法中将fruit_item布局加载进来,然后创建一个ViewHolder实例。
    //并且把加载出来的布局传入到构造函数中,最后将ViewHolder的实例返回。
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    
    
        View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.msg_item,parent,false);
        ViewHolder holder=new ViewHolder(view);
        return holder;
    }
    //用于对RecyclerView子项的数据进行赋值的,会在每个子项被滚动到屏幕内的时候执行。
    //这里我们通过position参数得到当前项的Fruit实例
    //再将数据设置到ViewHolder的ImageView和TetxView当中
    @Override
    public void onBindViewHolder(@NonNull MsgAdapter.ViewHolder holder, int position) {
    
    
        Msg msg =mMsgList.get(position);
       if(msg.getType()==Msg.TYPE_RECEIVED){
    
    
           //左侧收到
           holder.leftLayout.setVisibility(View.VISIBLE);
           holder.rightLayout.setVisibility(View.GONE);
           holder.leftMsg.setText(msg.getContent());
       }else if(msg.getType()==Msg.TYPE_SEND){
    
    
           //右侧收到
           holder.leftLayout.setVisibility(View.GONE);
           holder.rightLayout.setVisibility(View.VISIBLE);
           holder.rightMsg.setText(msg.getContent());
       }
    }
    //它用于告诉RecyclerView一共有多少子项,直接返回数据源的长度就可以了。
    @Override
    public int getItemCount() {
    
    
        return mMsgList.size();
    }
}

Luego pase los datos en la actividad principal:

public class FirstActivity extends BaseActivity {
    
    
    private List<Msg> msgList=new ArrayList<>();
    private EditText inputText;
    private Button send;
    private RecyclerView msgRecyclerView;
    private MsgAdapter adapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.first_layout);
        initMsgs();
        inputText=(EditText) findViewById(R.id.input_text);
        send =(Button) findViewById(R.id.send);
        msgRecyclerView=(RecyclerView) findViewById(R.id.recycler_view);
        LinearLayoutManager layoutManager =new LinearLayoutManager(this);
        //将信息显示区域设定成线性布局
        msgRecyclerView.setLayoutManager(layoutManager);
        //传入数据给适配器处理
        adapter=new MsgAdapter(msgList);
        msgRecyclerView.setAdapter(adapter);

        send.setOnClickListener(new View.OnClickListener() {
    
    
            @Override
            public void onClick(View view) {
    
    
                String content =inputText.getText().toString();
                if(!"".equals(content)){
    
    
                    Msg msg=new Msg(content,Msg.TYPE_SEND);
                    msgList.add(msg);
                    //当有新消息时,刷新显示
                    adapter.notifyItemInserted(msgList.size()-1);
                    //将ListView定位到最后一行
                    msgRecyclerView.scrollToPosition(msgList.size()-1);
                    inputText.setText("");
                }
            }
        });
    }
    private void initMsgs(){
    
    
        Msg msg1=new Msg("hello guy",Msg.TYPE_RECEIVED);
        msgList.add(msg1);
        Msg msg2=new Msg("hello what is that?",Msg.TYPE_SEND);
        msgList.add(msg2);
        Msg msg3=new Msg("煞笔吧,会说中文拽啥英文",Msg.TYPE_RECEIVED);
        msgList.add(msg3);
    }
}

Efecto logrado:
inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/weixin_42349568/article/details/128912950
Recomendado
Clasificación