<pre name="code" class="java" style="color: rgb(51, 51, 51); font-size: 14px; line-height: 26px;">ANRs : (“Application Not Responding”)


//将字符串转为整型,资源
Field field=R.drawable.class.getField("icon");
int drawable= field.getInt(new R.drawable());
如果自定义layout中有EditText,点击EditText会弹出输入法,此时会调用自定义layout或view的onMeasure方法,
所以,使用此策略可以监听输入法弹出
修改代码时,若想要获取之前view的配置,例如图片、颜色、字号等,可以调试,获取之前view的信息,通过view查找配置
listview继承自AbsListView,AbsListView中封装了对view的回收处理,使用setRecyclerListener对view被回收时做出处理



在使用listview,recycleview等进行嵌套时,系统本身不会对里面的listview进行宽高计算,所以要手动计算宽高,并设置里面的listview



即使是在自定义view中重写onTouchEvent,他所响应到的区间也是他的父布局,即所产生的坐标是父布局的相对坐标而不是整个屏幕绝对的坐标,
所以对自定义view的TouchEvent做出响应,应该判断是不是view的区间
在view 的OnTouchListener事件中,若返回FALSE则继续向上传递,若返回TRUE则又监听方法处理
即如果想要处理move移动事件或者up弹起事件要返回TRUE
有些控件,例如checkbox,即使不设置click监听也会对点击作出响应,这时需要在控件中加入
android:focusable="false"
android:focusableInTouchMode="false"
此时就会和listview本身的点击互不影响



设置view的可见性:
View.setVisibility 
GONE:不可见,不占据位置,即原来的位置会被有fill_parent的控件占据
INVISIBLE:不可见,占据位置,即还有宽高
VISIBLE:可见
在设置visible时,设置layout为gone,layout的子布局的visible并不会为gone
可以在canvas中通过控制矩阵Matrix来控制旋转rotate和缩放scale和平移translation
在ui thread中调用view的invalidate方法可以通知view重绘制(刷新),重绘制将调用onDraw()方法来重新绘制view
得到acticity中的contentview: content=(ViewGroup)this.findViewById(android.R.id.content)
在FrameLayout中,放在下面的子控件是叠在上面的,即第一个子控件是位于最底层的
scroll的三种状态(能滑动的控件,listview,gridview,recycleview都有): SCROLL_STATE_IDLE, SCROLL_STATE_DRAGGING or SCROLL_STATE_SETTLING.
IDLE指的是控件没有在滑动(SCROLL_STATE_IDLE为0)
DRAGGING指的是控件在滑动,手指在屏幕上移动(SCROLL_STATE_DRAGGING为1)
SETTLING指的是控件在滑动,手指已经放开屏幕,控件处于自动的动画滑动中(SCROLL_STATE_SETTLING为2)



主线程中创建handler,主要用来修改UI界面
Handler handler;
onCreate
{
	handler=new Handler();
}
//接着在任意地方
handler.post(new runable(可以传入参数));
//定义一个Runnable
private class runable implements Runnable
    {
        //构造方法
        private runable()
        {
        }
//实例化Runnable接口
        @Override
        public void run(){
        }
    }



//通过使用message调用handle
Handler mHandler = new Handler() {
	@Override
	public void handleMessage(Message msg) {
	}
};
//调用:
mHandler.sendEmptyMessage(0);
//注:一般发送的是Message,在handleMessage()方法中判断Message,执行不同的代码段



//在android主线程中使用handler.post(runnable),并不会开启新的线程,而是将消息压到main线程使用的消息池中,
//所以handler.post还是在主线程中。
//当无法确定是否是在主线程中执行代码,可以使用:
Thread.currentThread().getId()  
//或者
Thread.currentThread().getName()
//来确定当前线程



