2015/9/9/3

startActivityForResult与startActivity的不同之处

1、startActivity( )
仅仅是跳转到目标页面,若是想跳回当前页面,则必须再使用一次startActivity( )。
2、startActivityForResult( )
可以一次性完成这项任务,当程序执行到这段代码的时候,假若从T1Activity跳转到下一个T2Activity,而当这个T2Activity调用了finish()方法以后,程序会自动跳转回T1Activity,并调用前一个T1Activity中的onActivityResult( )方法。

Intent toChooseCityActivity=new Intent(this,ChooseCityActivity.class);
            startActivityForResult(toChooseCityActivity, 1);

startActivityForResult( )第一个Intent,第二个是个标识,但一定要>=0。

2.重写onActivityResult方法,用来接收B回传的数据。

 @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == 2){
        if (data != null){
            tvCity.setText(data.getStringExtra("city"));
        }
    }

3.在B中回传数据时采用setResult方法,并且之后要调用finish方法。

setResult(RESULT_OK, intent); //intent为A传来的带有Bundle的intent,当然也可以自己定义新的Bundle
finish();//此处一定要调用finish()方法

Android activity的setResult()在什么时候调用(重点也是难点)

如果在startActivityForResult起来的Activity里面设置setResult,结果并不会马上返回给parent的Activity,只有当前Activity被finish,结果才会被发送给parent的onActivityResult去处理!

2015/9/9-2

2015/9/9问题集

Android 带清除功能的输入框控件ClearEditText,仿IOS的输入框

出处http://blog.csdn.net/xiaanming/article/details/11066685

就是在Android系统的输入框右边加入一个小图标,点击小图标可以清除输入框里面的内容,IOS上面直接设置某个属性就可以实现这一功能,但是Android原生EditText不具备此功能,所以要想实现这一功能我们需要重写EditText,接下来就带大家来实现这一小小的功能
我们知道,我们可以为我们的输入框在上下左右设置图片,所以我们可以利用属性android:drawableRight设置我们的删除小图标

如果我们能为右边的图片设置监听,点击右边的图片清除输入框的内容并隐藏删除图标,这样子这个小功能就迎刃而解了,可是Android并没有给允许我们给右边小图标加监听的功能,这时候你是不是发现这条路走不通呢,其实不是,我们可能模拟点击事件,用输入框的的onTouchEvent()方法来模拟,
当我们触摸抬起(就是ACTION_UP的时候)的范围 大于输入框左侧到清除图标左侧的距离,小与输入框左侧到清除图片右侧的距离,我们则认为是点击清除图片,当然我这里没有考虑竖直方向,只要给清除小图标就上了监听,其他的就都好处理了

ClearEditText的代码

package com.zsz.develop.clearedittextdemo;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnFocusChangeListener;
import android.view.animation.Animation;
import android.view.animation.CycleInterpolator;
import android.view.animation.TranslateAnimation;
import android.widget.EditText;

public class ClearEditText extends EditText implements  
    OnFocusChangeListener, TextWatcher { 

private Drawable mClearDrawable; 

public ClearEditText(Context context) { 
    this(context, null); 
} 

public ClearEditText(Context context, AttributeSet attrs) {
    //这里构造方法也很重要,不加这个很多属性不能再XML里面定义  
    this(context, attrs, android.R.attr.editTextStyle);
} 

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


private void init() { 
    mClearDrawable = getCompoundDrawables()[2];
    if (mClearDrawable == null) { 
        mClearDrawable = getResources() 
                .getDrawable(R.drawable.emotionstore_progresscancelbtn);
    } 
    mClearDrawable.setBounds(0, 0, mClearDrawable.getIntrinsicWidth(), mClearDrawable.getIntrinsicHeight());
    //默认设置隐藏图标
    setClearIconVisible(false);
    //设置焦点改变的监听
    setOnFocusChangeListener(this);
    //设置输入框里面内容发生改变的监听 
    addTextChangedListener(this); 
}
/**
 * 因为我们不能直接给EditText设置点击事件,所以我们用记住我们按下的位置来模拟点击事件
 * 当我们按下的位置 在  EditText的宽度 - 图标到控件右边的间距 - 图标的宽度  和
 * EditText的宽度 - 图标到控件右边的间距之间我们就算点击了图标,竖直方向就没有考虑
 */

@Override 
public boolean onTouchEvent(MotionEvent event) { 
    if (getCompoundDrawables()[2] != null) { 
        if (event.getAction() == MotionEvent.ACTION_UP) { 
            boolean touchable = event.getX() > (getWidth() 
                    - getPaddingRight() - mClearDrawable.getIntrinsicWidth()) 
                    && (event.getX() < ((getWidth() - getPaddingRight())));
            if (touchable) { 
                this.setText(""); 
            } 
        } 
    } 

    return super.onTouchEvent(event); 
}
/**
 * 当ClearEditText焦点发生变化的时候,判断里面字符串长度设置清除图标的显示与隐藏
 */

@Override 
public void onFocusChange(View v, boolean hasFocus) { 
    if (hasFocus) { 
        setClearIconVisible(getText().length() > 0); 
    } else { 
        setClearIconVisible(false); 
    } 
}

/**
 * 设置清除图标的显示与隐藏,调用setCompoundDrawables为EditText绘制上去
 * @param visible
 */

protected void setClearIconVisible(boolean visible) { 
    Drawable right = visible ? mClearDrawable : null; 
    setCompoundDrawables(getCompoundDrawables()[0], 
            getCompoundDrawables()[1], right, getCompoundDrawables()[3]); 
}

/**
 * 当输入框里面内容发生变化的时候回调的方法
 */
@Override
public void onTextChanged(CharSequence s, int start, int count, 
        int after) { 
    setClearIconVisible(s.length() > 0); 
} 

@Override 
public void beforeTextChanged(CharSequence s, int start, int count, 
        int after) { 

} 

@Override 
public void afterTextChanged(Editable s) { 

}


/**
 * 设置晃动动画
 */
public void setShakeAnimation(){
    this.setAnimation(shakeAnimation(50));
}

/**
 * 晃动动画
 * @param counts 1秒钟晃动多少下
 * @return
 */

public static Animation shakeAnimation(int counts){
    Animation translateAnimation = new TranslateAnimation(0, 10, 0, 0);
    translateAnimation.setInterpolator(new CycleInterpolator(counts));
    translateAnimation.setDuration(1000);
    return translateAnimation;
}


}

