最近在做需求的时候遇到了这样的一个问题,需要完成一个recyclerview的吸顶效果的功能,一开始的提供的方案是,去监听需要进行吸顶吸顶功能的位置,然后根据这个具体的位置的信息来判断是否进行吸顶效果的逻辑。总感觉这样实现有点问题,感觉有点不太好实现,于是去看了好多别人的实现,感觉和自己的需求不太满足。找了一上午没有确定下来最终的方案,于是到了中午去吃饭回来的做电梯回工位的时候,突然有了思路。先大概的说一下这个思路吧,实现吸顶效果无非就是两个view交替的显示,在显示的时候另一个隐藏的效果。废话不多说先看效果图:
一般的需要吸顶的view是隐藏在这个activity的最顶部的,在recycler的item中还有与之对应的view,当item中的view和最顶部的position相等且顶部的position大于当前的item的view时就显示否则就隐藏,这个是实现整个效果的核心点。上代码,我尽可能的将代码整全。
首先我们需要创建一个recyclerview的效果,先看recyclerview所在的activity的xml代码
test_activity:
将吸顶效果的view进行隐藏
接着看一下recyclerview对应的item的xml代码
tem_test.xml:
同样的将对应的view进行隐藏
接下来是逻辑代码,写一个测试用的recyclerview的bean类
TestBean:
package com.example.mytestproject;
/**
* @describe:
* @created 2021/8/1
*/
public class TestBean {
String context1;
String context2;
public String getContext1() {
return context1;
}
public String getContext2() {
return context2;
}
public void setContext1(String context1) {
this.context1 = context1;
}
public void setContext2(String context2) {
this.context2 = context2;
}
}
接下来写一下他对应的adapter
MyTestAdapter:
package com.example.mytestproject;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* @describe:
* @created 2021/8/1
*/
public class MyTestAdapter extends RecyclerView.Adapter {
private Context mContext;
private List mList;
public MyTestAdapter(Context context, List list) {
this.mContext = context;
this.mList = list;
}
@NonNull
@NotNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull @NotNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.item_test, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull @NotNull RecyclerView.ViewHolder holder, int position) {
ViewHolder viewHolder = (ViewHolder) holder;
viewHolder.mTvContext1.setText(mList.get(position).getContext1());
viewHolder.mTvContext2.setText(mList.get(position).getContext2());
if (position == 10) {
//设定吸顶view的显示地方,这里我写好10,可以根据具体哦的业务需求向外暴露这个position值
viewHolder.mLlTest.setVisibility(View.VISIBLE);
}
}
@Override
public int getItemCount() {
return mList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView mTvContext1, mTvContext2;
LinearLayout mLlTest;
public ViewHolder(@NonNull @NotNull View itemView) {
super(itemView);
mTvContext1 = itemView.findViewById(R.id.tv_context1);
mTvContext2 = itemView.findViewById(R.id.tv_context2);
mLlTest = itemView.findViewById(R.id.ll_test);
}
}
}
recyclerview的adapter的大多数方法就不具体的分析了,其中主要是显示那个item的地方需要注意,可以根据自己的业务来向外暴露一个position的值,这里我就写死了。同时,我建议可以使用eventbus的方式将这个值传入到activity中进行逻辑的判断。
接下来是Activity的逻辑:
MyTestActivity:
package com.example.mytestproject;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.LinearLayout;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
public class MyTestActivity extends AppCompatActivity {
RecyclerView mRvTest;
LinearLayout mLlTest;
MyTestAdapter myTestAdapter;
List testBeans = new ArrayList<>();
TestBean testBean;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
initView();
setData(testBeans);
initRecyclerView();
}
private void initView() {
mRvTest = findViewById(R.id.rv_test);
mLlTest = findViewById(R.id.ll_test);
}
private void initRecyclerView() {
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
mRvTest.setLayoutManager(linearLayoutManager);
myTestAdapter = new MyTestAdapter(this, testBeans);
mRvTest.setAdapter(myTestAdapter);
mRvTest.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(@NonNull @NotNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
/**
*获取最顶部position的位置
*/
int topPosition = linearLayoutManager.findFirstCompletelyVisibleItemPosition();
if (dy > 0 && topPosition > 10) {
/**
* dy > 0是向上滑动,dy < 0 是下滑动
*/
mLlTest.setVisibility(View.VISIBLE);
Log.d("上下滑", String.valueOf(dy).toString());
} else if (dy < 0 && topPosition <= 10) {
mLlTest.setVisibility(View.GONE);
Log.d("上下滑", String.valueOf(dy).toString());
}
}
});
}
private void setData(List testBeans) {
testBean = new TestBean();
for (int i = 0; i < 100; i++) {
testBean.setContext1("item左内容");
testBean.setContext2("item右内容");
testBeans.add(testBean);
}
}
}
在activity中获取顶部的position,与adapter中需要显示的view进行判断,如果最顶部的position大于他就显示,同时为了显示效果更好,还进行监听recycler的滑动状态根据滑动的状态来进行判断当前的位置是否显示。总之,感觉这样实现能完成需求,但是感觉不太好,希望有好的方案可以私信我。