一个小的自定义的触摸控件,类似于联系人列表

来源:互联网 发布:java 工作流开发 编辑:程序博客网 时间:2024/05/21 13:23

这是一个自定义的触摸控件。这里做的触摸控件根据城市的首字母让列表选中相应的城市。下面放一张截图

写这个的心态就是,当时想要做这个功能。但是网上我找到的方法都很麻烦。所以干脆自己写了个控件。感觉挺简单的。

这里没有去完善它。只是实现了基本的功能。比如背景,文字颜色,并没有绘制。(直接代码里该比较痛快>o<)

mydemo.jpg

然后就是自定义控件的代码,我把注释写的比较详细。

package com.example.testcityselect;import android.content.Context;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.Rect;import android.util.AttributeSet;import android.util.Log;import android.view.GestureDetector;import android.view.MotionEvent;import android.view.View;public class MyView extends View {private GestureDetector gestureDetector;// 这个是用于引用手势探测器的public MyView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);// TODO Auto-generated constructor stub}public MyView(Context context, AttributeSet attrs) {super(context, attrs);// TODO Auto-generated constructor stubmContext = (MainActivity) context;// 将context对象强制转换为mContext对象gestureDetector = new GestureDetector(context, new GestureListener(),null, true);// 初始化手势探测器,其中第二个参数是本类中定义的类,继承自}private MainActivity mContext;// 由于例子中调用了MainActivity中定义方法,(用以修改居中的TextView的值)所以需要这个引用private int oneHeight;// 指每一个字母的高度public MyView(Context context) {super(context);// 调用父类View类默认构造方法}@Overrideprotected void onDraw(Canvas canvas) {// TODO Auto-generated method stubLog.e("tag", getHeight()+"/"+getWidth());Paint paint = new Paint();// paint.setARGB(200, 180, 170, 45);paint.setTextSize(20);// 设置字体的大小// canvas.drawColor(Color.CYAN);Paint bgPaint = new Paint();bgPaint.setARGB(255, 255, 255, 255);// 绘制背景的颜色Rect rect=new Rect();getLocalVisibleRect(rect);canvas.drawRect(rect, bgPaint);oneHeight=(rect.bottom-rect.top)/26;paint.setARGB(255, 0, 0, 0);// 设置字母的颜色paint.setTextSize(20);for (int i = 1; i < 27; i++) {canvas.drawText((char) (i + 64) + "", rect.left+getWidth()/2-10, oneHeight * i, paint);}// 利用for循环绘制字母}@Overridepublic boolean onTouchEvent(MotionEvent event) {// TODO Auto-generated method stubboolean retVal = false;retVal = gestureDetector.onTouchEvent(event);return retVal;}// 覆盖这个方法是为了让组件响应触摸事件/** * public void onUpDown(int i) { mContext.setText((char) i + ""); * invalidate(); } 之前的想法是应该分为向上向下滑动,但后来直接使用一个for循环,即记录下当前手指所在高度。 **/private class GestureListener extendsGestureDetector.SimpleOnGestureListener {@Overridepublic boolean onDown(MotionEvent e) {// TODO Auto-generated method stub// Toast.makeText(context, e.getX() + "," + e.getY(),// Toast.LENGTH_SHORT).show();int i = 1;for (; i < 26; i++) {if (e.getY() < (oneHeight) * i) {break;}}// 这里。手指按下后执行这个for循环,找出最接近的字母mContext.setText(i + 64);return true;}@Overridepublic boolean onScroll(MotionEvent e1, MotionEvent e2,float distanceX, float distanceY) {// TODO Auto-generated method stub// x = e1.getX() + droid.getWidth();// y = e1.getY();for (int i = 1; i < 27; i++) {if (e2.getY() < (oneHeight) * i) {mContext.setText(i + 64);break;}}// 这里。只要手指移动都会改变str的值return true;}}}
之后是布局文件

<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"    tools:context="com.example.testcityselect.MainActivity" >    <TextView          android:id="@+id/tv_hello"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="@string/hello_world"         android:layout_centerInParent="true"        android:textSize="50dp"/>    <ListView        android:id="@+id/lv_city_select"        android:layout_width="match_parent"        android:layout_height="match_parent" >    </ListView>    <com.example.testcityselect.MyView android:layout_width="20dp"        android:layout_height="match_parent"        android:layout_alignParentRight="true"        android:layout_margin="5dp"        /></RelativeLayout>

然后主Activity,这里没有什么特殊的。城市的信息是放在一个本地json文件中的

排序是根据汉字的首字母对应的字母的int值。这里根据汉字获取拼音是用了网路上分享的一个工具HanziToPinyin.就不贴出来了,

(貌似HanziToPinyin有个bug重庆获取到的首字母是Z)

然后这里的setText方法。是在上面的自定义控件中调用的。主要功能是设置中间的文本框显示字母,和让列表选中相应的字母列

然后还有个timer类。是让textview隐藏的。就是实现不点击控件的状态。textview隐藏

import android.widget.TextView;import android.widget.Toast;public class MainActivity extends Activity {private ArrayAdapter<String> cityAdapter;private ListView lvContactList;private List<CityInfo> cityList;private TextView tv_hello;private MyView view;private Map<Integer, Integer> cityMap;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);lvContactList = (ListView) findViewById(R.id.lv_city_select);cityList = new ArrayList<CityInfo>();cityMap = new HashMap<Integer, Integer>();HanziToPinyin tools = new HanziToPinyin(true);InputStreamReader inputStream = new InputStreamReader(getResources().openRawResource(R.raw.json_simple_name));BufferedReader reader = new BufferedReader(inputStream);try {String json = reader.readLine();reader.close();JSONArray jsonArray = new JSONArray(json);for (int i = 0; i < jsonArray.length(); i++) {JSONObject jsonObj = jsonArray.getJSONObject(i);String city = jsonObj.getString("city");String s = tools.get(jsonObj.getString("city")).get(0).target;int temp = s.charAt(0);// data.add(temp+"");cityList.add(new CityInfo(temp, city));}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (JSONException e) {// TODO Auto-generated catch blocke.printStackTrace();}Collections.sort(cityList);cityAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_expandable_list_item_1);cityAdapter.add((char) cityList.get(0).getNum() + "");cityAdapter.add(cityList.get(0).getCity());cityMap.put(cityList.get(0).getNum(), 0);for (int i = 1, count = 1; i < cityList.size(); i++) {if (cityList.get(i).getNum() != cityList.get(i - 1).getNum()) {cityAdapter.add((char) cityList.get(i).getNum() + "");cityMap.put(cityList.get(i).getNum(), ++count);}cityAdapter.add(cityList.get(i).getCity());count++;}lvContactList.setAdapter(cityAdapter);tv_hello = (TextView) findViewById(R.id.tv_hello);tv_hello.setVisibility(View.GONE);lvContactList.setOnItemClickListener(new OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view,int position, long id) {// TODO Auto-generated method stubString str = cityAdapter.getItem(position);if (str.length() > 1)Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();}});}public void setText(int i) {tv_hello.setText((char) i + "");Integer a = cityMap.get(i);if (a != null)lvContactList.setSelection(a);tv_hello.setVisibility(View.VISIBLE);final Timer timer=new Timer();timer.schedule(new TimerTask() {@Overridepublic void run() {// TODO Auto-generated method stubhandler.sendEmptyMessage(0);timer.cancel();}}, 2000); }Handler handler=new Handler(new Handler.Callback() {@Overridepublic boolean handleMessage(Message msg) {// TODO Auto-generated method stub.if(msg.what==0)tv_hello.setVisibility(View.GONE);return false;}});}

实体类覆盖了用于排序的方法


package com.example.testcityselect;public class CityInfo implements Comparable<CityInfo> {int num;String city;public CityInfo(int num, String city) {super();this.num = num;this.city = city;}@Overridepublic int compareTo(CityInfo another) {// TODO Auto-generated method stubif (this.num < another.num) {return -1;} else if (this.num > another.num) {return 1;}return 0;}public int getNum() {return num;}public String getCity() {return city;}}
ps:代码全部贴上来。只有那个汉字转拼音的类。因为不是我写的就没有贴。



0 0
原创粉丝点击