效果如下:
主界面界面布局:
主要是一个顶部的搜索栏加一个自定义的recyclerview。
其中将edittext控件的父布局的focusable和focusableInTouchMode属性设置为true可避免一显示该界面就自动弹出输入法。
自定义recyclerview:
public class MingRecyclerView extends RecyclerView {
private int mFirstY;
public MingRecyclerView(Context context) {
super(context);
}
public MingRecyclerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public MingRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent e) {
if(e.getAction()==MotionEvent.ACTION_DOWN)mFirstY= (int) e.getY();
return super.onInterceptTouchEvent(e);
}
@Override
public boolean performClick() {
return super.performClick();
}
public int getTouchPointY() {
return mFirstY;
}
}
关键点是onInterceptTouchEvent方法,用于获取手指接触屏幕时触摸点的y轴坐标。
由于实现了OnTouchListener监听,所以复写performClick方法以消除警告。
主界面:
public class MainActivity extends Activity {
private View searchBar;
private EditText editText;
private ImageView queryButton;
private MingRecyclerView recyclerView;
private List data;
int mFirstY, mCurrentY, marginTop;
boolean direction;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
data = new ArrayList<>();
data.add(new MainItemBean(R.drawable.ic_launcher_background, "头条"));
data.add(new MainItemBean(R.drawable.ic_launcher_background, "社会"));
data.add(new MainItemBean(R.drawable.ic_launcher_background, "国内"));
data.add(new MainItemBean(R.drawable.ic_launcher_background, "国际"));
data.add(new MainItemBean(R.drawable.ic_launcher_background, "娱乐"));
data.add(new MainItemBean(R.drawable.ic_launcher_background, "体育"));
data.add(new MainItemBean(R.drawable.ic_launcher_background, "军事"));
data.add(new MainItemBean(R.drawable.ic_launcher_background, "科技"));
data.add(new MainItemBean(R.drawable.ic_launcher_background, "财经"));
data.add(new MainItemBean(R.drawable.ic_launcher_background, "时尚"));
initView();
}
private void initView() {
marginTop = DisplayUtil.dp2px(this, 85); //顶部搜索栏高度为85dp,转为像素值255
MainListAdapter adapter = new MainListAdapter(this, data);
adapter.setOnItemClickListener(new MainListAdapter.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
Toast.makeText(MainActivity.this, data.get(position).getTitle(), Toast.LENGTH_SHORT).show();
}
});
searchBar = findViewById(R.id.search_bar);
editText=findViewById(R.id.exit_text);
queryButton=findViewById(R.id.query_button);
queryButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String query=editText.getText().toString();
}
});
recyclerView = findViewById(R.id.list_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this, OrientationHelper.VERTICAL, false));
recyclerView.setAdapter(adapter);
recyclerView.setOnTouchListener(new View.OnTouchListener() {
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_MOVE:
mFirstY=recyclerView.getTouchPointY();
mCurrentY = (int) motionEvent.getY();
Log.d("ttt","mFirstY:"+mFirstY+" mCurrentY:"+mCurrentY);
RelativeLayout.LayoutParams top = (RelativeLayout.LayoutParams) searchBar.getLayoutParams();
if (mCurrentY - mFirstY > 0) {
direction = false; //向下滑动
} else {
direction = true; //向上滑动
}
Log.d("uuu","top.margin:"+top.topMargin+" direction:"+direction);
if (direction) {
Log.d("uuu","上滑");
if (top.topMargin > -marginTop) {
top.topMargin += mCurrentY - mFirstY;
if(top.topMargin<-marginTop)
top.topMargin=-marginTop;
Log.d("uuu","top2:"+top.topMargin);
searchBar.requestLayout();
}
} else {
if (top.topMargin < 0) {
top.topMargin += mCurrentY - mFirstY;
if(top.topMargin>0)top.topMargin=0;
searchBar.requestLayout();
}
}
break;
}
return false;
}
});
}
}
关键点是OnTouchListener监听,手指滑动时判断是上滑还是下滑,然后用滑动的距离(mCurrentY-mFirstY)来设置顶部搜索栏的topMargin(顶部留白,这里值不大于0),调用requestLayout重新布局。
注:(试验发现)由于recyclerview实现item点击监听,会导致onTouch方法接收不到ACTION_DOWN事件,这是为什么要通过复写onInterceptTouchEvent方法来获取ACTION_DOWN事件。而recyclerview取消任何item点击监听的情况下,onTouch方法偶尔能接收到ACTION_DOWN事件,具体原因未深究,如有人知道请告诉我,谢谢!
附上适配器和item布局文件:
public class MainListAdapter extends RecyclerView.Adapter {
private Context context;
private List data;
private OnItemClickListener itemClickListener;
public MainListAdapter(Context context, List data){
this.context=context;
this.data=data;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view= LayoutInflater.from(context).inflate(R.layout.main_list_item,parent,false);
return new MyViewHolder(view,itemClickListener);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
ImageView imageView=((MyViewHolder)holder).v.findViewById(R.id.background);
imageView.setImageResource(data.get(position).getImageId());
TextView textView=((MyViewHolder)holder).v.findViewById(R.id.item_title);
textView.setText(data.get(position).getTitle());
}
@Override
public int getItemCount() {
return data.size();
}
class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
private OnItemClickListener onItemClickListener;
private View v;
public MyViewHolder(View itemView,OnItemClickListener onItemClickListener) {
super(itemView);
this.onItemClickListener=onItemClickListener;
itemView.setOnClickListener(this);
v=itemView;
}
@Override
public void onClick(View view) {
if(onItemClickListener!=null)
onItemClickListener.onItemClick(v,getAdapterPosition());
}
}
public interface OnItemClickListener{
void onItemClick(View view,int position);
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener){
this.itemClickListener=onItemClickListener;
}
}