Thread thread = new Thread(runnable);thread.start(); //开启一个新的线程,
// 而使用以下发送Message的方法也是在主线程当做执行
            Handler handler = new Handler(new Handler.Callback() {
                @Override
                public boolean handleMessage(Message msg) {
                    Log.w("sendEmptyMessage",Thread.currentThread().getName());
                    return false;
                }
            });
            handler.sendEmptyMessage(1);


//即使是在线程中发送消息,最后handle的执行也是在主线程当中
            final Handler handler = new Handler(new Handler.Callback() {
                @Override
                public boolean handleMessage(Message msg) {
                    Log.w("runnable2",Thread.currentThread().getName());
                    return false;
                }
            });
            Runnable runnable2 = new Runnable() {
                @Override
                public void run() {
                    handler.sendEmptyMessage(1);
                }
            };
            Thread thread = new Thread(runnable2);
            thread.start();



//可以使用特殊线程HandlerThread,可以很好的和handle结合在一起使用
            mWorkThread = new HandlerThread("threadname");
            mWorkThread.start();
            Handler workHandler = new Handler(mWorkThread.getLooper(), new Handler.Callback() {
                @Override
                public boolean handleMessage(Message msg) {
                    return false;
                }
            });
            workHandler.sendEmptyMessage(1);



//改变背景颜色:
//这样输入:             
layout.setBackgroundColor(Color.parseColor("#ffff00"));
//或者这样输入:           
layout.setBackgroundColor(0xFF6db7ff);
//0xFF6db7ff是Android中特殊的16进制颜色编码,FF表示的是透明度,6db7ff表示颜色编码
//表达式顺序是“aabbggrr”,其中“aa=alpha”(00 到 ff,00透明度为0%,ff透明度为100%)
//“bb=blue”(00 到 ff);“gg=green”(00 到 ff);“rr=red”(00 到 ff)



//java 代码修改控件高宽
        RelativeLayout.LayoutParams params=new RelativeLayout.LayoutParams((gwidth-40)/glistcount,(int)((gwidth-40)/glinecount*0.99));
//new RelativeLayout.LayoutParams(40,40);像素值
//new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,RelativeLayout.LayoutParams.WRAP_CONTENT);自适应
        控件.setLayoutParams(params);



<!-- android颜色color.xml设置 -->
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="white">#FFFFFF</color><!--白色 -->
</resources>



//计时器控件chronometer
chronometer.getText();//得到时间
chronometer.stop();//结束
chronometer.start();//开始
chronometer.setBase(SystemClock.elapsedRealtime());//设施开始时间为00:00



//导航栏高度:
ActionBar actionBar;
actionBar=getActionBar();
actionBar.getHeight();
//得到gridview的子视图
gridview.getChildAt(填入下标)



//设置全背景为一张图,包括actionbar
    private void setBackgrounnd() {
        Activity context =this;
        ViewGroup root =  (ViewGroup)context.getWindow().getDecorView();
        if (root != null) {
            ViewGroup group = ((ViewGroup)root.getChildAt(0));
            group.setBackgroundResource(R.drawable.background);
        }
    }



</pre><pre name="code" class="java">PreferenceScreen点击之后没有actionbar是因为没有设置title属性的原因
当工程失去R文件时重新编译就会出现一个新的R文件



自定义View的监听回调机制

