2014-10-27Android学习------布局处理(八)------自定义吐司(Toast)-----城市列表应用程序

写一篇文章很辛苦啊!!!

转载请注明,联系请邮件nlp30508@qq.com


我学习Android都是结合源代码去学习,这样比较直观,非常清楚的看清效果,觉得很好,今天的学习源码是网上找的个CityList 源码 百度搜就知道很多下载的地方

上篇文章  地址:http://blog.csdn.net/u014737138/article/details/40589131

有时候我们需要在视图上面提示一个小方框,上面弹出一个提示   

先看下效果是怎么样的:


例如图中的  蓝色的大    D   

我们需要实现的就是这样的自定义的吐司(Toast)

布局文件该怎么处理呢:

code:

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:background="#ffffff" 背景白色
    android:gravity="center"
    android:maxWidth="80dip"
    android:minWidth="80dip"
    android:padding="5dip"
    android:textColor="#3399ff"  蓝色的字体
    android:textSize="70sp" />   字体大小为70sp

Eclipse里面的效果:


就这样完了,然后我们需要去使用它,看看是怎么操作的:

1.在activity中声明:

private TextView overlay;

2.初始化的时候我们需要从资源文件找到这个控件

	private void initOverlay()
	{
		LayoutInflater inflater = LayoutInflater.from(this);
		overlay = (TextView) inflater.inflate(R.layout.overlay, null);
		overlay.setVisibility(View.INVISIBLE);
		WindowManager.LayoutParams lp = new WindowManager.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
				WindowManager.LayoutParams.TYPE_APPLICATION, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
				PixelFormat.TRANSLUCENT);
		WindowManager windowManager = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);
		windowManager.addView(overlay, lp);
	}

自定义这个吐司的时候我们是没有设置它的宽高的,上面的图片提示了没有设置宽高,原来我们需要在这个位置来设置。

import android.view.WindowManager;

这里我从Android文档里面找出这些变量的意义出来  大家看看就这个这个变量是什么意思了:


对应这一句:

WindowManager windowManager = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);

this指的是当前的activity的上下文,


对应这一句:

windowManager.addView(overlay, lp);

这两个参数好解释:Android中任何一个widget都可以看做是一个View对象,包括自定义的

那么接下来就是需要去写出lp对应的对象就行了,lp的类型是:ViewGroup.LayoutParams   

前面的那张图给我展示了WindowManager是实现了ViewManager的,

下面的这张图可以看出  WindowManager.LayoutParams 是实现了ViewGroup.LayoutParams的


下面这张图给我们展示他的构造函数:


我们选择的构造函数正好就是框起来的那条

接下来就是看各个参数是什么意思了:





到这里就结束了。

说白了这个初始化函数就是在当前的窗体上添加一个视图   :这个视图就是我们自定义的吐司(Toast)

这里也告诉我们一点:如果我们想去实现某个方法,从Android的文档中去找 我们需要的东西是最合适的,如果谁把Android的文档搞的精通 ,它一定是大牛中的大牛!!!!!


3.使用它的时候

overlay.setText(sections[position]);//设置文本
overlay.setVisibility(View.VISIBLE);//设置可见


就这样我们就简单的搞完了这个效果,但是这个时候肯定有人说,你是怎么做到像系统提供的吐司(Toast)那样,显示一会儿它就自动消失了呢,

这个也简单,我们需要做个显示的时间处理就可以了,定义一个线程来解决这个问题


第一步:

首先用这个控件的名字定义一个线程类  实现Runable接口

// 设置overlay不可见
private class OverlayThread implements Runnable
{
@Override
public void run()
{
overlay.setVisibility(View.GONE);
}
}

int android.view.View.GONE = 8 [0x8]



public static final int GONE 
Since: API Level 1 
This view is invisible, and it doesn't take any space for layout purposes. Use with setVisibility(int). 

说白了重载run()函数,让这个控件显示不可见  使用GONE变量的好处是下面这个:

