【Android开发那些事】自定义弹出框(搜寻,登陆)

【Android开发那些事】自定义弹出框(搜索,登陆)

做过web开发的同学肯定知道,ajax查询结果的样式,比如google大神的首页效果:

【Android开发那些事】自定义弹出框(搜寻,登陆)

现在我们需要在Android中实现同样的效果。OK, follow me..

首先来看下我已经实现好的效果。

没输入关键字前:

【Android开发那些事】自定义弹出框(搜寻,登陆)

输入关键字a,返回所有结果,并且用一个弹出框显示所有结果:

【Android开发那些事】自定义弹出框(搜寻,登陆)

好了,我们来看下Android中如何实现展示列表弹出框:

原理是监听textview的事件,当textview的text改变了,我们就去请求后台,并且接收返回的结果,有了结果之后,再利用我们自定义的弹出框来展示这些结果集。

首先在你的layout里面定义一个TextView,

<EditText 
            android:id="@+id/edit_search"
            android:layout_width="0dip"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:drawableLeft="@drawable/category_search_btn"
            android:gravity="left|center"
            android:hint="@string/search_placeholder"
            android:textAppearance="?android:textAppearanceMedium" />

然后在activity里获取到此textview,绑定其事件:

// search function
		searchTextView = (TextView) findViewById(R.id.edit_search);
		searchTextView.addTextChangedListener(new TextWatcher() {
			@SuppressWarnings("unchecked")
			@Override
			public void afterTextChanged(Editable arg0) {
				String keyword = searchTextView.getText().toString().trim();
				QuhaoLog.i(TAG, keyword);
				try {
					String result = CommonHTTPRequest
							.get("MerchantController/getMerchantsByName?name="
									+ keyword);
					if (result.equalsIgnoreCase("null")) {
						QuhaoLog.i(TAG, "no result");
					} else {
						QuhaoLog.i(TAG, result);
						mList = (List<Merchant>) ParseJson
								.getMerchants(result);
						for (Merchant m : mList) {
							QuhaoLog.i(TAG, m.name);
						}
						createView();
					}
				} catch (ClientProtocolException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}

			@Override
			public void beforeTextChanged(CharSequence arg0, int arg1,
					int arg2, int arg3) {
				// TODO Auto-generated method stub
			}

			@Override
			public void onTextChanged(CharSequence arg0, int arg1, int arg2,
					int arg3) {
				// TODO Auto-generated method stub
			}

		});

在textchangedListener里面我们去请求了服务器端的代码,然后获取到一个List,完了之后调用了createView()方法,此方法就是用服务器端返回的结果集结合我们自定义的弹出框进行展示:

这里是createView方法:

/**
	 * called when user input something in search box
	 * @param mList
	 */
	private void createView() {
		int[] location = new int[2];
		searchTextView.getLocationOnScreen(location);
		int height = searchTextView.getHeight();

		searchResultView = new CommonFloatView(getApplicationContext());
		searchResultView.setBackgroundColor(Color.RED);
		searchResultView.getBackground().setAlpha(80);
		searchResultView.setVerticalScrollBarEnabled(true);
		searchResultView.setAdapter(new SearchAdapter(searchResultView, mList));
		searchResultView.setOnItemClickListener(new OnItemClickListener(){
			@Override
			public void onItemClick(AdapterView<?> arg0, View arg1, int index,
					long arg3) {
				destroyView();
				Merchant merchant = mList.get(index);
				QuhaoLog.i(TAG, "merchant.name: "+merchant.name);
				Intent intent = new Intent();
				intent.putExtra("merchantId", merchant.id);
				intent.setClass(MainActivity.this,
						MerchantDetailActivity.class);
				startActivity(intent);
			}
		});

		// 获取WindowManager
		wm = (WindowManager) getApplicationContext().getSystemService("window");
		wmParams = ((QHClientApplication) getApplication()).getMywmParams();

		// 设置LayoutParams(全局变量)相关参数
		wmParams.type = LayoutParams.MATCH_PARENT; // 设置window type
		wmParams.format = PixelFormat.RGBA_8888; // 设置图片格式,效果为背景透明
		wmParams.gravity = Gravity.LEFT | Gravity.TOP; // 调整悬浮窗口至左上角
		// 以屏幕左上角为原点,设置x、y初始值
		wmParams.x = 0;
		wmParams.y = height;
		QuhaoLog.i(TAG, "float y: " + wmParams.y);
		
		// 设置悬浮窗口长宽数据
		wmParams.width = LayoutParams.MATCH_PARENT;
		wmParams.height = 500;

		// 显示myFloatView图像
		wm.addView(searchResultView, wmParams);
	}

看这里的CommonFloatView,这个就是我们自定义的弹出框, 我这里继承了ListView,因为我的结果集我要放在一个ListView中。而且这个也可以实现那种悬浮窗口的。

import android.content.Context;
import android.util.Log;
import android.view.MotionEvent;
import android.view.WindowManager;
import android.widget.ListView;

import com.withiter.quhao.QHClientApplication;
import com.withiter.quhao.util.QuhaoLog;

public class CommonFloatView extends ListView {

	private float mTouchStartX;
	private float mTouchStartY;
	private float x;
	private float y;
	private static final String TAG = CommonFloatView.class.getName();

	private WindowManager wm = (WindowManager) getContext()
			.getApplicationContext().getSystemService("window");

	// 此wmParams为获取的全局变量,用以保存悬浮窗口的属性
	private WindowManager.LayoutParams wmParams = ((QHClientApplication) getContext()
			.getApplicationContext()).getMywmParams();

	public CommonFloatView(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
	}

//	@Override
//	public boolean onTouchEvent(MotionEvent event) {
//		return move(event);
//	}
	
	
	private boolean move(MotionEvent event){
		// getRawX()获取相对屏幕的坐标,即以屏幕左上角为原点
				x = event.getRawX();
				y = event.getRawY() - 25; // 25是系统状态栏的高度
				QuhaoLog.i(TAG, "currX" + x + "====currY" + y);
				switch (event.getAction()) {
				case MotionEvent.ACTION_DOWN:
					// getX()获取相对View的坐标,即以此View左上角为原点
					mTouchStartX = event.getX();
					mTouchStartY = event.getY();

					QuhaoLog.i(TAG, "startX" + mTouchStartX + "====startY"
							+ mTouchStartY);

					break;
				case MotionEvent.ACTION_MOVE:
					updateViewPosition();
					break;

				case MotionEvent.ACTION_UP:
					updateViewPosition();
					mTouchStartX = mTouchStartY = 0;
					break;
				}
				return true;
	}

	private void updateViewPosition() {
		// 更新浮动窗口位置参数,x是鼠标在屏幕的位置,mTouchStartX是鼠标在图片的位置
		wmParams.x = (int) (x - mTouchStartX);
		wmParams.y = (int) (y - mTouchStartY);
		wm.updateViewLayout(this, wmParams);
		
		QuhaoLog.i(TAG, "wmParams.x:"+wmParams.x);
		QuhaoLog.i(TAG, "wmParams.y"+wmParams.y);

	}
}

其实最主要的代码是这里的代码:

// 获取WindowManager
		wm = (WindowManager) getApplicationContext().getSystemService("window");
		wmParams = ((QHClientApplication) getApplication()).getMywmParams();

		// 设置LayoutParams(全局变量)相关参数
		wmParams.type = LayoutParams.MATCH_PARENT; // 设置window type
		wmParams.format = PixelFormat.RGBA_8888; // 设置图片格式,效果为背景透明
		wmParams.gravity = Gravity.LEFT | Gravity.TOP; // 调整悬浮窗口至左上角
		// 以屏幕左上角为原点,设置x、y初始值
		wmParams.x = 0;
		wmParams.y = height;
		QuhaoLog.i(TAG, "float y: " + wmParams.y);
		
		// 设置悬浮窗口长宽数据
		wmParams.width = LayoutParams.MATCH_PARENT;
		wmParams.height = 500;

		// 显示myFloatView图像
		wm.addView(searchResultView, wmParams);

通过WindowsManager来添加悬浮框的属性。更多关于悬浮框的信息,可以去看下Android的WindowsManager。这里面的属性特别多。