English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Se utilizan muchos componentes personalizados en el proyecto de la tesis, y siempre he planeado resumir la forma de implementar componentes personalizados. Hoy en día, voy a resumir. Antes de eso, aprendí algunos artículos de blog de la gran figura Guo Lin, y siento que he aprendido mucho, y este artículo se refiere a algunos de los contenidos.
En resumen, la implementación de componentes personalizados tiene tres métodos, respectivamente: componentes combinados, componentes dibujados y componentes heredados. A continuación, se presentarán estos tres métodos respectivamente.
(一)组件组合
Los componentes combinados, como su nombre indica, consisten en combinar varios componentes pequeños para formar un nuevo componente, y estos pequeños componentes son muchos componentes del sistema. Por ejemplo, los componentes de la barra de título utilizados en muchas aplicaciones son componentes combinados. A continuación, se explicará el uso de los componentes combinados a través de la implementación de un componente personalizado de barra de título simple.
1、Crear un proyecto de Android nuevo, crear un archivo de diseño personalizado de la barra de título title_bar.xml:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#0000ff" > <Button android:id="@"+id/left_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_margin="5dp" android:background="@drawable/back1_64" /> <TextView android:id="@"+id/title_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="Este es el título" android:textColor="#ffffff" android:textSize="20sp" /> </RelativeLayout>
Visible que este controlador de barra de título es bastante simple, en la izquierda hay un botón de regreso y el fondo es una imagen preparada anteriormente back1_64.png, el texto del título está en el centro de la barra de título.
2Crear una clase TitleView, que hereda de RelativeLayout:
public class TitleView extends RelativeLayout { // Controlador del botón de regreso private Button mLeftBtn; // Texto de título private TextView mTitleTv; public TitleView(Context context, AttributeSet attrs) { super(context, attrs); // Cargar el diseño LayoutInflater.from(context).inflate(R.layout.title_bar, this); // Obtener los controladores mLeftBtn = (Button) findViewById(R.id.left_btn); mTitleTv = (TextView) findViewById(R.id.title_tv); } // Agregar un evento de clic personalizado al botón de regreso izquierdo public void setLeftButtonListener(OnClickListener listener) { mLeftBtn.setOnClickListener(listener); } // Método para establecer el título public void setTitleText(String title) { mTitleTv.setText(title); } }
En TitleView, principalmente se carga el diseño de la barra de título personalizada, se agrega un método de escucha de eventos al botón de regreso y se proporciona un método para establecer el texto del título.
3En activity_main.xml, importar la barra de título personalizada:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@"+id/main_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <com.example.test.TitleView android:id="@"+id/title_bar" android:layout_width="match_parent" android:layout_height="wrap_content" > </com.example.test.TitleView> </LinearLayout>
4En MainActivity, obtener la barra de título personalizada y agregar un evento de clic personalizado al botón de regreso:
private TitleView mTitleBar; mTitleBar = (TitleView) findViewById(R.id.title_bar); mTitleBar.setLeftButtonListener(new OnClickListener() { @Override public void onClick(View v) { Toast.makeText(MainActivity.this, "Se hizo clic en el botón de regreso", Toast.LENGTH_SHORT) .show(); finish(); } });
5El efecto de ejecución es el siguiente:
De esta manera, se ha implementado un título personalizado de combinación, realmente, mediante más combinaciones, se pueden crear controles personalizados más complejos, como una barra de búsqueda personalizada, etc.
(II) Controlador de dibujo autónomo
Los controles dibujados de manera autónoma son todos dibujados por sí mismos, se completan en el método onDraw de View. A continuación, se realiza un simple contador, cada vez que se hace clic en él, el valor de cuenta se suma1Y mostrar.
1、Crear la clase CounterView, que hereda de View e implementa la interfaz OnClickListener:
public class CounterView extends View implements OnClickListener { // Definir pluma private Paint mPaint; // Se utiliza para obtener el ancho y la altura del texto private Rect mBounds; // El valor de cuenta, cada vez que se hace clic en este controlador, su valor aumenta1 private int mCount; public CounterView(Context context, AttributeSet attrs) { super(context, attrs); // Inicializar pluma y Rect mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mBounds = new Rect(); // El evento de clic de este controlador setOnClickListener(this); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); mPaint.setColor(Color.BLUE); // Dibujar un rectángulo relleno de azul canvas.drawRect(0, 0, getWidth(), getHeight(), mPaint); mPaint.setColor(Color.YELLOW); mPaint.setTextSize(50); String text = String.valueOf(mCount); // Obtener el ancho y alto del texto mPaint.getTextBounds(text, 0, text.length(), mBounds); float textWidth = mBounds.width(); float textHeight = mBounds.height(); // Dibujar cadena canvas.drawText(text, getWidth() / 2 - textWidth / 2, getHeight() / 2 + textHeight / 2, mPaint); } @Override public void onClick(View v) { mCount ++; // Redibujar invalidate(); } }
2Introducir este diseño personalizado en activity_main.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@"+id/main_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <com.example.test.CounterView android:id="@"+id/counter_view" android:layout_width="100dp" android:layout_height="100dp" android:layout_gravity="center_horizontal|top" android:layout_margin="20dp" /> </LinearLayout>
3El efecto de ejecución es el siguiente:
(Tres) Heredar controles
Es heredar de un control existente, crear un nuevo control, mantener las características del control heredado del padre y, además, introducir nuevas características. A continuación, se presenta una implementación de CustomListView que admite la eliminación de elementos de lista deslizando horizontalmente.
1Crear el diseño de botón de eliminación delete_btn.xml, que se muestra después de deslizar horizontalmente una entrada de lista:
<?xml version="1.0" encoding="utf-8"?> <Button xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#FF0000" android:padding="5dp" android:text="eliminar" android:textColor="#FFFFFF" android:textSize="16sp" > </Button>
2Crear la clase CustomListView que hereda de ListView e implementa las interfaces OnTouchListener y OnGestureListener:
public class CustomListView extends ListView implements OnTouchListener, OnGestureListener { // Detector de acción de gestos private GestureDetector mGestureDetector; // escucha de eventos de eliminación public interface OnDeleteListener { void onDelete(int index); } private OnDeleteListener mOnDeleteListener; // botón de eliminación private View mDeleteBtn; // diseño de elemento de lista private ViewGroup mItemLayout; // elemento de lista seleccionado private int mSelectedItem; // Si el botón de eliminación actual se muestra private boolean isDeleteShown; public CustomListView(Context context, AttributeSet attrs) { super(context, attrs); // Crear objeto de escucha de gestos mGestureDetector = new GestureDetector(getContext(), this); // escuchar evento onTouch setOnTouchListener(this); } // establecer evento de escucha de eliminación public void setOnDeleteListener(OnDeleteListener listener) { mOnDeleteListener = listener; } // evento de escucha de toque @Override public boolean onTouch(View v, MotionEvent event) { if (isDeleteShown) { hideDelete(); return false; } else { return mGestureDetector.onTouchEvent(event); } } @Override public boolean onDown(MotionEvent e) { if (!isDeleteShown) { mSelectedItem = pointToPosition((int) e.getX(), (int) e.getY()); } return false; } @Override public boolean onFling(MotionEvent e1, MotionEvent e}}2, float velocityX, float velocityY) { // Si el botón de eliminación actual no se muestra y la velocidad de deslizamiento en el eje X es mayor que la velocidad de deslizamiento en el eje Y if (!isDeleteShown && Math.abs(velocityX) > Math.abs(velocityY)) { mDeleteBtn = LayoutInflater.from(getContext()).inflate( R.layout.delete_btn, null); mDeleteBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mItemLayout.removeView(mDeleteBtn); mDeleteBtn = null; isDeleteShown = false; mOnDeleteListener.onDelete(mSelectedItem); } }); mItemLayout = (ViewGroup) getChildAt(mSelectedItem - getFirstVisiblePosition()); RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); params.addRule(RelativeLayout.CENTER_VERTICAL); mItemLayout.addView(mDeleteBtn, params); isDeleteShown = true; } return false; } // ocultar el botón de eliminación public void hideDelete() { mItemLayout.removeView(mDeleteBtn); mDeleteBtn = null; isDeleteShown = false; } public boolean isDeleteShown() { return isDeleteShown; } /** * las siguientes métodos no se utilizan en este ejemplo */ @Override public void onShowPress(MotionEvent e) { } @Override public boolean onSingleTapUp(MotionEvent e) { return false; } @Override public boolean onScroll(MotionEvent e)1, MotionEvent e}}2, float distanceX, float distanceY) { return false; } @Override public void onLongPress(MotionEvent e) { } }
3、定义列表项布局custom_listview_item.xml,它的结构很简单,只包含了一个TextView:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:descendantFocusability="blocksDescendants" > <TextView android:id="@"+id/content_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_margin="30dp" android:gravity="center_vertical|left" /> </RelativeLayout>
4、定义适配器类CustomListViewAdapter,继承自ArrayAdapter<String>:
public class CustomListViewAdapter extends ArrayAdapter<String> { public CustomListViewAdapter(Context context, int textViewResourceId, List<String> objects) { super(context, textViewResourceId, objects); } @Override public View getView(int position, View convertView, ViewGroup parent) { View view; if (convertView == null) { view = LayoutInflater.from(getContext()).inflate( R.layout.custom_listview_item, null); } else { view = convertView; } TextView contentTv = (TextView) view.findViewById(R.id.content_tv); contentTv.setText(getItem(position)); return view; } }
5、在activity_main.xml中引入自定义的ListView:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@"+id/main_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <com.example.test.CustomListView android:id="@"+id/custom_lv" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout>
6、在MainActivity中对列表进行初始化、设置列表项删除按钮点击事件等处理:
public class MainActivity extends Activity { // 自定义Lv private CustomListView mCustomLv; // 自定义适配器 private CustomListViewAdapter mAdapter; // 内容列表 private List<String> contentList = new ArrayList<String>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); initContentList(); mCustomLv = (CustomListView) findViewById(R.id.custom_lv); mCustomLv.setOnDeleteListener(new OnDeleteListener() { @Override public void onDelete(int index) { contentList.remove(index); mAdapter.notifyDataSetChanged(); } }); mAdapter = new CustomListViewAdapter(this, 0, contentList); mCustomLv.setAdapter(mAdapter); } // Inicializar lista de contenido private void initContentList() { for (int i = 0; i < 20; i++) { contentList.add("elemento de contenido" + i); } } @Override public void onBackPressed() { if (mCustomLv.isDeleteShown()) { mCustomLv.hideDelete(); return; } super.onBackPressed(); } }
7El efecto de ejecución es el siguiente:
Esto es todo el contenido del artículo, espero que sea útil para su aprendizaje y que todos apoyen el tutorial de alarido.
Aviso: Este artículo se ha redactado en línea, el copyright pertenece al propietario original, el contenido ha sido contribuido y subido por los usuarios de Internet, este sitio web no posee los derechos de propiedad, no se ha procesado editorialmente y no asume ninguna responsabilidad legal. Si encuentra contenido sospechoso de infracción de derechos de autor, por favor envíe un correo electrónico a: notice#w proporcionando evidencia relevante.3Declaración: El contenido de este artículo se ha obtenido de la red, pertenece al propietario original, el contenido se ha contribuido y subido por los usuarios de Internet, este sitio web no posee los derechos de propiedad, no se ha procesado editorialmente y no asume ninguna responsabilidad legal. Si encuentra contenido sospechoso de infracción de derechos de autor, por favor envíe un correo electrónico a: notice#w proporcionando evidencia relevante, una vez confirmado, este sitio eliminará inmediatamente el contenido sospechoso de infracción.