public class colorpick extends View{

(1)在自定义View的类内预留接口
 public interface OnColorChangedListener {
        void colorChanged(int color);
 }

(2)在自定义View的类内创建一个该接口
private OnColorChangedListener mListener;

(3)在构造方法中对创建的接口赋值
    public colorpick(Context context,
                             OnColorChangedListener listener,
                             int initialColor) {
        mListener = listener;
    }

(5)至此,就可以在View的内部调用实例化好的接口,如下,对mListener.colorChanged输入0xff0000ff的参数,因为mListener在构造方法中被赋值,相当于外部定义的colorpick赋值给了mListener,
        所以,mListener的colorChanged方法会有Log.w("color is "+color,"color is "+color);的语句,会在控制台输出log
	mListener.colorChanged(0xff0000ff);

(4)在外部创建自定义View
	colorpick colorpick1= new colorpick(testactivity.this, new colorpick.OnColorChangedListener() {
		@Override
		public void colorChanged(int color) {
			Log.w("color is "+color,"color is "+color);
		}
	}
	,0xff000000);



混合渲染ComposeShader显示无效果时,需要在配置文件中加入
<activity android:hardwareAccelerated="false" />
或者



//获取自定义view的颜色值
	int pixel;
	View view;
	Bitmap bitmap;
	view.buildDrawingCache();
	bitmap = view.getDrawingCache();
	pixel = bitmap.getPixel((int)event.getX(),(int)event.getY());



<span style="font-family: Arial, Helvetica, sans-serif;">调节边距可以尝试padding和margin</span>
padding可以做到实时更新




//自定义控件,onMeasure可以设置空间的大小,只有当所在的控件设置为match_parent或者固定的dp数值时才能有高和宽,
//而设置wrap_content时widthMeasureSpec和heightMeasureSpec是没有数值的,因为wrap_content是自己计算宽度和高度的。
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        w=measure(widthMeasureSpec);
        setMeasuredDimension(w,w);
    }

    private int measure(int measureSpec) {
        int result = 0;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        if (specMode == MeasureSpec.EXACTLY) {
            result = specSize;
        } else {
            if (specMode == MeasureSpec.AT_MOST) {
                result = Math.min(result, specSize);
            }
        }
        return result;
    }



//使用别的包的资源:
//不把图片放在res/drawable下,而是存放在src某个package中(如:com.drawable.resource),这种情况下的调用方法为: 
String path = "com/drawable/resource/imageName.png"; 
InputStream is = getClassLoader().getResourceAsStream(path); 
Drawable.createFromStream(is, "src"); 

//如果还是希望直接使用res/drawable中的图片,就需要通过下面的方法了: 
//假设创建工程的时候,填写的package名字为:com.test.image 
//通过字符串获取Drawable的ResourcesID
int resID = getResources().getIdentifier("imageName", "drawable", "com.test.image"); 
Drawable image = getResources().getDrawable(resID);



//自定义layout
//使用以下方法加载布局,为控件找到ID
       LayoutInflater inflater=(LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
      inflater.inflate(R.layout.editkeyboard_layout, this);
        upButton = (Button)findViewById(R.id.up) ;
//等同于
       LayoutInflater inflater=LayoutInflater.from(mContext);
        View contextVie=inflater.inflate(R.layout.editkeyboard_layout, EditKeyboardLayout.this);
        upButton = (Button)contextVie.findViewById(R.id.up) ;



在自定义layout中使用merge标签来包含子控件,例如:
<merge
    xmlns:android="http://schemas.android.com/apk/res/android">
    <ImageButton/>
    <LinearLayout/>
    <LinearLayout>
        <TextView/>
    </LinearLayout>
    <ImageButton/>
</merge>



//子View脱离父View再加入新View:
InputView view = (InputView)mKeyboardSwitcher.getInputView();
if (view.getParent() != null) {
	ViewGroup parent = (ViewGroup)view.getParent();
	parent.removeView(view);
}
LinearLayout.LayoutParams p = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT);
mLinearLayout.addView(view, p);



屏幕宽度:	
WindowManager wm = (WindowManager) getContext()
				.getSystemService(Context.WINDOW_SERVICE);

 int width = wm.getDefaultDisplay().getWidth();
 int height = wm.getDefaultDisplay().getHeight();



TextView文字居中:
1.在xml文件设置:android:gravity="center"
2.在程序中设置:m_TxtTitle.setGravity(Gravity.CENTER);

TextViews从dimen中获取字号
        mGetPaintTextView = new TextView(mContext);
        mGetPaintTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mContext.getResources().getDimension(R.dimen.yantext_size));