xml的设置

<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"
>


<com.zsz.develop.clearedittextdemo.ClearEditText
    android:id="@+id/filter_edit"
    android:layout_marginTop="5dip"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"

    android:drawableLeft="@drawable/search_bar_icon_normal"
    android:hint="dd"
    android:singleLine="true"
    android:textSize="15.0dip" />
</RelativeLayout>

ListView的setSelection()和setSelectionFromTop()联系

通常,app中的数据都是以ListView的形式展示的。默认地,把“新”数据添加到数据列表的尾部。
但是,如果是IM类型的app,比如查看历史消息这个模块。新数据并不是插到数据列表的尾部,而是插到数据列表的头部。
要实现比较好的用户体验,需要保持当前的ListView的位置。换句话说,如果我们能够随心所欲地指定ListView滚动的位置,那么这个问题就迎刃而解。
在ListView中,有一个setSelectionFromTop()方法

他的源码如下:

/** 
 * Sets the selected item and positions the selection y pixels from the top edge 
 * of the ListView. (If in touch mode, the item will not be selected but it will 
 * still be positioned appropriately.) 
 * 
 * @param position Index (starting at 0) of the data item to be selected. 
 * @param y The distance from the top edge of the ListView (plus padding) that the 
 *        item will be positioned. 
 */  
public void setSelectionFromTop(int position, int y) {  
if (mAdapter == null) {  
    return;  
}  

if (!isInTouchMode()) {  
    position = lookForSelectablePosition(position, true);  
    if (position >= 0) {  
        setNextSelectedPositionInt(position);  
    }  
} else {  
    mResurrectToPosition = position;  
}  

if (position >= 0) {  
    mLayoutMode = LAYOUT_SPECIFIC;  
    mSpecificTop = mListPadding.top + y;  

    if (mNeedSync) {  
        mSyncPosition = position;  
        mSyncRowId = mAdapter.getItemId(position);  
    }  

    requestLayout();  
}  
}  

从上面的代码可以得知,setSelectionFromTop()的作用是设置ListView选中的位置,同时在Y轴设置一个偏移量(padding值)。
ListView还有一个方法叫setSelection(),传入一个index整型数值,就可以让ListView定位到指定Item的位置。
这两个方法有什么区别呢?看一下setSelection()的具体实现,代码如下:

/** 
 * Sets the currently selected item. If in touch mode, the item will not be selected 
 * but it will still be positioned appropriately. If the specified selection position 
 * is less than 0, then the item at position 0 will be selected. 
 * 
 * @param position Index (starting at 0) of the data item to be selected. 
 */  
@Override  
public void setSelection(int position) {  
    setSelectionFromTop(position, 0);  
}  

原来,setSelection()内部就是调用了setSelectionFromTop(),只不过是Y轴的偏移量是0而已。
现在应该对setSelection()和setSelectionFromTop()有了更深刻的认识了。

2015/9/9

2015/9/9日

http://www.jb51.net/article/16829.htm

Java正则表达式

基础知识

我们先从简单的开始。假设你要搜索一个包含字符“cat”的字符串,搜索用的正则表达式就是“cat”。如果搜索对大小写不敏感,单词“catalog”、“Catherine”、“sophisticated”都可以匹配。