INVISIBLE:仍旧会占用空间,只是内容不显示。GONE:不会占用空间。
这里我们还有明白一点就是:在当前的视图上面显示一个小吐司,消息(UI)更新是由当前的activity主线程来执行呢,还是由子线程来执行呢?
一般来说Android里面更新视图的功能都是由主线程来执行的,但是它执行的时间间隔相当的短,好像只有6秒,如果超过这个时间的话,应用程序会出现anr异常的。一般我们是使用子线程去去处理这个消息,处理完之后告诉主线程,让它去更新。
说的不是很对,如果不对,请指出。还在学习中!!!
所有我们就采用子线程去负责它显示的时间了,
自己创建的线程该怎么去调用他们呢,这里就需要用到一个类   Handler  
我们先简单的说明一下:知道它是干什么的就可以去理解,下次有机会在详细介绍它的用法和作用
HandlerAndroid中是很常用的,或是用来更新UI,或是派发任务给子线程去执行,也可以用来产生超时效果,比如用sendMessageDelayed(TASK_TIMEOUT, OUT_TIME)方法

多余的话不说了,直接看代码说来的明白些:
1.在activity中定义一个Handler对象
private Handler handler;
2.初始化
handler = new Handler();
3.使用
handler.removeCallbacks(overlayThread);
// 延迟一秒后执行,让overlay为不可见
handler.postDelayed(overlayThread, 1500);
这个函数的源代码全部:
	private class LetterListViewListener implements OnTouchingLetterChangedListener
	{

		@Override
		public void onTouchingLetterChanged(final String s)
		{
			if (alphaIndexer.get(s) != null)
			{
				int position = alphaIndexer.get(s);
				mCityLit.setSelection(position);
				overlay.setText(sections[position]);
				overlay.setVisibility(View.VISIBLE);
				handler.removeCallbacks(overlayThread);
				// 延迟1.5秒后执行,让overlay为不可见
				handler.postDelayed(overlayThread, 1500);
			}
		}

	}


这里要说道了:postDelayed方法和removeCallbacks方法的区别是什么?为什么这里这样设置呢?他们有什么作用呢?
方法removeCallbacks方法是删除指定的Runnable对象,使线程对象停止运行:首先我们为什么要让这个线程停止运行呢?因为这个是个内部类,上一步我们有可能已经触摸了某个字母的,这个线程是在运行着的,当我们再触摸一个字母的时候,我们需要先让这个线程对象停止掉,
方法postDelayed的作用是延迟多少毫秒后开始运行:这个函数的作用就是让这个线程延迟1.5秒再执行,也就是我的控件先显示1.5秒,然后子线程告诉我,这个控件不能显示了。
它的原型:
 
 
  1. public final boolean postDelayed (Runnable r, long delayMillis) 

其中参数Runnable r在Handler对象所运行的线程中执行。
到此为止   这个自定义的吐司从创建到使用基本就介绍完了,它的源代码:

转载请注明,联系请邮件nlp30508@qq.com

public class CityList extends Activity {
	
