[Android Studio]Fragment+RecyclerView實現吸頂式佈局+item點擊事件

Fragment+RecyclerView實現吸頂式佈局+item點擊事件

在上次的微信Fragment項目基礎上,選擇一個tab實現用RecyclerView顯示內容。我實現的是吸頂式顯示外加點擊item會有Toast提示。

項目文件已上傳至github,詳見 1. layout文件 2. java文件


以下RecyclerView的效果實現參考https://www.jianshu.com/p/c4cfe38a91ed

修改build.gradle(Module:app)

我使用的Android Studio的版本是3.5.3,一開始按照v7的包使用RecyclerView出現很多編譯問題以及運行時閃退問題,網上查找原因,發現是此AS版本已經不支持使用v7了。

後查找到此解決方法,如下後三行(不包括註釋)代碼。

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.0'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
//    implementation 'androidx.recyclerview:recyclerview:1.1.0'
    def recyclerview_version = "1.0.0"
    implementation "androidx.recyclerview:recyclerview:$recyclerview_version"
// For control over item selection of both touch and mouse driven selection
    implementation "androidx.recyclerview:recyclerview-selection:$recyclerview_version"
}

編寫佈局xml文件

//tab_addr.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="match_parent">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rcv_sticky"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:overScrollMode="never"
        android:scrollbars="none"/>

    <include layout="@layout/sticky_item" />

</RelativeLayout>

//item.xml
//內容項item

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

    <include layout="@layout/sticky_item"/>

    <TextView
        android:id="@+id/txtPlants"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="3dp"
        android:textSize="20sp"
        android:textColor="#666"
        android:text="TextView" />
</LinearLayout>
// sticky_item.xml
//吸頂item

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/txtSunlight"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="25sp"
        android:padding="3dp"
        android:textColor="#666"
        android:background="#DBEDFF"
        android:text="TextView" />
</LinearLayout>

item.xml和RecyclerView所在的xml文件都要include一個吸頂item佈局(sticky_item.xml)。

編寫adapter

先寫好數據類GroupData.java,裏面有sunlight和plants,sunlight的數據是吸頂顯示的,plants的數據是內容項。

StickyAdapter.java

	private Context mContext;
    private List<GroupData> mList;
    private OnItemClickListener mListener;
	public static final int FIRST_STICKY_VIEW = 1;
    public static final int HAS_STICKY_VIEW = 2;
    public static final int NONE_STICKY_VIEW = 3;
    
    public void onBindViewHolder(@NonNull StickyViewHolder holder, int position) {
        final GroupData groupData = mList.get(position);
        holder.txtPlants.setText(groupData.plants);
        if (position == 0) {
            holder.txtSunlight.setVisibility(View.VISIBLE);
            holder.txtSunlight.setText(groupData.sunlight);
            holder.itemView.setTag(FIRST_STICKY_VIEW);
        } else {
            if (!TextUtils.equals(groupData.sunlight, mList.get(position-1).sunlight)) {
                holder.txtSunlight.setVisibility(View.VISIBLE);
                holder.txtSunlight.setText(groupData.sunlight);
                holder.itemView.setTag(HAS_STICKY_VIEW);
            } else {
                holder.txtSunlight.setVisibility(View.GONE);
                holder.itemView.setTag(NONE_STICKY_VIEW);
            }
        }
        holder.itemView.setContentDescription(groupData.sunlight);

        //點擊事件傳入addrFragment(Activity)
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mListener.onItemClick(groupData.plants);
            }
        });
    }

編寫Fragment

首先初始化數據:

	private List<String> mList = new ArrayList<>();
    private List<GroupData> mDataList = new ArrayList<>();
	
	private void initList() {
        mList.add("陽光:0|小噴菇");
        mList.add("陽光:0|水兵菇");
        mList.add("陽光:25|土豆地雷");
        mList.add("陽光:25|陽光菇");
       	//更多mList.add...
	}
	
	private void initData() {
        for (int i = 0; i < mList.size(); i++) {
            GroupData groupData = new GroupData();
            String s = mList.get(i);
            String sunlight = s.substring(0, s.indexOf("|"));//得到mList前半邊的數據給sunlight
            String plants = s.substring(s.indexOf("|") + 1);//得到mList後半邊的數據給plants
            groupData.setSunlight(sunlight);
            groupData.setPlants(plants);
            mDataList.add(groupData);
        }
    }

然後是將數據顯示出來

	private Context context;
    private RecyclerView mRcv;
    private StickyAdapter stickyAdapter;

	public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.tab_addr, container, false);
        context = view.getContext();
        initList();
        initData();
        initView(view);
        return view;
    }
	private void initView(View view) {
        stickyAdapter = new StickyAdapter(context, this);
        mRcv = view.findViewById(R.id.rcv_sticky);
        final TextView txtSunlight = view.findViewById(R.id.txtSunlight);

        LinearLayoutManager manager = new LinearLayoutManager(context);
        manager.setOrientation(LinearLayoutManager.VERTICAL);

        mRcv.setLayoutManager(manager);
        mRcv.setHasFixedSize(true);
        mRcv.setAdapter(stickyAdapter);

        stickyAdapter.setStickyDataList(mDataList);
        mRcv.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);

                View stickyView = recyclerView.findChildViewUnder(txtSunlight.getMeasuredWidth()/2, 5);
                if (stickyView != null && stickyView.getContentDescription() != null) {
                    txtSunlight.setText(String.valueOf(stickyView.getContentDescription()));
                }

                View transInfoView = recyclerView.findChildViewUnder(txtSunlight.getMeasuredWidth()/2, txtSunlight.getMeasuredHeight()+1);
                if (transInfoView != null && transInfoView.getTag() != null) {
                    int tranViewStatus = (int) transInfoView.getTag();
                    int dealtY = transInfoView.getTop() - txtSunlight.getMeasuredHeight();

                    if (tranViewStatus == StickyAdapter.HAS_STICKY_VIEW) {
                        if (transInfoView.getTop() > 0) {
                            txtSunlight.setTranslationY(dealtY);
                        } else {
                            txtSunlight.setTranslationY(0);
                        }
                    } else if (tranViewStatus == StickyAdapter.NONE_STICKY_VIEW) {
                        txtSunlight.setTranslationY(0);
                    }
                }
            }
        });
    }

點擊事件Toast提示

	public void onItemClick(String content) {
        Toast.makeText(context, "這是 " + content, Toast.LENGTH_SHORT).show();
    }

實現吸頂效果時,因爲StickyAdapter.java中的onCreateViewHolder方法中本應該是 View view = LayoutInflater.from(mContext).inflate(R.layout.item, parent, false); 的代碼寫錯了目標佈局id,導致編譯時成功而運行時一點擊tab_addr按鈕區就閃退,AS的logcat報空指針的錯誤。

java.lang.NullPointerException: Attempt to invoke virtual method ‘void android.widget.TextView.setText(java.lang.CharSequence)’ on a null object reference

按我在網上查找到說法是項目它運行時遇到了找不到某個id的情況。

運行結果
在這裏插入圖片描述


效果實現參考https://www.jianshu.com/p/c4cfe38a91ed

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