Android仿微信朋友圈圖片上傳選擇器佈局

標題有點繞口,直接上一個效果圖,如果符合你的需求的請在往下看,避免浪費你的時間
在這裏插入圖片描述
噹噹噹當,標紅的區域就是今天我們要乾的活了 ,搞起來!

思路:

對android有點了解的人都知道在列表顯示中我們可以使用GridLayoutManager這個佈局可以輕鬆實現圖片文字的一行顯示的個數,所以在使用recyclerview渲染列表的時候我們就使用GridLayoutManager這個佈局來代替以往的LinearLayoutManager
然後在適配器方面我們直接寫一個類繼承RecyclerView.Adapter來手把手實現我們想要的功能,其中我們在重寫**getItemCount()**這個方法是 因爲我們要在顯示的圖片列表的最後加上一個添加的圖片 ,所以我們的這個方法返回的個數應該是我們當前數據的個數加1 這裏也算是本章博客的一個小重點了,關於我們圖片上傳選擇器佈局的實現主要還是圍繞這裏進行擴展的。
在這裏插入圖片描述
好了,廢話不多說,直接開始歡樂的代碼時間!

主活動中的佈局:

在這裏插入圖片描述
代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".activity.ContainSendActivity">
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="50dp">
        <ImageView
            android:layout_margin="5dp"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:src="@drawable/icon_back"/>
        <Button
            android:textColor="#ffffff"
            android:layout_margin="@dimen/dp_10"
            android:background="#009933"
            android:layout_alignParentRight="true"
            android:text="發表"
            android:clickable="false"
            android:layout_width="wrap_content"
            android:layout_height="50dp"/>
    </RelativeLayout>

    <EditText
        android:gravity="start"
        android:layout_margin="10dp"
        android:hint="記錄點滴幸福。。。。"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
         android:background="@null"
         android:lines="6"
        />
<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/send_recycler"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>

</LinearLayout>

兩個recyclerview要顯示的佈局文件

這裏就不貼效果圖片了 很簡單就是兩個圖片 顯示的內容不同罷了
send_item_final.xml

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

    <ImageView
        android:id="@+id/defaultimg"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        app:srcCompat="@drawable/icon_add"
        android:contentDescription="TODO" />
</androidx.cardview.widget.CardView>

send_item.xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="4dp"
    android:orientation="vertical">


    <ImageView
        android:id="@+id/imageView6"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:scaleType="centerCrop"
        android:src="@drawable/smart"
        />
</androidx.cardview.widget.CardView>

適配器代碼

public class SendBlogAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
    private Context context;
    private List<String> data;

    private static final int ITEM_ONE=1;
    private static final int ITEM_TWO=2;
    public SendBlogAdapter(Context context,List<String> data){
        this.context = context;
        this.data = data;

    }

  
    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view;
        RecyclerView.ViewHolder holder;
        if(viewType==ITEM_TWO){
             view = LayoutInflater.from(parent.getContext()).inflate(R.layout.send_ittem_final,parent,false);
             holder = new AnoViewHolder(view);
        }else {
            view = LayoutInflater.from(parent.getContext()).inflate(R.layout.send_item,parent,false);
            holder = new ViewHolder(view);
        }
        return holder;

    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        if (holder instanceof AnoViewHolder) {
            ((AnoViewHolder) holder).img.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(context,"im specatil",Toast.LENGTH_SHORT).show();
                }
            });
        }else {
            ((ViewHolder) holder).imageView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(context,"im nomal",Toast.LENGTH_SHORT).show();
                }
            });
        }

    }


    @Override
    public int getItemCount() {
        return data.size()+1;
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        private ImageView imageView;
        public ViewHolder(View itemView) {
            super(itemView);
            imageView = itemView.findViewById(R.id.imageView6);
            
        }
    }

    public class AnoViewHolder extends RecyclerView.ViewHolder{
        private ImageView img;

        public AnoViewHolder(@NonNull View itemView) {
            super(itemView);
            img = itemView.findViewById(R.id.defaultimg);
            img.setOnClickListener(this);
        }
    }

    @Override
    public int getItemViewType(int position) {
        if(position>data.size()-1){
            return ITEM_TWO;
        }else {
            return ITEM_ONE;
        }
    }
}

詳解以及自己遇到的BUG分享

首先說明上面的適配器代碼是修改好的 複製到你的程序中完全是可用的 ,只是將自己在實現這個功能時遇到的異常和大家做一個分享,避免你以後在遇到同樣問題時不知道該如何去處理,也算是一個小的總結。

思路:

我們要在傳過來的數據中進行判斷,噹噹前顯示的時最後一個傳過來的數據時,我們在他的後面顯示我們之前放好的添加圖片的那個佈局圖片,所以我聲明瞭2個變量在我們的**getItemViewType()方法中進行判斷,如果當前的position大於我們穿過來的數據,就說明當前位置我們應該顯示添加圖片的那個佈局了,然後我們在onCreateViewHolder()**中根據viewType參數進行比對,將我們要顯示的添加圖片顯示上來 到這一步 我們的程序是可以實現靜態佈局的 注意這裏說的是隻是實現靜態佈局。

