qq的搜索功能在点击搜索框时整个页面上移,出现透明布局。该效果是模仿iOS实现的,但是在Android也是很容易实现的。于是就花了点时间仿照效果写了一个demo。可能实现方式并不是完全相同。
具体请看效果图:
详细说明略。第一种是利用隐藏的透明LinearLayout实现效果。第二、三种是通过PopupWindow实现的,只有一处区别,即搜索框的两种状态。第二种采用的是ListView的addHeaderView实现的。
不多说直接上代码
/********************************************************** * @文件名称:MainActivity.java * @创建时间:2014年11月21日 下午8:12:24 * @修改历史:2014年11月21日 **********************************************************/ package com.jinlin.searchview; import java.util.ArrayList; import java.util.List; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.util.Log; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnTouchListener; import android.view.animation.Animation; import android.view.animation.Animation.AnimationListener; import android.view.animation.TranslateAnimation; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.TextView; import android.widget.TextView.OnEditorActionListener; import android.widget.Toast; /** * @author J!nl!n * @date 2014年11月21日 * @time 下午8:12:24 * @type MainActivity.java * @todo */ public class Activity1 extends Activity implements OnClickListener{ protected static final String TAG = Activity1.class.getSimpleName(); // 容器布局 private LinearLayout container; // 标题栏布局 private View titleView; private View searchView; private ListView listView; // 输入框是否获取到焦点 private static boolean isFocused = false; // 图标居中输入框 private EditText et_search; // 真是输入框 private EditText et_input; // 取消按钮 private Button btn_cancel; // 显示或隐藏软键盘 private enum KeyBoardType { show, hide; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity1); initView(); } private List<String> getData() { List<String> data = new ArrayList<String>(); for (int i = 0; i < 100; i++) { data.add("测试数据" + i); } return data; } /** * 【未做验证】这里需要注意在removeView之后,标题栏设置的监听事件是否失去,倘若在点击取消调用addView方法之后是否需要重新设置监听 */ private void initView() { // 找到整个容器的布局 container = ((LinearLayout) findViewById(R.id.container)); // 获取标题栏布局 titleView = findViewById(R.id.title_header); listView = (ListView) findViewById(R.id.listview); listView.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_expandable_list_item_1, getData())); // 找到隐藏的搜索布局 searchView = findViewById(R.id.floatview); et_search = (EditText) findViewById(R.id.et_search); et_input = (EditText) findViewById(R.id.et_input); // 取消按钮 btn_cancel = (Button) findViewById(R.id.btn_cancel); // 取消按钮设置监听 btn_cancel.setOnClickListener(this); et_search.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: isFocused = true; // 显示隐藏的布局 showSearchView(titleView); // 对软键盘及焦点的操作 doSomething(); break; } return false; } }); } private void doSomething() { et_search.setFocusable(false); if (isFocused) { Toast.makeText(Activity1.this, "获取焦点", Toast.LENGTH_SHORT).show(); et_input.setFocusable(true); et_input.setFocusableInTouchMode(true); et_input.requestFocus(); // 显示软键盘 operateKeyboard(KeyBoardType.show, container); } } /** * 隐藏软键盘 * * @param v */ private void operateKeyboard(KeyBoardType type, View v) { InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); if (type == KeyBoardType.show) imm.toggleSoftInput(0, InputMethodManager.SHOW_FORCED); else imm.hideSoftInputFromWindow(v.getWindowToken(), 0); setKeyboardDoneListener(); } private void setKeyboardDoneListener() { // 软键盘回车完成监听 et_input.setOnEditorActionListener(new OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { if (actionId == EditorInfo.IME_ACTION_DONE) { operateKeyboard(KeyBoardType.hide, v); Log.d("1111", "done"); // do something Toast.makeText(Activity1.this, et_input.getText().toString().trim(), Toast.LENGTH_SHORT).show(); return true; } return false; } }); } public void showSearchView(View view) { Animation translateAnimation = new TranslateAnimation(0, 0, 0, -getHeight(view)); translateAnimation.setDuration(300); container.startAnimation(translateAnimation); translateAnimation.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation arg0) { } @Override public void onAnimationRepeat(Animation arg0) { } @Override public void onAnimationEnd(Animation arg0) { TranslateAnimation anim = new TranslateAnimation(0, 0, 0, 0); container.setAnimation(anim); titleView.setVisibility(View.GONE); titleView.setPadding(0, -getHeight(titleView), 0, 0); // 显示隐藏的布局 searchView.setVisibility(View.VISIBLE); } }); } /** * */ private int getHeight(View view) { return view.getHeight(); } @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); Toast.makeText(this, "高度是:" + getHeight(titleView), Toast.LENGTH_SHORT).show(); } private void resetUI(View view) { operateKeyboard(KeyBoardType.hide, view); // 继续隐藏搜索布局 searchView.setVisibility(View.GONE); titleView.setPadding(0, 0, 0, 0); titleView.setVisibility(View.VISIBLE); Animation translateAnimation = new TranslateAnimation(0, 0, -getHeight(titleView), 0); translateAnimation.setDuration(300); container.startAnimation(translateAnimation); translateAnimation.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation arg0) { } @Override public void onAnimationRepeat(Animation arg0) { } @Override public void onAnimationEnd(Animation arg0) { TranslateAnimation anim = new TranslateAnimation(0, 0, 0, 0); container.setAnimation(anim); } }); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_cancel: isFocused = false; resetUI(v); break; default: break; } } }
/********************************************************** * @文件名称:Activity2.java * @创建时间:2014年11月22日 下午9:54:31 * @修改历史:2014年11月22日 **********************************************************/ package com.jinlin.searchview; import java.util.ArrayList; import java.util.List; import java.util.Timer; import java.util.TimerTask; import android.app.Activity; import android.content.Context; import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; import android.os.Bundle; import android.text.Editable; import android.text.TextWatcher; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup.LayoutParams; import android.view.animation.Animation; import android.view.animation.Animation.AnimationListener; import android.view.animation.TranslateAnimation; import android.view.inputmethod.InputMethodManager; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.EditText; import android.widget.ListView; import android.widget.PopupWindow; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; /** * @author J!nl!n * @date 2014年11月22日 * @time 下午9:54:31 * @type Activity2.java * @todo */ public class Activity2 extends Activity implements OnClickListener, OnItemClickListener, PopupWindow.OnDismissListener { private TextView tv_top_title; private ListView listView; private View headerView; private TextView tv_search; // show and hide private RelativeLayout mainLayout; private RelativeLayout titleBarLayout; private int moveHeight; private int statusBarHeight; // search popupwindow private PopupWindow popupWindow; private View searchView; private EditText searchEditText; private TextView cancelTextView; private ListView filterListView; private View alphaView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity2); tv_top_title = (TextView) findViewById(R.id.tv_top_title); tv_top_title.setText("我是第二种"); initCtrl(); } @Override public void onClick(View view) { switch (view.getId()) { case R.id.tv_search: showSearchBar(); break; case R.id.popup_window_tv_cancel: dismissPopupWindow(); break; case R.id.popup_window_v_alpha: dismissPopupWindow(); break; } } @Override public void onItemClick(AdapterView<?> viewGroup, View view, int position, long arg3) { switch (viewGroup.getId()) { case R.id.lv: if (position == 0) { showSearchBar(); } break; case R.id.popup_window_lv: Toast.makeText(Activity2.this, "click-" + position, Toast.LENGTH_LONG).show(); break; } } @Override public void onDismiss() { resetUI(); } private void initCtrl() { listView = (ListView) findViewById(R.id.lv); LayoutInflater mInflater = LayoutInflater.from(this); headerView = mInflater.inflate(R.layout.activity2_3_search, null); listView.addHeaderView(headerView); listView.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, getData())); listView.setOnItemClickListener(this); tv_search = (TextView) headerView.findViewById(R.id.tv_search); tv_search.setOnClickListener(this); mainLayout = (RelativeLayout) findViewById(R.id.main); titleBarLayout = (RelativeLayout) findViewById(R.id.title_bar_layout); searchView = mInflater.inflate(R.layout.popup_window_search, null); searchEditText = (EditText) searchView.findViewById(R.id.popup_window_et_search); searchEditText.setFocusable(true); searchEditText.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { if (s.toString().equals("")) { alphaView.setVisibility(View.VISIBLE); filterListView.setVisibility(View.GONE); } else { alphaView.setVisibility(View.GONE); filterListView.setVisibility(View.VISIBLE); } } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void afterTextChanged(Editable s) { } }); cancelTextView = (TextView) searchView.findViewById(R.id.popup_window_tv_cancel); cancelTextView.setOnClickListener(this); filterListView = (ListView) searchView.findViewById(R.id.popup_window_lv); filterListView.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, getData2())); filterListView.setOnItemClickListener(this); alphaView = searchView.findViewById(R.id.popup_window_v_alpha); alphaView.setOnClickListener(this); popupWindow = new PopupWindow(searchView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); popupWindow.setFocusable(true); popupWindow.setOutsideTouchable(true); popupWindow.setTouchable(true); popupWindow.setBackgroundDrawable(new BitmapDrawable()); popupWindow.setOnDismissListener(this); } private List<String> getData() { List<String> data = new ArrayList<String>(); for (int i = 0; i < 100; i++) { data.add("测试数据" + i); } return data; } private List<String> getData2() { List<String> data = new ArrayList<String>(); for (int i = 0; i < 100; i++) { data.add("搜索数据" + i); } return data; } private void getStatusBarHeight() { Rect frame = new Rect(); getWindow().getDecorView().getWindowVisibleDisplayFrame(frame); statusBarHeight = frame.top; } private void showSearchBar() { getStatusBarHeight(); moveHeight = titleBarLayout.getHeight(); Animation translateAnimation = new TranslateAnimation(0, 0, 0, -moveHeight); translateAnimation.setDuration(300); mainLayout.startAnimation(translateAnimation); translateAnimation.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation arg0) { } @Override public void onAnimationRepeat(Animation arg0) { } @Override public void onAnimationEnd(Animation arg0) { TranslateAnimation anim = new TranslateAnimation(0, 0, 0, 0); mainLayout.setAnimation(anim); titleBarLayout.setVisibility(View.GONE); titleBarLayout.setPadding(0, -moveHeight, 0, 0); popupWindow.showAtLocation(mainLayout, Gravity.CLIP_VERTICAL, 0, statusBarHeight); openKeyboard(); } }); } private void openKeyboard() { Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS); } }, 0); } private void dismissPopupWindow() { if (popupWindow != null && popupWindow.isShowing()) { popupWindow.dismiss(); } } private void resetUI() { titleBarLayout.setPadding(0, 0, 0, 0); titleBarLayout.setVisibility(View.VISIBLE); Animation translateAnimation = new TranslateAnimation(0, 0, -moveHeight, 0); translateAnimation.setDuration(300); mainLayout.startAnimation(translateAnimation); translateAnimation.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation arg0) { } @Override public void onAnimationRepeat(Animation arg0) { } @Override public void onAnimationEnd(Animation arg0) { TranslateAnimation anim = new TranslateAnimation(0, 0, 0, 0); mainLayout.setAnimation(anim); // titleBarLayout.setPadding(0, 0, 0, 0); } }); } }
/********************************************************** * @文件名称:Activity3.java * @创建时间:2014年11月22日 下午9:54:53 * @修改历史:2014年11月22日 **********************************************************/ package com.jinlin.searchview; import java.util.ArrayList; import java.util.List; import java.util.Timer; import java.util.TimerTask; import android.app.Activity; import android.content.Context; import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; import android.os.Bundle; import android.text.Editable; import android.text.TextWatcher; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup.LayoutParams; import android.view.animation.Animation; import android.view.animation.Animation.AnimationListener; import android.view.animation.TranslateAnimation; import android.view.inputmethod.InputMethodManager; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.PopupWindow; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; /** * @author J!nl!n * @date 2014年11月22日 * @time 下午9:54:53 * @type Activity3.java * @todo */ public class Activity3 extends Activity implements OnClickListener, OnItemClickListener, PopupWindow.OnDismissListener { private TextView tv_top_title; private ListView listView; private TextView tv_search; // show and hide private LinearLayout mainLayout; private RelativeLayout titleBarLayout; private int moveHeight; private int statusBarHeight; // search popupwindow private PopupWindow popupWindow; private View searchView; private EditText searchEditText; private TextView cancelTextView; private ListView filterListView; private View alphaView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity3); tv_top_title = (TextView) findViewById(R.id.tv_top_title); tv_top_title.setText("我是第三种"); initCtrl(); } @Override public void onClick(View view) { switch (view.getId()) { case R.id.tv_search: showSearchBar(); break; case R.id.popup_window_tv_cancel: dismissPopupWindow(); break; case R.id.popup_window_v_alpha: dismissPopupWindow(); break; } } @Override public void onItemClick(AdapterView<?> viewGroup, View view, int position, long arg3) { switch (viewGroup.getId()) { case R.id.lv: if (position == 0) { showSearchBar(); } break; case R.id.popup_window_lv: Toast.makeText(Activity3.this, "click-" + position, Toast.LENGTH_LONG).show(); break; } } @Override public void onDismiss() { resetUI(); } private void initCtrl() { listView = (ListView) findViewById(R.id.lv); LayoutInflater mInflater = LayoutInflater.from(this); listView.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, getData())); listView.setOnItemClickListener(this); tv_search = (TextView) findViewById(R.id.tv_search); tv_search.setOnClickListener(this); mainLayout = (LinearLayout) findViewById(R.id.mainLayout); titleBarLayout = (RelativeLayout) findViewById(R.id.title_bar_layout); searchView = mInflater.inflate(R.layout.popup_window_search, null); searchEditText = (EditText) searchView.findViewById(R.id.popup_window_et_search); searchEditText.setFocusable(true); searchEditText.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { if (s.toString().equals("")) { alphaView.setVisibility(View.VISIBLE); filterListView.setVisibility(View.GONE); } else { alphaView.setVisibility(View.GONE); filterListView.setVisibility(View.VISIBLE); } } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void afterTextChanged(Editable s) { } }); cancelTextView = (TextView) searchView.findViewById(R.id.popup_window_tv_cancel); cancelTextView.setOnClickListener(this); filterListView = (ListView) searchView.findViewById(R.id.popup_window_lv); filterListView.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, getData2())); filterListView.setOnItemClickListener(this); alphaView = searchView.findViewById(R.id.popup_window_v_alpha); alphaView.setOnClickListener(this); popupWindow = new PopupWindow(searchView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); popupWindow.setFocusable(true); popupWindow.setOutsideTouchable(true); popupWindow.setTouchable(true); popupWindow.setBackgroundDrawable(new BitmapDrawable()); popupWindow.setOnDismissListener(this); } private List<String> getData() { List<String> data = new ArrayList<String>(); for (int i = 0; i < 100; i++) { data.add("测试数据" + i); } return data; } private List<String> getData2() { List<String> data = new ArrayList<String>(); for (int i = 0; i < 100; i++) { data.add("搜索数据" + i); } return data; } private void getStatusBarHeight() { Rect frame = new Rect(); getWindow().getDecorView().getWindowVisibleDisplayFrame(frame); statusBarHeight = frame.top; } private void showSearchBar() { getStatusBarHeight(); moveHeight = titleBarLayout.getHeight(); Animation translateAnimation = new TranslateAnimation(0, 0, 0, -moveHeight); translateAnimation.setDuration(300); mainLayout.startAnimation(translateAnimation); translateAnimation.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation arg0) { } @Override public void onAnimationRepeat(Animation arg0) { } @Override public void onAnimationEnd(Animation arg0) { TranslateAnimation anim = new TranslateAnimation(0, 0, 0, 0); mainLayout.setAnimation(anim); titleBarLayout.setVisibility(View.GONE); titleBarLayout.setPadding(0, -moveHeight, 0, 0); popupWindow.showAtLocation(mainLayout, Gravity.CLIP_VERTICAL, 0, statusBarHeight); openKeyboard(); } }); } private void openKeyboard() { Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS); } }, 0); } private void dismissPopupWindow() { if (popupWindow != null && popupWindow.isShowing()) { popupWindow.dismiss(); } } private void resetUI() { titleBarLayout.setPadding(0, 0, 0, 0); titleBarLayout.setVisibility(View.VISIBLE); Animation translateAnimation = new TranslateAnimation(0, 0, -moveHeight, 0); translateAnimation.setDuration(300); mainLayout.startAnimation(translateAnimation); translateAnimation.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation arg0) { } @Override public void onAnimationRepeat(Animation arg0) { } @Override public void onAnimationEnd(Animation arg0) { TranslateAnimation anim = new TranslateAnimation(0, 0, 0, 0); mainLayout.setAnimation(anim); // titleBarLayout.setPadding(0, 0, 0, 0); } }); } }githib地址:https://github.com/5peak2me/QQSearchView