popupwindow:
创建:
view是什么布局参数2和3的LayoutParams可以采用什么,也可以填入固定整型数值
mPopupWindow = new PopupWindow(view, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);

附着锚点显示:mPopupWindow.showAsDropDown(mButton);
showAsDropDown有不同的函数提供重载
mPopupWindow.dismiss();隐藏

 创建PopupWindow
     步骤1:初始化
	 PopupWindow popupWindow = new PopupWindow();
	 步骤2:设置ContentView
        LayoutInflater layoutInflater = LayoutInflater.from(mContext);
        View view1 = layoutInflater.inflate(R.layout.yantext_listview_item_layout, null);
        TextView textView = (TextView) view1.findViewById(R.id.yantext_view1);
        textView.setText("sfksidfxdhgsdghsrhgrg");
        popupWindow.setContentView(view1);
	步骤3:设置宽高
        popupWindow.setHeight(200);
        popupWindow.setWidth(200);
	步骤4:显示
        popupWindow.showAsDropDown(mAnchor);
	步骤5:消失
		popupWindow.dismiss();



//点击外部PopupWindow消失
        mSharePopupWindow.setBackgroundDrawable(new BitmapDrawable());
        mSharePopupWindow.setOutsideTouchable(true);



LinearLayout设置控件居中,要在LinearLayout中设置:
android:gravity="center"



ImageView设置 android:scaleType="centerInside"
如果设置了view的width和height大于wrap_content,内部的图片会wrap_content



//字符串"R.drawable" 转换资源整型:
//方法1:
try{  
 Field field=R.drawable.class.getField("icon");  
 int i= field.getInt(new R.drawable());  
  Log.d("icon",i+"");  
}catch(Exception e){  
 Log.e("icon",e.toString());  
}

//方法2:
Resources res=getResources();  
int i=res.getIdentifier("icon","drawable",getPackageName());  
Log.i("res",Integer.toString(i));



检测apk是否安装在手机上:
获得包名列表:
        PackageManager packageManager = mContext.getPackageManager();
        List<ApplicationInfo> appList = packageManager.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES);
检测包名:
 for (ApplicationInfo applicationInfo : appList) { 
	String pkgName = applicationInfo.packageName;
	//对比前缀
	if (pkgName.startsWith("prefix name")) {}
 }



获取其他pkg下的Resource
 Resources res = packageManager.getResourcesForApplication(pkgName);
 获取其他pkg下的Drawable
 int mDrawableResID = res.getIdentifier(drawableName, "drawable", pkgName);
 mTestDrawable = res.getDrawable(mDrawableResID);
 得到Asset资源
 InputStream is = res.getAssets().open(fileName);



获得安装的包的信息列表
PackageManager packageManager = mContext.getPackageManager();
List<ApplicationInfo> appList = packageManager.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES);



//在viewpager中如果删除页面并删除页面的数据,再显示控件,会有部分页面显示数据为空,
mYanPagerAdapter = mViewPager.getAdapter();// 得到Adapter
mViewPager.setAdapter(null); 			//设置Adapter为空
mViewPager.setAdapter(mYanPagerAdapter);// 再把Adapter设置回去可解决



//在android的try,catch中可以利用Exception来输出类似于程序崩溃时的错误信息,包括了错误类型(Exception类),
//具体的错误java文件和错误行数
	try {
	} catch (Exception e) {
		Log.e("getDrawable error", "Exception", e); //输出log level为error
		e.printStackTrace();			//输出log level为warn
	}



//在recycleview中,在getItemViewType返回position就可以在onCreateViewHolder中的viewType得到position,
//虽然可以把<span style="font-family: Arial, Helvetica, sans-serif;">ViewType作为position来使用,但是</span>这种使用方法并不是viewType的正确使用方式
@Override
public int getItemViewType(int position) {
	return position;
}

