效果如下:
主界面界面布局:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout 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" android:orientation="vertical" android:background="#fff" tools:context="com.example.mingnews.MainActivity"> <LinearLayout android:id="@+id/search_bar" android:background="#345" android:paddingTop="30dp" android:paddingBottom="5dp" android:paddingStart="5dp" android:paddingEnd="5dp" android:layout_width="match_parent" android:layout_height="85dp" android:focusable="true" android:focusableInTouchMode="true"> <EditText android:id="@+id/exit_text" android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" android:textColor="@android:color/white" android:textColorHint="@android:color/white" android:hint="@string/query_hint"/> <ImageView android:id="@+id/query_button" android:layout_width="35dp" android:layout_height="35dp" android:paddingTop="5dp" android:clickable="true" android:focusable="true" android:src="@drawable/search_tubiao" /> </LinearLayout> <com.example.mingnews.MingRecyclerView android:id="@+id/list_view" android:layout_below="@id/search_bar" android:layout_width="match_parent" android:layout_height="match_parent" /> </RelativeLayout>主要是一个顶部的搜索栏加一个自定义的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<MainItemBean> 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<MainItemBean> 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; } }
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="105dp" android:padding="15dp"> <ImageView android:id="@+id/background" android:layout_width="match_parent" android:layout_height="match_parent" tools:background="#678"/> <TextView android:id="@+id/item_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="true" android:layout_centerVertical="true" android:layout_marginEnd="47dp" android:textSize="35sp" tools:text="科技" /> </RelativeLayout>