Android自定義ViewGroup實現朋友圈九宮格控件
一、簡介
最近項目裡有個類似微信朋友圈的九圖控件的需求,Github找瞭一下,發現都不太滿足需求,我需要單張圖片的時候可以按照圖片寬高比列在一定范圍內自適應,而大多開源項目單張圖片也是一個小正方形,所以,幹脆自己動手寫一個
1.1、效果圖如下
1.2、主要功能如下
1:單張圖片的時候支持按照圖片寬高比列在設定區域內自適應
2:Adapter方式綁定數據和UI
3:圖片點擊事件回調
4:設置圖片間隔大小
5:自由通過Glide設置ImageView圓角效果
二、使用
2.1、自定義屬性如下
<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.2、佈局中使用自定義NineImageLayout
<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" />
2.3、Adapter方式綁定數據和UI
其中Glide.asBitmap是為瞭計算圖片寬高,如果後臺有返回圖片的寬高可以省略這一步,直接setSingleImage(width, height,imageView),
Ps:如果可以建議後臺返回圖片寬高,這樣可以避免單張圖片的時候控件高度跳屏,比如我限制單張圖片寬高在200dp范圍,要展示寬1000px高500px的時候,在圖片未加載完成時控件寬高為200dp,圖片加載完成後高度變為100dp,會有一個不好的用戶體驗,所以建議上傳圖片的時候記錄圖片寬高信息
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(); } });
2.4、列表裡面使用
頁面放一個RecyclerView
<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>
item佈局如下
<?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>
Activity中構造一下測試數據,大致代碼如下
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); } }
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); } } }
三、源碼地址
具體自定義NineImageLayout過程,可以查看NineImageLayout
四、總結
到此這篇關於Android自定義ViewGroup實現朋友圈九宮格控件的文章就介紹到這瞭,更多相關Android朋友圈九宮格控件內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Android如何使用Glide加載清晰長圖
- Android圖片加載庫Glide用法
- Android 使用RecycleView列表實現加載更多的示例代碼
- GridView實現桌面圖標顯示案例
- Android Gridview佈局出現滾動條或組件沖突解決方法