@Override
public EmojiSelectViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
}



//recycleview滑动监听,onScrolled不是滑动之后才会调用,而是在滑动时就会调用,
//个人认为应该是从一个点移动到另一个点就会调用(有待研究)
mScrollListener = new RecyclerView.OnScrollListener() {
	@Override
	public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
	}
	@Override
	public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
		Log.e("onScrolled", "onScrolled");
	}
};
mRecyclerView.setOnScrollListener(mScrollListener);



自定义xml属性:
(1)建立res/values/attrs.xml文件
(2)在attrs.xml写入
<resources>
   <declare-styleable name="PieChart">
       <attr name="showText" format="boolean" />
       <attr name="labelPosition" format="enum">
           <enum name="left" value="0"/>
           <enum name="right" value="1"/>
       </attr>
   </declare-styleable>
</resources>
(3)使用,特别注意在gradle工程中使用: xmlns:custom="http://schemas.android.com/apk/res-auto"
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:custom="http://schemas.android.com/apk/res/com.example.customviews">
 <com.example.customviews.charting.PieChart
     custom:showText="true"
     custom:labelPosition="left" />
</LinearLayout>
(4)在带有AttributeSet的系统提供的构造方法中获取数值:
public PieChart(Context context, AttributeSet attrs) {
   super(context, attrs);
   TypedArray a = context.getTheme().obtainStyledAttributes(
        attrs,
        R.styleable.PieChart,
        0, 0);

   try {
	   //第二个参数为默认值,当取不到R.styleable.PieChart_showText的值时会返回false
       mShowText = a.getBoolean(R.styleable.PieChart_showText, false); 
	   //第二个参数为默认值,当取不到R.styleable.PieChart_labelPosition的值时会返回0
       mTextPos = a.getInteger(R.styleable.PieChart_labelPosition, 0);
   } finally {
       a.recycle();
   }
}
(5)TypedArray.getResourceId();
可以取得format="reference" 的数值



多点触控:
使用 onTouchEvent方法来实现,
action由MotionEventCompat.getActionMasked(event)方法来获取,不再使用event.getAction()方法来获取:
action = MotionEventCompat.getActionMasked(event);
switch (action)
	case MotionEvent.ACTION_DOWN: //第一个点按下
	case MotionEvent.ACTION_POINTER_DOWN: //第二个点或者之后的点按下,这时候要判断2 <= event.getPointerCount(),通常会有2个以上
	case MotionEvent.ACTION_MOVE: 		//遍历所有的点
		for(int i = 0; i < event.getPointerCount(); i++){
            event.getX(i);
            event.getY(i);
			} 
	case MotionEvent.ACTION_POINTER_UP: //有点离开就会调用,event.getActionIndex()获取离开的点,触点的排列顺序的从第一个按下排列到最后一个
										//例如upPointIndex为0,就是第一个按下的点离开了屏幕;upPointIndex为2,就是第三个按下的点离开了屏幕,
		int upPointIndex = event.getActionIndex();
	case MotionEvent.ACTION_UP: //最后一个点离开屏幕



//分享图片:
//获取bitmap的URI
Bitmap bitmap = mDesignContainer.getDrawingCache();
String pathofBmp = MediaStore.Images.Media.insertImage(EditActivity.this.getContentResolver(), bitmap, null, null);
Uri bmpUri = Uri.parse(pathofBmp);

//指定包名的分享:
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("image/*");
shareIntent.setPackage("com.facebook.katana");
shareIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
shareIntent.putExtra(Intent.EXTRA_STREAM, mBitmapUri);
mContext.startActivity(shareIntent);

//打开系统的分享列表,选择指定的分享应用:
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("image/*");
shareIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
shareIntent.putExtra(Intent.EXTRA_STREAM, mBitmapUri);
mContext.startActivity(Intent.createChooser(shareIntent, "share imger"));