1.1 句点符号

假设你在玩英文拼字游戏,想要找出三个字母的单词,而且这些单词必须以“t”字母开头,以“n”字母结束。另外,假设有一本英文字典,你可以用正则表达式搜索它的全部内容。要构造出这个正则表达式,你可以使用一个通配符——句点符号“.”。这样,完整的表达式就是“t.n”,它匹配“tan”、“ten”、“tin”和“ton”,还匹配“t#n”、“tpn”甚至“t n”,还有其他许多无意义的组合。这是因为句点符号匹配所有字符,包括空格、Tab字符甚至换行符:

1.2 方括号符号

为了解决句点符号匹配范围过于广泛这一问题,你可以在方括号(“[]”)里面指定看来有意义的字符。此时,只有方括号里面指定的字符才参与匹配。也就是说,正则表达式“t[aeio]n”只匹配“tan”、“Ten”、“tin”和“ton”。但“Toon”不匹配,因为在方括号之内你只能匹配单个字符:

1.3 “或”符号

如果除了上面匹配的所有单词之外,你还想要匹配“toon”,那么,你可以使用“|”操作符。“|”操作符的基本意义就是“或”运算。要匹配“toon”,使用“t(a|e|i|o|oo)n”正则表达式。这里不能使用方扩号,因为方括号只允许匹配单个字符;这里必须使用圆括号“()”。圆括号还可以用来分组,具体请参见后面介绍。

1.4 表示匹配次数的符号
表一显示了表示匹配次数的符号,这些符号用来确定紧靠该符号左边的符号出现的次数:

Java中正则Matcher类的matches()、lookAt()和find()的区别

在Matcher类中有matches、lookingAt和find都是匹配目标的方法,但容易混淆,整理它们的区别如下:

matches:整个匹配,只有整个字符序列完全匹配成功,才返回True,否则返回False。但如果前部分匹配成功,将移动下次匹配的位置。

lookingAt:部分匹配,总是从第一个字符进行匹配,匹配成功了不再继续匹配,匹配失败了,也不继续匹配。

find:部分匹配,从当前位置开始匹配,找到一个匹配的子串,将移动下次匹配的位置。

reset:给当前的Matcher对象配上个新的目标,目标是就该方法的参数;如果不给参数,reset会把Matcher设到当前字符串的开始处。

2015/9/8-6

实现接口Comparator排序

int compare(Object o1, Object o2) 返回一个基本类型的整型,返回负数表示o1 小于o2,返回0 表示o1和o2相等,返回正数表示o1大于o2。

Java String.compareTo()方法

Java String.compareTo()方法用法实例教程, 此方法如果这个字符串是等参数字符串那么​返回值0,如果这个字符串是按字典顺序小于字符串参数那么返回小于0的值,如果此字符串是按字典顺序大于字符串参数那么一个大于0的值

简单使用

package com.zsz.develop.sortlistdemo;

import java.util.Comparator;

/**
 * 
 * @author xiaanming
 *
 */
public class PinyinComparator implements Comparator<SortModel> {

public int compare(SortModel o1, SortModel o2) {
    //这两个是不同的啊,一个是ol等于@,一个是ol等于#。对象就不一样了
    //忘记了这是if语句啊!!!第一个if为真就不会再执行了。
    //排个序。
    if (o1.getSortLetters().equals("@") || o2.getSortLetters().equals("#")) {
        return -1;
    } else if (o1.getSortLetters().equals("#") || o2.getSortLetters().equals("@")) {
        return 1;
    } else {
        return o1.getSortLetters().compareTo(o2.getSortLetters());
    }
}

}

java中Collections.sort排序

Comparator是个接口,可重写compare()及equals()这两个方法,用于比价功能;如果是null的话,就是使用元素的默认顺序,如a,b,c,d,e,f,g,就是a,b,c,d,e,f,g这样,当然数字也是这样的。
compare(a,b)方法:根据第一个参数小于、等于或大于第二个参数分别返回负整数、零或正整数。
equals(obj)方法:仅当指定的对象也是一个 Comparator,并且强行实施与此 Comparator 相同的排序时才返回 true。
Collections.sort(list, new PriceComparator());的第二个参数返回一个int型的值,就相当于一个标志,告诉sort方法按什么顺序来对list进行排序。

2015/9/8-5

Android事件传递机制(dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent)

Android中的事件类型分为按键事件和屏幕触摸事件,Touch事件是屏幕触摸事件的基础事件,有必要对它进行深入的了解。

View即普通的控件,没有子布局的,如Button、TextView.

ViewGroup继承自View,表示可以有子控件,如Linearlayout、Listview这些。

事件即MotionEvent,最重要的有3个:

  • (1)MotionEvent.ACTION_DOWN 按下View,是所有事件的开始
  • (2)MotionEvent.ACTION_MOVE 滑动事件
  • (3)MotionEvent.ACTION_UP 与down对应,表示抬起

明确事件传递机制的最终目的都是为了触发执行View的点击监听和触摸监听:

******.setOnClickListener(new View.OnClickListener() {

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        Log.i(tag, "testLinelayout---onClick...");
    }
});

*******.setOnTouchListener(new View.OnTouchListener() {

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        // TODO Auto-generated method stub

        return false;
    }
});

我们简称为onClick监听和onTouch监听,一般程序会注册这两个监听。从上面可以看到,onTouch监听里默认return false。不要小看了这个return false,后面可以看到它有大用。

对于View来说,事件传递机制有两个函数:dispatchTouchEvent负责分发事件,在dispatch*里又会调用onTouchEvent表示执行事件,或者说消费事件,

总结

1、事件入口是dispatchTouchEvent(),它会先执行注册的onTouch监听,如果一切顺利的话,接着执行onTouchEvent,在onTouchEvent里会执行onClick监听。

2、无论是dispatchTouchEvent还是onTouchEvent,如果返回true表示这个事件已经被消费、处理了,不再往下传了。在dispathTouchEvent的源码里可以看到,如果onTouchEvent返回了true,那么它也返回true。如果dispatch*在执行onTouch监听的时候,onTouch返回了true,那么它也返回true,这个事件提前被onTouch消费掉了。就不再执行onTouchEvent了,更别说onClick监听了。

3、我们通常在onTouch监听了设置图片一旦被触摸就改变它的背景、透明度之类的,这个onTouch表示事件的时机。而在onClick监听了去具体干某些事。

在自定义的View里面添加再设置一个外加View

再mianActivity中添加进来:

sideBar.setTextView(dialog);

在sideBar中再对他进行设置。

/**

 * 在mainActivity中吧TextView设置进来。
 * @param mTextDialog
 */
public void setTextView(TextView mTextDialog) {
    this.mTextDialog = mTextDialog;
}

在dispatchTouchEvent中对他进行监听和控制。

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
    final int action = event.getAction();
    final float y = event.getY();// 点击y坐标
    final int oldChoose = choose;
    final OnTouchingLetterChangedListener listener = onTouchingLetterChangedListener;
    final int c = (int) (y / getHeight() * b.length);// 点击y坐标所占总高度的比例*b数组的长度就等于点击b中的个数.

    switch (action) {
    case MotionEvent.ACTION_UP:
        setBackgroundDrawable(new ColorDrawable(0x00000000));
        choose = -1;//
        invalidate();
        if (mTextDialog != null) {
            mTextDialog.setVisibility(View.INVISIBLE);
        }
        break;

    default:
        setBackgroundResource(R.drawable.sidebar_background);
        if (oldChoose != c) {
            if (c >= 0 && c < b.length) {
                if (listener != null) {
                    listener.onTouchingLetterChanged(b[c]);
                }
                if (mTextDialog != null) {
                    mTextDialog.setText(b[c]);
                    mTextDialog.setVisibility(View.VISIBLE);
                }

                choose = c;
                invalidate();
            }
        }

        break;
    }
    return true;
}

View.VISIBLE、INVISIBLE、GONE的区别

android中UI应用的开发中经常会使用view.setVisibility()来设置控件的可见性,其中该函数有3个可选值,他们有着不同的含义:

View.VISIBLE—->可见

View.INVISIBLE—->不可见,但这个View仍然会占用在xml文件中所分配的布局空间,不重新layout

View.GONE——>不可见,但这个View在ViewGroup中不保留位置,会重新layout,不再占用空间,那后面的view就会取代他的位置,

invalidate()函数

invalidate()函数的主要作用是请求View树进行重绘,该函数可以由应用程序调用,或者由系统函数间接调用,例如setEnable(), setSelected(), setVisiblity()都会间接调用到invalidate()来请求View树重绘,更新View树的显示。

2015/9/8-4

Android自定义控件

我们每天的开发工作当中都在不停地跟View打交道,Android中的任何一个布局、任何一个控件其实都是直接或间接继承自View的,如TextView、Button、ImageView、ListView等。这些控件虽然是Android系统本身就提供好的,我们只需要拿过来使用就可以了,但你知道它们是怎样被绘制到屏幕上的吗?

速成班

先简单的画一个图

  • 首先要继承View
  • 实现他的几个方法(ps.可以不做任何动作)
  • 实现onDraw方法就可以开始画了
  • onDraw里面提供了一个参数Canvas,这是一块画布。然后我们要自己创建一只画笔Paint
  • 然后用paint+Canvas绘制出各种东西。(ps。canvas。Draw绘制时要填入的参数代表距离父控件的距离)

-

package com.zsz.develop.sidebardemo;

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

/**
 * Created by shengzhong on 2015/9/8.
 */
public class customView extends View {

private Paint mPaint=new Paint();

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

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

public customView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}

@Override
protected void onDraw(Canvas canvas) {
    mPaint.setColor(Color.RED);
    canvas.drawRect(0, 0, 300, 400, mPaint);
    mPaint.setColor(Color.BLACK);
    mPaint.setTextSize(20);
    String text ="hello";
    canvas.drawText(text,0,getHeight()/2,mPaint);

}
}

绘制sideBar,通讯录边上右一栏的绘制

通过for循环绘制每个字母。选中和没选中的颜色也是不一样的。最后还要重置画笔。

/**
 * 重写这个方法
 */
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    // 获取焦点改变背景颜色.
    int height = getHeight();// 获取对应高度
    int width = getWidth(); // 获取对应宽度
    int singleHeight = height / b.length;// 获取每一个字母的高度

    for (int i = 0; i < b.length; i++) {
        paint.setColor(Color.rgb(33, 65, 98));
        // paint.setColor(Color.WHITE);
        paint.setTypeface(Typeface.DEFAULT_BOLD);
        paint.setAntiAlias(true);
        paint.setTextSize(20);
        // 选中的状态
        if (i == choose) {
            paint.setColor(Color.parseColor("#3399ff"));
            paint.setFakeBoldText(true);
        }
        // x坐标等于中间-字符串宽度的一半.
        float xPos = width / 2 - paint.measureText(b[i]) / 2;
        float yPos = singleHeight * i + singleHeight;
        canvas.drawText(b[i], xPos, yPos, paint);
        paint.reset();// 重置画笔
    }

}

2015/9/8-3

Java汉字转换为拼音

使用类:CharacterParser。

package com.zsz.develop.characterparserdemo;

import android.util.Log;

/**
 * Java汉字转换为拼音
 *
 */

public class CharacterParser {
private static int[] pyvalue = new int[] {-20319, -20317, -20304, -20295, -20292, -20283, -20265, -20257, -20242, -20230, -20051, -20036, -20032,
        -20026, -20002, -19990, -19986, -19982, -19976, -19805, -19784, -19775, -19774, -19763, -19756, -19751, -19746, -19741, -19739, -19728,
        -19725, -19715, -19540, -19531, -19525, -19515, -19500, -19484, -19479, -19467, -19289, -19288, -19281, -19275, -19270, -19263, -19261,
        -19249, -19243, -19242, -19238, -19235, -19227, -19224, -19218, -19212, -19038, -19023, -19018, -19006, -19003, -18996, -18977, -18961,
        -18952, -18783, -18774, -18773, -18763, -18756, -18741, -18735, -18731, -18722, -18710, -18697, -18696, -18526, -18518, -18501, -18490,
        -18478, -18463, -18448, -18447, -18446, -18239, -18237, -18231, -18220, -18211, -18201, -18184, -18183, -18181, -18012, -17997, -17988,
        -17970, -17964, -17961, -17950, -17947, -17931, -17928, -17922, -17759, -17752, -17733, -17730, -17721, -17703, -17701, -17697, -17692,
        -17683, -17676, -17496, -17487, -17482, -17468, -17454, -17433, -17427, -17417, -17202, -17185, -16983, -16970, -16942, -16915, -16733,
        -16708, -16706, -16689, -16664, -16657, -16647, -16474, -16470, -16465, -16459, -16452, -16448, -16433, -16429, -16427, -16423, -16419,
        -16412, -16407, -16403, -16401, -16393, -16220, -16216, -16212, -16205, -16202, -16187, -16180, -16171, -16169, -16158, -16155, -15959,
        -15958, -15944, -15933, -15920, -15915, -15903, -15889, -15878, -15707, -15701, -15681, -15667, -15661, -15659, -15652, -15640, -15631,
        -15625, -15454, -15448, -15436, -15435, -15419, -15416, -15408, -15394, -15385, -15377, -15375, -15369, -15363, -15362, -15183, -15180,
        -15165, -15158, -15153, -15150, -15149, -15144, -15143, -15141, -15140, -15139, -15128, -15121, -15119, -15117, -15110, -15109, -14941,
        -14937, -14933, -14930, -14929, -14928, -14926, -14922, -14921, -14914, -14908, -14902, -14894, -14889, -14882, -14873, -14871, -14857,
        -14678, -14674, -14670, -14668, -14663, -14654, -14645, -14630, -14594, -14429, -14407, -14399, -14384, -14379, -14368, -14355, -14353,
        -14345, -14170, -14159, -14151, -14149, -14145, -14140, -14137, -14135, -14125, -14123, -14122, -14112, -14109, -14099, -14097, -14094,
        -14092, -14090, -14087, -14083, -13917, -13914, -13910, -13907, -13906, -13905, -13896, -13894, -13878, -13870, -13859, -13847, -13831,
        -13658, -13611, -13601, -13406, -13404, -13400, -13398, -13395, -13391, -13387, -13383, -13367, -13359, -13356, -13343, -13340, -13329,
        -13326, -13318, -13147, -13138, -13120, -13107, -13096, -13095, -13091, -13076, -13068, -13063, -13060, -12888, -12875, -12871, -12860,
        -12858, -12852, -12849, -12838, -12831, -12829, -12812, -12802, -12607, -12597, -12594, -12585, -12556, -12359, -12346, -12320, -12300,
        -12120, -12099, -12089, -12074, -12067, -12058, -12039, -11867, -11861, -11847, -11831, -11798, -11781, -11604, -11589, -11536, -11358,
        -11340, -11339, -11324, -11303, -11097, -11077, -11067, -11055, -11052, -11045, -11041, -11038, -11024, -11020, -11019, -11018, -11014,
        -10838, -10832, -10815, -10800, -10790, -10780, -10764, -10587, -10544, -10533, -10519, -10331, -10329, -10328, -10322, -10315, -10309,
        -10307, -10296, -10281, -10274, -10270, -10262, -10260, -10256, -10254};
public static String[] pystr = new String[] {"a", "ai", "an", "ang", "ao", "ba", "bai", "ban", "bang", "bao", "bei", "ben", "beng", "bi", "bian",
        "biao", "bie", "bin", "bing", "bo", "bu", "ca", "cai", "can", "cang", "cao", "ce", "ceng", "cha", "chai", "chan", "chang", "chao", "che",
        "chen", "cheng", "chi", "chong", "chou", "chu", "chuai", "chuan", "chuang", "chui", "chun", "chuo", "ci", "cong", "cou", "cu", "cuan",
        "cui", "cun", "cuo", "da", "dai", "dan", "dang", "dao", "de", "deng", "di", "dian", "diao", "die", "ding", "diu", "dong", "dou", "du",
        "duan", "dui", "dun", "duo", "e", "en", "er", "fa", "fan", "fang", "fei", "fen", "feng", "fo", "fou", "fu", "ga", "gai", "gan", "gang",
        "gao", "ge", "gei", "gen", "geng", "gong", "gou", "gu", "gua", "guai", "guan", "guang", "gui", "gun", "guo", "ha", "hai", "han", "hang",
        "hao", "he", "hei", "hen", "heng", "hong", "hou", "hu", "hua", "huai", "huan", "huang", "hui", "hun", "huo", "ji", "jia", "jian",
        "jiang", "jiao", "jie", "jin", "jing", "jiong", "jiu", "ju", "juan", "jue", "jun", "ka", "kai", "kan", "kang", "kao", "ke", "ken",
        "keng", "kong", "kou", "ku", "kua", "kuai", "kuan", "kuang", "kui", "kun", "kuo", "la", "lai", "lan", "lang", "lao", "le", "lei", "leng",
        "li", "lia", "lian", "liang", "liao", "lie", "lin", "ling", "liu", "long", "lou", "lu", "lv", "luan", "lue", "lun", "luo", "ma", "mai",
        "man", "mang", "mao", "me", "mei", "men", "meng", "mi", "mian", "miao", "mie", "min", "ming", "miu", "mo", "mou", "mu", "na", "nai",
        "nan", "nang", "nao", "ne", "nei", "nen", "neng", "ni", "nian", "niang", "niao", "nie", "nin", "ning", "niu", "nong", "nu", "nv", "nuan",
        "nue", "nuo", "o", "ou", "pa", "pai", "pan", "pang", "pao", "pei", "pen", "peng", "pi", "pian", "piao", "pie", "pin", "ping", "po", "pu",
        "qi", "qia", "qian", "qiang", "qiao", "qie", "qin", "qing", "qiong", "qiu", "qu", "quan", "que", "qun", "ran", "rang", "rao", "re",
        "ren", "reng", "ri", "rong", "rou", "ru", "ruan", "rui", "run", "ruo", "sa", "sai", "san", "sang", "sao", "se", "sen", "seng", "sha",
        "shai", "shan", "shang", "shao", "she", "shen", "sheng", "shi", "shou", "shu", "shua", "shuai", "shuan", "shuang", "shui", "shun",
        "shuo", "si", "song", "sou", "su", "suan", "sui", "sun", "suo", "ta", "tai", "tan", "tang", "tao", "te", "teng", "ti", "tian", "tiao",
        "tie", "ting", "tong", "tou", "tu", "tuan", "tui", "tun", "tuo", "wa", "wai", "wan", "wang", "wei", "wen", "weng", "wo", "wu", "xi",
        "xia", "xian", "xiang", "xiao", "xie", "xin", "xing", "xiong", "xiu", "xu", "xuan", "xue", "xun", "ya", "yan", "yang", "yao", "ye", "yi",
        "yin", "ying", "yo", "yong", "you", "yu", "yuan", "yue", "yun", "za", "zai", "zan", "zang", "zao", "ze", "zei", "zen", "zeng", "zha",
        "zhai", "zhan", "zhang", "zhao", "zhe", "zhen", "zheng", "zhi", "zhong", "zhou", "zhu", "zhua", "zhuai", "zhuan", "zhuang", "zhui",
        "zhun", "zhuo", "zi", "zong", "zou", "zu", "zuan", "zui", "zun", "zuo"};
private StringBuilder buffer;
private String resource;
private static CharacterParser characterParser = new CharacterParser();

public static CharacterParser getInstance() {
    return characterParser;
}

public String getResource() {
    return resource;
}

public void setResource(String resource) {
    this.resource = resource;
}

/** * 汉字转成ASCII码 * * @param chs * @return */
private int getChsAscii(String chs) {
    int asc = 0;
    try {
//            正确显示成中文就必须对编码进行转换"gb2312"是中文的一种编码方式。
        byte[] bytes = chs.getBytes("gb2312");
        if (bytes == null || bytes.length > 2 || bytes.length <= 0) {
            throw new RuntimeException("illegal resource string");
        }
        if (bytes.length == 1) {
            asc = bytes[0];
        }
        if (bytes.length == 2) {
            int hightByte = 256 + bytes[0];
            int lowByte = 256 + bytes[1];
            asc = (256 * hightByte + lowByte) - 256 * 256;
        }
    } catch (Exception e) {
        System.out.println("ERROR:ChineseSpelling.class-getChsAscii(String chs)" + e);
    }
    return asc;
}

/** * 单字解析 * * @param str * @return */
public String convert(String str) {
    String result = null;
    int ascii = getChsAscii(str);
    Log.e("ascii",ascii+"");
    if (ascii > 0 && ascii < 160) {
        result = String.valueOf((char) ascii);
    } else {
        for (int i = (pyvalue.length - 1); i >= 0; i--) {
            if (pyvalue[i] <= ascii) {
                result = pystr[i];
                break;
            }
        }
    }
    return result;
}

/** * 词组解析 * * @param chs * @return */
public String getSelling(String chs) {
    String key, value;
    buffer = new StringBuilder();
    for (int i = 0; i < chs.length(); i++) {
        key = chs.substring(i, i + 1);
        if (key.getBytes().length >= 2) {
            value = (String) convert(key);
            if (value == null) {
                value = "unknown";
            }
        } else {
            value = key;
        }
        buffer.append(value);
    }
    return buffer.toString();
}

public String getSpelling() {
    return this.getSelling(this.getResource());
}

}

实现原理

单字:

  • 1.先把输入的中文转成byte【】。
  • 2.再把byte【】转成ASCII码
  • 3.通过Ascii进行比对。

对于词组

  • 通过String。substring()的方法截取某一个字符。得到一个单字。接下去就一样了

    key = chs.substring(i, i + 1);

问题一chs.getBytes(“gb2312”)

byte[] bytes = chs.getBytes("gb2312");

getBytes():使用平台的默认字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。

正确显示成中文就必须对编码进行转换”gb2312”是中文的一种编码方式。

String.getBytes(String decode)方法会根据指定的decode编码返回某字符串在该编码下的byte数组表示,如

byte[] b_gbk = “中”.getBytes(“GBK”);
byte[] b_utf8 = “中”.getBytes(“UTF-8”);
byte[] b_iso88591 = “中”.getBytes(“ISO8859-1”);

将分别返回“中”这个汉字在GBK、UTF-8和ISO8859-1编码下的byte数组表示,此时b_gbk的长度为2,b_utf8的长度为3,b_iso88591的长度为1。

Android Paint类的介绍

Android Paint类的介绍

要绘图,首先得调整画笔,待画笔调整好之后,再将图像绘制到画布上,这样才可以显示在手机屏幕上。Android 中的画笔是 Paint类,Paint 中包含了很多方法对其属性进行设置,主要方法如下:

setAntiAlias: 设置画笔的锯齿效果。
setColor: 设置画笔颜色
setARGB: 设置画笔的a,r,p,g值。
setAlpha: 设置Alpha值
setTextSize: 设置字体尺寸。
setStyle: 设置画笔风格,空心或者实心。
setStrokeWidth: 设置空心的边框宽度。
getColor: 得到画笔的颜色
getAlpha: 得到画笔的Alpha值。

 * Paint类介绍  
 *   
 * Paint即画笔,在绘图过程中起到了极其重要的作用,画笔主要保存了颜色,  
 * 样式等绘制信息,指定了如何绘制文本和图形,画笔对象有很多设置方法,  
 * 大体上可以分为两类,一类与图形绘制相关,一类与文本绘制相关。         
 *   
 * 1.图形绘制  
 * setARGB(int a,int r,int g,int b);  
 * 设置绘制的颜色,a代表透明度,r,g,b代表颜色值。  
 *   
 * setAlpha(int a);  
 * 设置绘制图形的透明度。  
 *   
 * setColor(int color);  
 * 设置绘制的颜色,使用颜色值来表示,该颜色值包括透明度和RGB颜色。  
 *   
* setAntiAlias(boolean aa);  
 * 设置是否使用抗锯齿功能,会消耗较大资源,绘制图形速度会变慢。  
 *   
 * setDither(boolean dither);  
 * 设定是否使用图像抖动处理,会使绘制出来的图片颜色更加平滑和饱满,图像更加清晰  
 *   
 * setFilterBitmap(boolean filter);  
 * 如果该项设置为true,则图像在动画进行中会滤掉对Bitmap图像的优化操作,加快显示  
 * 速度,本设置项依赖于dither和xfermode的设置  
 *   
 * setMaskFilter(MaskFilter maskfilter);  
 * 设置MaskFilter,可以用不同的MaskFilter实现滤镜的效果,如滤化,立体等       *   
 * setColorFilter(ColorFilter colorfilter);  
 * 设置颜色过滤器,可以在绘制颜色时实现不用颜色的变换效果  
 *   
 * setPathEffect(PathEffect effect);  
 * 设置绘制路径的效果,如点画线等  
 *   
 * setShader(Shader shader);  
 * 设置图像效果,使用Shader可以绘制出各种渐变效果  
 *  
 * setShadowLayer(float radius ,float dx,float dy,int color);  
 * 在图形下面设置阴影层,产生阴影效果,radius为阴影的角度,dx和dy为阴影在x轴和y轴上的距离,color为阴影的颜色  
 *   
 * setStyle(Paint.Style style);  
 * 设置画笔的样式,为FILL,FILL_OR_STROKE,或STROKE  
 *   
 * setStrokeCap(Paint.Cap cap);  
 * 当画笔样式为STROKE或FILL_OR_STROKE时,设置笔刷的图形样式,如圆形样式  
 * Cap.ROUND,或方形样式Cap.SQUARE  
 *   
 * setSrokeJoin(Paint.Join join);  
 * 设置绘制时各图形的结合方式,如平滑效果等  
 *   
 * setStrokeWidth(float width);  
 * 当画笔样式为STROKE或FILL_OR_STROKE时,设置笔刷的粗细度  
 *   
 * setXfermode(Xfermode xfermode);  
 * 设置图形重叠时的处理方式,如合并,取交集或并集,经常用来制作橡皮的擦除效果  
 *   
 * 2.文本绘制  
 * setFakeBoldText(boolean fakeBoldText);  
 * 模拟实现粗体文字,设置在小字体上效果会非常差  
 *   
 * setSubpixelText(boolean subpixelText);  
 * 设置该项为true,将有助于文本在LCD屏幕上的显示效果  
 *   
 * setTextAlign(Paint.Align align);  
 * 设置绘制文字的对齐方向  
 *   
   * setTextScaleX(float scaleX);  
* 设置绘制文字x轴的缩放比例,可以实现文字的拉伸的效果  
 *   
 * setTextSize(float textSize);  
 * 设置绘制文字的字号大小  
 *   
 * setTextSkewX(float skewX);  
 * 设置斜体文字,skewX为倾斜弧度  
 *   
 * setTypeface(Typeface typeface);  
 * 设置Typeface对象,即字体风格,包括粗体,斜体以及衬线体,非衬线体等  
 *   
 * setUnderlineText(boolean underlineText);  
 * 设置带有下划线的文字效果  
 *   
 * setStrikeThruText(boolean strikeThruText);  
 * 设置带有删除线的效果  

2015/9/7/3

adapter

通过ViewHolder

首先分析下ViewHolder的作用,通过convertView.setTag与convertView进行绑定,然后当convertView复用时,直接从与之对于的ViewHolder(getTag)中拿到convertView布局中的控件,省去了findViewById的时间~

也就是说,实际上们每个convertView会绑定一个ViewHolder对象,这个viewHolder主要用于帮convertView存储布局中的控件。

那么我们只要写出一个通用的ViewHolder,然后对于任意的convertView,提供一个对象让其setTag即可;

既然是通用,那么我们这个ViewHolder就不可能含有各种控件的成员变量了,因为每个Item的布局是不同的,最好的方式是什么呢?

提供一个容器,专门存每个Item布局中的所有控件,而且还要能够查找出来;既然需要查找,那么ListView肯定是不行了,需要一个键值对进行保存,键为控件的Id,值为控件的引用,相信大家立刻就能想到Map;但是我们不用Map,因为有更好的替代类,就是我们android提供的SparseArray这个类,和Map类似,但是比Map效率,不过键只能为Integer.

还需要重温好多边

http://blog.csdn.net/lmj623565791/article/details/38902805/