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:
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:
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:
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:
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:
si se establece en horizontal android:orientation="horizontal", se verá así:
[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:
[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>
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:
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>
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>
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:
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:
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)
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:
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:
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:
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
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:
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:
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.
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>
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: