1. 程式人生 > >安卓仿BOSS直聘的那種選擇國家、地區和地區程式碼的列表

安卓仿BOSS直聘的那種選擇國家、地區和地區程式碼的列表

 最近在工作之餘,擠了點時間寫這篇部落格,是公司專案要實現一個功能,就是:選擇國家和地區還有對應的編號,類似於下拉選擇聯絡人的列表一樣的,上張圖:

這裡寫圖片描述

1.MainActivity

package com.city.list.main;

import java.io.File;
import java.util.ArrayList;

import com.city.list.db.DBManager;

import android.app.Activity;
import android.content.Intent;
import android.database.Cursor;
import
android.database.sqlite.SQLiteDatabase; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class MainActivity extends Activity { /** Called when the activity is first created. */ Button btn; @Override public
void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); btn = (Button) findViewById(R.id.selectBtn); btn.setOnClickListener(new OnClickListener() { @Override public void onClick
(View v) { startActivity(new Intent(MainActivity.this, CityList.class)); } }); } }

2.CityList

package com.city.list.main;

import android.app.Activity;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.city.list.db.DBManager;
import com.city.list.main.MyLetterListView.OnTouchingLetterChangedListener;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;


/**
 * 城市列表
 * 
 * @author sy
 * 
 */
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
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.city_list);

        mCityLit = (ListView) findViewById(R.id.city_list);
        letterListView = (MyLetterListView) findViewById(R.id.cityLetterListView);
        initHeaderView();
        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());

    }

    private void initHeaderView() {
        AbsListView.LayoutParams localLayoutParams = new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        View headerView = View.inflate(this, R.layout.header_view, null);
        headerView.setLayoutParams(localLayoutParams);
        mCityLit.addHeaderView(headerView);
    }

    /**
     * 從資料庫獲取城市資料
     * 
     * @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")));
            cityModel.setAreaCode(cursor.getString(cursor.getColumnIndex("AreaCode")));
            names.add(cityModel);
        }
        return names;
    }

    /**
     * 城市列表點選事件
     * 
     * @author sy
     * 
     */
    class CityListOnItemClick implements OnItemClickListener
    {

        @Override
        public void onItemClick(AdapterView<?> arg0, View arg1, int pos, long arg3)
        {
            if(pos!=0){
                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);
                holder.code = (TextView) convertView.findViewById(R.id.code);
                holder.view_item_top_line =convertView.findViewById(R.id.view_item_top_line);
                convertView.setTag(holder);
            } else
            {
                holder = (ViewHolder) convertView.getTag();
            }

            holder.name.setText(list.get(position).getCityName());
            holder.code.setText(list.get(position).getAreaCode());
            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);
                holder.view_item_top_line.setVisibility(View.GONE);
            } else
            {
                holder.alpha.setVisibility(View.GONE);
                holder.view_item_top_line.setVisibility(View.VISIBLE);
            }
            return convertView;
        }

        private class ViewHolder
        {
            TextView alpha;
            TextView name;
            TextView code;
            View view_item_top_line;
        }

    }

    // 初始化漢語拼音首字母彈出提示框
    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+1);
                overlay.setText(sections[position]);
                overlay.setVisibility(View.VISIBLE);
                handler.removeCallbacks(overlayThread);
                // 延遲一秒後執行,讓overlay為不可見

                handler.postDelayed(overlayThread, 700);
            }
        }

    }

    // 設定overlay不可見
    private class OverlayThread implements Runnable
    {

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

    }

}

3.CityModel

package com.city.list.main;

/**
 * 城市屬性實體類
 * @author sy
 *
 */
public class CityModel
{
    private String CityName; //城市名字
    private String NameSort; //城市首字母
    private String AreaCode; //地區編號

    public String getAreaCode() {
        return AreaCode;
    }

    public void setAreaCode(String areaCode) {
        AreaCode = areaCode;
    }



    public String getCityName()
    {
        return CityName;
    }

    public void setCityName(String cityName)
    {
        CityName = cityName;
    }

    public String getNameSort()
    {
        return NameSort;
    }

    public void setNameSort(String nameSort)
    {
        NameSort = nameSort;
    }

}

4. MyLetterListView

package com.city.list.main;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class MyLetterListView extends View
{

    OnTouchingLetterChangedListener onTouchingLetterChangedListener;
    String[] b = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z","#" };
    int choose = -1;
    Paint paint = new Paint();
    boolean showBkg = false;

    public MyLetterListView(Context context, AttributeSet attrs, int defStyle)
    {
        super(context, attrs, defStyle);
    }

    public MyLetterListView(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    }

    public MyLetterListView(Context context)
    {
        super(context);
    }

    @Override
    protected void onDraw(Canvas canvas)
    {
        super.onDraw(canvas);
        if (showBkg)
        {
            //canvas.drawColor(Color.parseColor("#f3c516"));
        }

        int height = getHeight();
        int width = getWidth();
        int singleHeight = height / b.length;
        for (int i = 0; i < b.length; i++)
        {
            paint.setColor(Color.parseColor("#f3c516"));
            paint.setTypeface(Typeface.DEFAULT_BOLD);
            paint.setAntiAlias(true);
            if (i == choose)
            {
                paint.setColor(Color.parseColor("#f3c516"));
                paint.setFakeBoldText(true);
            }
            float xPos = width / 2 - paint.measureText(b[i]) / 2;
            float yPos = singleHeight * i + singleHeight;
            paint.setTextSize(35);
            canvas.drawText(b[i], xPos, yPos, paint);
            paint.reset();
        }

    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event)
    {
        final int action = event.getAction();
        final float y = event.getY();
        final int oldChoose = choose;
        final OnTouchingLetterChangedListener listener = onTouchingLetterChangedListener;
        final int c = (int) (y / getHeight() * b.length);

        switch (action) {
        case MotionEvent.ACTION_DOWN:
            showBkg = true;
            if (oldChoose != c && listener != null)
            {
                if (c >= 0 && c < b.length)
                {
                    listener.onTouchingLetterChanged(b[c]);
                    choose = c;
                    invalidate();
                }
            }

            break;
        case MotionEvent.ACTION_MOVE:
            if (oldChoose != c && listener != null)
            {
                if (c >= 0 && c < b.length)
                {
                    listener.onTouchingLetterChanged(b[c]);
                    choose = c;
                    invalidate();
                }
            }
            break;
        case MotionEvent.ACTION_UP:
            showBkg = false;
            choose = -1;
            invalidate();
            break;
        }
        return true;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
        return super.onTouchEvent(event);
    }

    public void setOnTouchingLetterChangedListener(OnTouchingLetterChangedListener onTouchingLetterChangedListener)
    {
        this.onTouchingLetterChangedListener = onTouchingLetterChangedListener;
    }

    public interface OnTouchingLetterChangedListener
    {
        public void onTouchingLetterChanged(String s);
    }

}

5.還需要將raw中得資料庫檔案寫入到data資料庫中

package com.city.list.db;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.os.Environment;

import com.city.list.main.R;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * 將raw中得資料庫檔案寫入到data資料庫中
 * @author sy
 *
 */
public class DBManager
{
    private final int BUFFER_SIZE = 400000;
    private static final String PACKAGE_NAME = "com.city.list.main";
    public static final String DB_NAME = "china_city_name.db";
    public static final String DB_PATH = "/data" + Environment.getDataDirectory().getAbsolutePath() + "/" + PACKAGE_NAME ; // 存放路徑
    private Context mContext;
    private SQLiteDatabase database;

    public DBManager(Context context)
    {
        this.mContext = context;
    }

    /**
     * 被呼叫方法
     */
    public void openDateBase()
    {
        this.database = this.openDateBase(DB_PATH + "/" + DB_NAME);

    }

    /**
     * 開啟資料庫
     * 
     * @param dbFile
     * @return SQLiteDatabase
     * @author sy
     */
    private SQLiteDatabase openDateBase(String dbFile)
    {
        File file = new File(dbFile);
        if (!file.exists())
        {
            // // 開啟raw中得資料庫檔案,獲得stream流
            InputStream stream = this.mContext.getResources().openRawResource(R.raw.china_city_name);
            try
            {

                // 將獲取到的stream 流寫入道data中
                FileOutputStream outputStream = new FileOutputStream(dbFile);
                byte[] buffer = new byte[BUFFER_SIZE];
                int count = 0;
                while ((count = stream.read(buffer)) > 0)
                {
                    outputStream.write(buffer, 0, count);
                }
                outputStream.close();
                stream.close();
                SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(dbFile, null);
                return db;
            } catch (FileNotFoundException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return database;
    }

    public void closeDatabase()
    {
        if (database != null && database.isOpen())
        {
            this.database.close();
        }
    }
}

差不多了,還有一些佈局檔案和raw資料夾下的檔案沒顯示,全在專案包下,已經把專案提交到了GitHub上:https://github.com/xinyitiandi/CityList,有哪些不足之處,大家可以指正哦,這次寫的匆忙,沒有加太多的文字說明,實在沒有太多的時間了,請大家諒解!