	private BaseAdapter adapter;
	private ListView mCityLit;
	private TextView overlay;
	private MyLetterListView letterListView;
	private HashMap<String, Integer> alphaIndexer;// 存放存在的汉语拼音首字母和与之对应的列表位置
	private String[] sections;// 存放存在的汉语拼音首字母
	private Handler handler;
	private OverlayThread overlayThread;
	private SQLiteDatabase database;
	private ArrayList<CityModel> mCityNames;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.city_list);
		
		mCityLit = (ListView) findViewById(R.id.city_list);
		letterListView = (MyLetterListView) findViewById(R.id.cityLetterListView);
		DBManager dbManager = new DBManager(this);
		dbManager.openDateBase();
		dbManager.closeDatabase();
		database = SQLiteDatabase.openOrCreateDatabase(DBManager.DB_PATH + "/" + DBManager.DB_NAME, null);
		mCityNames = getCityNames();
		database.close();
		letterListView.setOnTouchingLetterChangedListener(new LetterListViewListener());
		alphaIndexer = new HashMap<String, Integer>();
		handler = new Handler();
		overlayThread = new OverlayThread();
		initOverlay();
		setAdapter(mCityNames);
		mCityLit.setOnItemClickListener(new CityListOnItemClick());
	}
	
	/**
	 * 从数据库获取城市数据
	 * 
	 * @return
	 */
	private ArrayList<CityModel> getCityNames()
	{
		ArrayList<CityModel> names = new ArrayList<CityModel>();
		Cursor cursor = database.rawQuery("SELECT * FROM T_City ORDER BY NameSort", null);
		for (int i = 0; i < cursor.getCount(); i++)
		{
			cursor.moveToPosition(i);
			CityModel cityModel = new CityModel();
			cityModel.setCityName(cursor.getString(cursor.getColumnIndex("CityName")));
			cityModel.setNameSort(cursor.getString(cursor.getColumnIndex("NameSort")));
			names.add(cityModel);
		}
		return names;
	}
	
	/**
	 * 城市列表点击事件
	 * 
	 * @author sy
	 * 
	 */
	class CityListOnItemClick implements OnItemClickListener
	{

		@Override
		public void onItemClick(AdapterView<?> arg0, View arg1, int pos, long arg3)
		{
			CityModel cityModel = (CityModel) mCityLit.getAdapter().getItem(pos);
			Toast.makeText(CityList.this, cityModel.getCityName(), Toast.LENGTH_SHORT).show();
		}

	}
	
	/**
	 * 为ListView设置适配器
	 * 
	 * @param list
	 */
	private void setAdapter(List<CityModel> list)
	{
		if (list != null)
		{
			adapter = new ListAdapter(this, list);
			mCityLit.setAdapter(adapter);
		}

	}
	
	/**
	 * ListViewAdapter
	 * 
	 * @author sy
	 * 
	 */
	private class ListAdapter extends BaseAdapter
	{
		private LayoutInflater inflater;
		private List<CityModel> list;

		public ListAdapter(Context context, List<CityModel> list)
		{

			this.inflater = LayoutInflater.from(context);
			this.list = list;
			alphaIndexer = new HashMap<String, Integer>();
			sections = new String[list.size()];

			for (int i = 0; i < list.size(); i++)
			{
				// 当前汉语拼音首字母
				// getAlpha(list.get(i));
				String currentStr = list.get(i).getNameSort();
				// 上一个汉语拼音首字母,如果不存在为“ ”
				String previewStr = (i - 1) >= 0 ? list.get(i - 1).getNameSort() : " ";
				if (!previewStr.equals(currentStr))
				{
					String name = list.get(i).getNameSort();
					alphaIndexer.put(name, i);
					sections[i] = name;
				}
			}

		}

		@Override
		public int getCount()
		{
			return list.size();
		}

		@Override
		public Object getItem(int position)
		{
			return list.get(position);
		}

		@Override
		public long getItemId(int position)
		{
			return position;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent)
		{
			ViewHolder holder;
			if (convertView == null)
			{
				convertView = inflater.inflate(R.layout.list_item, null);
				holder = new ViewHolder();
				holder.alpha = (TextView) convertView.findViewById(R.id.alpha);
				holder.name = (TextView) convertView.findViewById(R.id.name);
				convertView.setTag(holder);
			} else
			{
				holder = (ViewHolder) convertView.getTag();
			}

			holder.name.setText(list.get(position).getCityName());
			String currentStr = list.get(position).getNameSort();
			String previewStr = (position - 1) >= 0 ? list.get(position - 1).getNameSort() : " ";
			if (!previewStr.equals(currentStr))
			{
				holder.alpha.setVisibility(View.VISIBLE);
				holder.alpha.setText(currentStr);
			} else
			{
				holder.alpha.setVisibility(View.GONE);
			}
			return convertView;
		}

		private class ViewHolder
		{
			TextView alpha;
			TextView name;
		}

	}
	
	// 初始化汉语拼音首字母弹出提示框
	private void initOverlay()
	{
		LayoutInflater inflater = LayoutInflater.from(this);
		overlay = (TextView) inflater.inflate(R.layout.overlay, null);
		overlay.setVisibility(View.INVISIBLE);
		WindowManager.LayoutParams lp = new WindowManager.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
				WindowManager.LayoutParams.TYPE_APPLICATION, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
				PixelFormat.TRANSLUCENT);
		WindowManager windowManager = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);
		windowManager.addView(overlay, lp);
	}
	
	private class LetterListViewListener implements OnTouchingLetterChangedListener
	{

		@Override
		public void onTouchingLetterChanged(final String s)
		{
			if (alphaIndexer.get(s) != null)
			{
				int position = alphaIndexer.get(s);
				mCityLit.setSelection(position);
				overlay.setText(sections[position]);
				overlay.setVisibility(View.VISIBLE);
				handler.removeCallbacks(overlayThread);
				// 延迟一秒后执行,让overlay为不可见
				handler.postDelayed(overlayThread, 1500);
			}
		}

	}
	
	// 设置overlay不可见
	private class OverlayThread implements Runnable
	{

		@Override
		public void run()
		{
			overlay.setVisibility(View.GONE);
		}

	}
	
	

}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值