写一篇文章很辛苦啊!!!
转载请注明,联系请邮件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
我们先简单的说明一下:知道它是干什么的就可以去理解,下次有机会在详细介绍它的用法和作用
Handler在Android中是很常用的,或是用来更新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秒,然后子线程告诉我,这个控件不能显示了。
它的原型:
- 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);
}
}
}