//获取响应该分享的应用列表:
Intent intent = new Intent(Intent.ACTION_SEND, null);
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setType("image/*");
PackageManager pManager = EditActivity.this.getPackageManager();
mShareImgList = pManager.queryIntentActivities(intent, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT);



在gridview,recycleview等view中如果设置同一个带有按下状态的drawable给每个item会产生按下状态混乱的BUG,
需要给每个item都配置一个带有按下状态的drawable,例如在每次设置item时调用以下方法,赋值一个新的drawable



给edittext或searchview设置提示字符串和提示图标:
1.构建SpannableStringBuilder或者spannableString
SpannableStringBuilder ssb = new SpannableStringBuilder("title");
或者 SpannableString spannableString = new SpannableString("title");

2.构建ImageSpan
ImageSpan imageHint = new ImageSpan(drawable);

3.字号(可以不设)
int textSize = (int) (searchAutoComplete.getTextSize() * 1.25);
searchIcon.setBounds(0, 0, textSize, textSize);

4.将包含了图标的ImageSpan设进去
ssb.setSpan(new ImageSpan(searchIcon), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spannableString.setSpan(imageHint, 0, 1, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

5.设置
mEditor.setHint(spannableString);

SearchView.SearchAutoComplete searchAutoComplete = (SearchView.SearchAutoComplete) mSearchView.findViewById(android.support.v7.appcompat.R.id.search_src_text);
searchAutoComplete.setHint(spannableString);

总体:
SpannableStringBuilder ssb = new SpannableStringBuilder("    ");
ssb.append("hint");
 int textSize = (int) (searchAutoComplete.getTextSize() * 1.25);
searchIcon.setBounds(0, 0, textSize, textSize);
ssb.setSpan(new ImageSpan(searchIcon), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);	
 searchAutoComplete.setHint(ssb);		
 
注:在开发过程中遇到过想要去除searchview提示图标去除不了的情况,直接把一个字符串的id设置就可以了,例如:
searchAutoComplete.setHint(R.string.mediapicker_gif_title);



SearchView
关闭edittext collapseActionView()
展开edittext expandActionView()

也可以对SearchView对应的MenuItem调用collapseActionView(),也可以关闭
mSearchItem = menu.findItem(R.id.action_gif_search);
mSearchView = (SearchView) mSearchItem.getActionView();



Fragment
放置在Activity中,可以通过FragmentManager进行交互和管理Fragment,

使用方法1:在xml中放置,Activity的onCreateView()方法设置即可 
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <fragment android:name="com.example.news.ArticleListFragment"
            android:id="@+id/list"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="match_parent" />
    <fragment android:name="com.example.news.ArticleReaderFragment"
            android:id="@+id/viewer"
            android:layout_weight="2"
            android:layout_width="0dp"
            android:layout_height="match_parent" />
</LinearLayout>

使用方法2:使用FragmentTransaction,其中R.id.fragment_container是一个放置fragment的layout

FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

ExampleFragment fragment = new ExampleFragment();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();

获取:使用find id和find tag获取fragment
findFragmentById()



span:
SpannableString 在setSpan时需要指定flag,以下四种中的其中一种,
如果设置了SPAN_EXCLUSIVE_EXCLUSIVE指的是如果设置SpannableString改变字体颜色,那么在SpannableString的
之前和之后再输入字符都不会出现改变字体颜色的效果。
如果设置了SPAN_INCLUSIVE_INCLUSIVE指的是如果设置SpannableString改变字体颜色,那么在SpannableString的
之前和之后再输入字符都会出现改变字体颜色的效果。
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE(前后都不包括)
Spanned.SPAN_INCLUSIVE_EXCLUSIVE(前面包括,后面不包括)
Spanned.SPAN_EXCLUSIVE_INCLUSIVE(前面不包括,后面包括)
Spanned.SPAN_INCLUSIVE_INCLUSIVE(前后都包括)