我遇到的BUG詳解

我們在使用微信發朋友圈時 他是會根據我們點擊選中的時圖片還是添加進行判斷,如果是選擇的圖片他會進入一個圖片詳情界面,如果是添加圖片時他會執行另外一個邏輯,我第一次的思路是直接在一個ViewHolder中實例化我們兩個佈局中的ImageView ,在onBindViewHolder中看看代碼會不會自動根據我們選中的圖片進行邏輯處理,結果程序直接崩潰了,然後就寫了兩個viewHolder 都直接繼承RecyclerView.ViewHolder,這樣在onCreateViewHolder()中判斷當前改初始化那個佈局了,將結果返回給我們定義的ViewHolder中,然後在onBindViewHolder()中我們就可以根據holder找到他的孩子了 就可以進行兩個佈局中各事件的處理了

擴展

在adapter中處理我們的事件操作就不是很方便,我還想在選擇圖片時加一個底部彈出框,就想着把點擊事件在我們要顯示的佈局中進行處理,就仿照點擊事件接口將點擊事件的觸發寫在了activity中
擴展後的adapter:

public class SendBlogAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
    private Context context;
    private List<String> data;

    private static final int ITEM_ONE=1;
    private static final int ITEM_TWO=2;
    public SendBlogAdapter(Context context,List<String> data){
        this.context = context;
        this.data = data;

    }

    private OnItemClickListener clickListener;

    public void setClickListener(OnItemClickListener clickListener) {
        this.clickListener = clickListener;
    }

    public interface OnItemClickListener {
        void onClick(View view, int position);
        void onSelected(View view,int position);
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view;
        RecyclerView.ViewHolder holder;
        if(viewType==ITEM_TWO){
             view = LayoutInflater.from(parent.getContext()).inflate(R.layout.send_ittem_final,parent,false);
             holder = new AnoViewHolder(view);
        }else {
            view = LayoutInflater.from(parent.getContext()).inflate(R.layout.send_item,parent,false);
            holder = new ViewHolder(view);
        }
        return holder;

    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
//        if (holder instanceof AnoViewHolder) {
//            ((AnoViewHolder) holder).img.setOnClickListener(new View.OnClickListener() {
//                @Override
//                public void onClick(View v) {
//                    Toast.makeText(context,"im specatil",Toast.LENGTH_SHORT).show();
//                }
//            });
//        }else {
//            ((ViewHolder) holder).imageView.setOnClickListener(new View.OnClickListener() {
//                @Override
//                public void onClick(View v) {
//                    Toast.makeText(context,"im nomal",Toast.LENGTH_SHORT).show();
//                }
//            });
//        }

    }


    @Override
    public int getItemCount() {
        return data.size()+1;
    }

    public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
        private ImageView imageView;
        public ViewHolder(View itemView) {
            super(itemView);
            imageView = itemView.findViewById(R.id.imageView6);
            imageView.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            if(clickListener!=null){
                clickListener.onSelected(itemView, getAdapterPosition());
            }
        }
    }

    public class AnoViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
        private ImageView img;

        public AnoViewHolder(@NonNull View itemView) {
            super(itemView);
            img = itemView.findViewById(R.id.defaultimg);
            img.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            if(clickListener!=null){
                clickListener.onClick(itemView, getAdapterPosition());
            }
        }
    }

    @Override
    public int getItemViewType(int position) {
        if(position>data.size()-1){
            return ITEM_TWO;
        }else {
            return ITEM_ONE;
        }
    }
}

最後就是在我們activity中的引用了:(這裏使用的是kotlin)

       fun initData() {

        var array4 = arrayOf("1","2","3")
        send_recycler.layoutManager  = GridLayoutManager(this,3)
        var adapter = SendBlogAdapter(this, array4.toMutableList())
        send_recycler.adapter = adapter
        adapter.setClickListener(object :SendBlogAdapter.OnItemClickListener{
            override fun onSelected(view: View?, position: Int) {//添加圖片點擊的事件監聽
                Toast.makeText(this@ContainSendActivity,"======",Toast.LENGTH_SHORT).show()
            }

            override fun onClick(view: View?, position: Int) {//選中已添加的圖片點擊的事件監聽
                Toast.makeText(this@ContainSendActivity,"didia",Toast.LENGTH_SHORT).show()
            }

        })
    }

最後上一個我做好的效果圖:
在這裏插入圖片描述
界面有點醜哈 在後面我會進行優化的 嘻嘻
歐克,到這裏我們的仿微信朋友圈圖片上傳選擇器佈局的實現就算完成了。
在後面的章節中我也會將微信朋友圈的功能一點點的做出來的並且記錄下來,動態添加刪除圖片,圖片的選擇方式,圖片瀏覽的功能等等 ,,,
編寫不易,請大家多多點贊支持 !!!!
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章