Introduccion
Recientemente, existe una demanda de un control de nueve imágenes similar al círculo de amigos de WeChat. Github lo buscó y descubrió que no satisfacía las necesidades. Cuando necesito una sola imagen, puedo enumerarla en un cierto rango de acuerdo con la relación de aspecto de la imagen. La mayoría de las imágenes individuales de proyectos de código abierto también son un cuadrado pequeño, así que simplemente escriba una usted mismo
Código fuente del proyecto
Se NineImageLayout
puede ver el proceso de personalización específico NineImageLayout
.
El cuadro de efectos es el siguiente:
Las funciones principales son las siguientes:
- 1: cuando se admite una sola imagen, se puede enumerar de forma adaptativa en el área establecida de acuerdo con la relación de aspecto de la imagen
- 2:
Adapter
Formas de vincular datos e IU - 3: devolución de llamada de evento de clic de imagen
- 4: establecer el tamaño del intervalo de imagen
- 5: establece libremente el efecto de esquina redonda ImageView a través de Glide
Para utilizar
1: los atributos personalizados son los siguientes
<resources>
<declare-styleable name="NineImageLayout">
<!-- 控件宽高 -->
<attr name="nine_layoutWidth" format="dimension"/>
<!-- 单张图片时的最大宽高范围-->
<attr name="nine_singleImageWidth" format="dimension" />
<!-- 图片之间间隙大小 -->
<attr name="nine_imageGap" format="dimension" />
</declare-styleable>
</resources>
2: Use NineImageLayout personalizado en el diseño
<com.cyq.customview.nineLayout.view.NineImageLayout
android:id="@+id/nine_image_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/tv_title"
android:layout_marginTop="20dp"
app:nine_imageGap="4dp"
app:nine_layoutWidth="300dp"
app:nine_singleImageWidth="180dp" />
3: forma de adaptador para enlazar datos e interfaz de usuario
Entre ellos Glide.asBitmap
está calcular el ancho y alto de la imagen. Si hay un ancho y alto de la imagen devuelta en el fondo, puede omitir este paso y directamente setSingleImage(width, height,imageView)
.
Ps: Si puede sugerir volver al ancho y la altura de la imagen en el fondo, esto puede evitar la pantalla de salto de altura de control cuando una sola imagen, por ejemplo, limito el ancho y la altura de una sola imagen en el rango de 200dp, cuando se mostrarán el ancho y la 1000px
altura 500px
, la imagen no se carga. Cuando el ancho y la altura del control son los 200dp
siguientes, la altura cambiará después de cargar la imagen 100dp
y habrá una mala experiencia del usuario, por lo que se recomienda registrar la información de ancho y altura de la imagen al cargar la imagen.
nineImageLayout.setAdapter(new NineImageAdapter() {
@Override
protected int getItemCount() {
return mData.size();
}
@Override
protected View createView(LayoutInflater inflater, ViewGroup parent, int i) {
return inflater.inflate(R.layout.item_img_layout, parent, false);
}
@Override
protected void bindView(View view, final int i) {
final ImageView imageView = view.findViewById(R.id.iv_img);
Glide.with(mContext).load(mData.get(i)).into(imageView);
if (mData.size() == 1) {
Glide.with(mContext)
.asBitmap()
.load(mData.get(0))
.into(new SimpleTarget<Bitmap>() {
@Override
public void onResourceReady(Bitmap bitmap, Transition<? super Bitmap> transition) {
final int width = bitmap.getWidth();
final int height = bitmap.getHeight();
nineImageLayout.setSingleImage(width, height,imageView);
}
});
Glide.with(mContext).load(mData.get(0)).into(imageView);
} else {
Glide.with(mContext).load(mData.get(i)).into(imageView);
}
}
@Override
public void OnItemClick(int i, View view) {
super.OnItemClick(position, view);
Toast.makeText(mContext, "position:" + mData.get(i), Toast.LENGTH_SHORT).show();
}
});
Usar en la lista
1: poner una páginaRecyclerView
<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"
tools:context=".nineLayout.NineImageLayoutActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</FrameLayout>
2: el diseño del elemento es el siguiente
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="标题"
android:textColor="@android:color/black"
android:textSize="18sp" />
<com.cyq.customview.nineLayout.view.NineImageLayout
android:id="@+id/nine_image_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/tv_title"
android:layout_marginTop="20dp"
app:nine_imageGap="4dp"
app:nine_layoutWidth="300dp"
app:nine_singleImageWidth="180dp" />
</RelativeLayout>
3: Construya los datos de prueba en Actividad, el código general es el siguiente
public class NineImageLayoutActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private MyAdapter mAdapter;
private Random random;
private final String URL_IMG = "http://q3x62hkt1.bkt.clouddn.com/banner/58f57dfa5bb73.jpg";
private final String URL_IMG_2 = "http://q3x62hkt1.bkt.clouddn.com/timg.jpeg";
private List<List<String>> mList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_nine_image_layout);
random = new Random();
List<String> testList = new ArrayList<>();
testList.add(URL_IMG_2);
for (int i = 0; i < 100; i++) {
int count = i % 9 + 1;
List<String> list = new ArrayList<>();
for (int j = 0; j < count; j++) {
list.add(URL_IMG);
}
if (i % 8 == 0) {
mList.add(testList);
}
mList.add(list);
}
mRecyclerView = findViewById(R.id.recyclerview);
mAdapter = new MyAdapter(mList, this);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mRecyclerView.setAdapter(mAdapter);
}
}
4: Establecer datos en MyAdapter
import java.util.List;
/**
* @author : ChenYangQi
* date : 2020/1/16 13:49
* desc :
*/
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private List<List<String>> mList;
private Context mContext;
public MyAdapter(List<List<String>> mList, Context mContext) {
this.mList = mList;
this.mContext = mContext;
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.item_nine_img_layout_list, parent, false);
return new MyViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull final MyViewHolder holder, final int position) {
final List<String> mData = mList.get(position);
holder.tvTitle.setText("这是" + mData.size() + "张图片的标题");
final NineImageLayout nineImageLayout = holder.nineImageLayout;
holder.nineImageLayout.setAdapter(new NineImageAdapter() {
@Override
protected int getItemCount() {
return mData.size();
}
@Override
protected View createView(LayoutInflater inflater, ViewGroup parent, int i) {
return inflater.inflate(R.layout.item_img_layout, parent, false);
}
@Override
protected void bindView(View view, final int i) {
final ImageView imageView = view.findViewById(R.id.iv_img);
Glide.with(mContext).load(mData.get(i)).into(imageView);
if (mData.size() == 1) {
Glide.with(mContext)
.asBitmap()
.load(mData.get(0))
.into(new SimpleTarget<Bitmap>() {
@Override
public void onResourceReady(Bitmap bitmap, Transition<? super Bitmap> transition) {
final int width = bitmap.getWidth();
final int height = bitmap.getHeight();
nineImageLayout.setSingleImage(width, height,imageView);
}
});
Glide.with(mContext).load(mData.get(0)).into(imageView);
} else {
Glide.with(mContext).load(mData.get(i)).into(imageView);
}
}
@Override
public void OnItemClick(int i, View view) {
super.OnItemClick(position, view);
Toast.makeText(mContext, "position:" + mData.get(i), Toast.LENGTH_SHORT).show();
}
});
}
@Override
public int getItemCount() {
return mList.size();
}
class MyViewHolder extends RecyclerView.ViewHolder {
TextView tvTitle;
NineImageLayout nineImageLayout;
public MyViewHolder(@NonNull View itemView) {
super(itemView);
tvTitle = itemView.findViewById(R.id.tv_title);
nineImageLayout = itemView.findViewById(R.id.nine_image_layout);
}
}
}
Dirección de origen de Github: https://github.com/DaLeiGe/AndroidSamples/blob/master/CustomViewDemo/app/src/main/java/com/cyq/customview/nineLayout/view/NineImageLayout.java