分类目录归档:Android

android的四种启动模式,与五大布局,五种存储模式,四大组件::::::演道网Andriod专栏提供Andriod基础概念,具体代码演示,方便大家深入理解和运用Android。大部分代码可以直接使用。

Android中的Selector的用法

Android中的Selector主要是用来改变ListView和Button控件的默认背景。其使用方法可以按一下步骤来设计:(以在mylist_view.xml为例)

  1. 创建mylist_view.xml文件

首先在res目录下新建drawable文件夹,再在新建的drawable文件夹中新建mylist_view.xml,其目录结构为:res/drawable/mylist_view.xml。

2.根据具体需求编辑mylist_view.xml文件
新建mylist_view.xml文件后,在没有添加任何属性时其内部代码结构为:

<?xml version="1.0" encoding="utf-8" ?>     
<selector xmlns:android="http://schemas.android.com/apk/res/android">   
   
</selector>  

下面就可以根据项目需求,在其内部定义为自己想要的样式了,主要属性如下:

<?xml version="1.0" encoding="utf-8" ?>     
<selector xmlns:android="http://schemas.android.com/apk/res/android">   
<!-- 默认时的背景图片-->    
  <item android:drawable="@drawable/pic1" />      
<!-- 没有焦点时的背景图片 -->    
  <item android:state_window_focused="false"     
        android:drawable="@drawable/pic1" />     
<!-- 非触摸模式下获得焦点并单击时的背景图片 -->    
  <item android:state_focused="true" android:state_pressed="true"   android:drawable= "@drawable/pic2" />   
<!-- 触摸模式下单击时的背景图片-->    
<item android:state_focused="false" android:state_pressed="true"   android:drawable="@drawable/pic3" />    
<!--选中时的图片背景-->    
  <item android:state_selected="true"   android:drawable="@drawable/pic4" />     
<!--获得焦点时的图片背景-->    
  <item android:state_focused="true"   android:drawable="@drawable/pic5" />     
</selector>  

3.引用mylist_view.xml文件
三种方法可以来引用刚才创建的文件:
1.在ListView中添加如下属性代码

android:listSelector="@drawable/mylist_view"  

2.在ListView的item界面中添加如下属性代码

android:background="@drawable/mylist_view"  

3.利用JAVA代码直接编写

Drawable drawable =     getResources().getDrawable(R.drawable.mylist_view);   
listView.setSelector(drawable);  

为了防止列表拉黑的情况发生,需要在ListView中添加以下的属性代码

android:cacheColorHint="@android:color/transparent"  

属性介绍:

  • android:state_selected选中
  • android:state_focused获得焦点
  • android:state_pressed点击
  • android:state_enabled设置是否响应事件,指所有事件

Android开发示例:如何设置圆角的EditText

设置EditText边框为圆角如下图所示:

首先定义一个圆角xml,路径:res/drawable/rounded_edittext.xml

  1. <?xml version=“1.0” encoding=“utf-8”?>
  2. <shape xmlns:Android=“http://schemas.android.com/apk/res/android”
  3.     android:shape=“rectangle” android:padding=“10dp”>
  4.     <solid android:color=“#FFFFFF” />
  5.     <corners android:bottomRightRadius=“15dp”
  6.         android:bottomLeftRadius=“15dp” android:topLeftRadius=“15dp”
  7.         android:topRightRadius=“15dp” />
  8. </shape>

显示控件的xml中

  1. <EditText android:id=“@+id/edt_operator_name” style=“@style/syncEditText”
  2.                     android:hint=“@string/hint_operator_name”
  3. android:background=“@drawable/rounded_edittext”
  4. android:layout_width=“250dip”
  5. android:layout_height=“wrap_content”
  6. android:paddingTop=“10dip”
  7. android:paddingBottom=“10dip”
  8. android:gravity=“center_vertical” />

其中关键的就是设置编辑文本控件的background属性为刚定义的圆角xml。

即:

  1. android:background=“@drawable/rounded_edittext”

 

android软键盘弹出引起的各种不适终极解决方案

很多写登录界面的开发者都会遇到一个问题:那就是在登录界面时,当你点击输入框时,下边的按钮有时会被输入框挡住,这个不利于用户的体验,所以很多人希望软键盘弹出时,也能把按钮挤上去。很多开发者想要监听键盘的状态,这无疑是一个很麻烦的做法。
我们可以在AndroidManifest.xml的Activity设置属性:

xml
android:windowSoftInputMode = "adjustResize"

软键盘弹出时,要对主窗口布局重新进行布局,并调用onSizeChanged方法,切记一点当我们设置为“adjustResize”时,我们的界面不要设置为全屏模式,否则设置了这个属性也不会有什么效果。而当我们设置
xml
android: windowSoftInputMode = "adjustPan"

时,主窗口就不会调用onSizeChanged方法,界面的一部分就会被软键盘覆盖住,就不会被挤到软键盘之上了。

我们通过一段代码来测试一下,当我们设置了该属性后,弹出输入法时,系统做了什么.
重写Layout布局:

    public class ResizeLayout extends LinearLayout{ 
        private static int count = 0; 
         
        public ResizeLayout(Context context, AttributeSet attrs)            { 
            super(context, attrs); 
        } 
         
        @Override 
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {     
            super.onSizeChanged(w, h, oldw, oldh);          
            Log.e("onSizeChanged " + count++, "=>onResize called! w="+w + ",h="+h+",oldw="+oldw+",oldh="+oldh); 
       } 
         
        @Override 
        protected void onLayout(boolean changed, int l, int t, int r, int b) { 
            super.onLayout(changed, l, t, r, b); 
            Log.e("onLayout " + count++, "=>OnLayout called! l=" + l + ", t=" + t + ",r=" + r + ",b="+b); 
        } 
         
        @Override 
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);       
            Log.e("onMeasure " + count++, "=>onMeasure called! widthMeasureSpec=" + widthMeasureSpec + ", heightMeasureSpec=" + heightMeasureSpec); 
        } 

我们的布局设置为:

    <com.winuxxan.inputMethodTest.ResizeLayout  
        xmlns:android="http://schemas.android.com/apk/res/android" 
        android:id="@+id/root_layout" 
        android:layout_width="fill_parent" 
        android:layout_height="fill_parent" 
        android:orientation="vertical" 
        > 
         
        <EditText 
            android:layout_width="fill_parent"  
            android:layout_height="wrap_content"  
        /> 
       
        <LinearLayout 
                android:id="@+id/bottom_layout" 
                android:layout_width="fill_parent"  
                android:layout_height="fill_parent"  
                android:orientation="vertical" 
                android:gravity="bottom">s 
        
        <TextView   
            android:layout_width="fill_parent"  
            android:layout_height="wrap_content"  
            android:text="@string/hello" 
            android:background="#77777777" 
          /> 
       </LinearLayout> 
    </com.winuxxan.inputMethodTest.ResizeLayout> 

AndroidManifest.xml的Activity设置属性:

android:windowSoftInputMode = "adjustResize"

运行程序,点击文本框,查看调试信息:

E/onMeasure 6(7960): =>onMeasure called! widthMeasureSpec=1073742144, heightMeasureSpec = 1073742024

E/onMeasure 7(7960): =>onMeasure called! widthMeasureSpec=1073742144, heightMeasureSpec = 1073742025

E/onSizeChanged 8(7960): =>onSizeChanged called! w=320,h=201,oldw=320,oldh=377

E/onLayout 9(7960): =>OnLayout called! l=0, t=0,r=320,b=201

从调试结果我们可以看出,当我们点击文本框后,根布局调用了onMeasure,onSizeChanged和onLayout。

windowSoftInputMode的值如果设置为adjustPan,那么该Activity主窗口并不调整屏幕的大小以便留出软键盘的空间。相反,当前窗口的内容将自动移动以便当前焦点从不被键盘覆盖和用户能总是看到输入内容的部分。这个通常是不期望比调整大小,因为用户可能关闭软键盘以便获得与被覆盖内容的交互操作。
上面的例子中,我们将AndroidManifest.xml的属性进行更改:

xml
android: windowSoftInputMode = "adjustPan"

重新运行,并点击文本框,查看调试信息:
E/onMeasure 6(8378): =>onMeasure called! widthMeasureSpec=1073742144, heightMeasureSpec=1073742200
E/onMeasure 7(8378): =>onMeasure called! widthMeasureSpec=1073742144, heightMeasureSpec=1073742201
E/onLayout 8(8378): =>OnLayout called! l=0, t=0,r=320,b=377
我们看到:系统也重新进行了measrue和layout,但是我们发现,layout过程中onSizeChanged并没有调用,这说明输入法弹出前后并没有改变原有布局的大小。

当然还有其他属性可以设置:

  • stateUnspecified 软键盘的状态(是否它是隐藏或可见)没有被指定。系统将选择一个合适的状态或依赖于主题的设置。 这个是为了软件盘行为默认的设置。
  • stateUnchanged 软键盘被保持无论它上次是什么状态,是否可见或隐藏,当主窗口出现在前面时。
  • stateHidden 当用户选择该Activity时,软键盘被隐藏——也就是,当用户确定导航到该Activity时,而不是返回到它由于离开另一个Activity。
  • stateAlwaysHidden 软键盘总是被隐藏的,当该Activity主窗口获取焦点时。
  • stateVisible 软键盘是可见的,当那个是正常合适的时(当用户导航到Activity主窗口时)。
  • stateAlwaysVisible 当用户选择这个Activity时,软键盘是可见的——也就是,也就是,当用户确定导航到该Activity时,而不是返回到它由于离开另一个Activity。
  • adjustUnspecifie 它不被指定是否该Activity主窗口调整大小以便留出软键盘的空间,或是否窗口上的内容得到屏幕上当前的焦点是可见的。系统将自动选择这些模式中一种主要依赖于是否窗口的内容有任何布局视图能够滚动他们的内容。如果有这样的一个视图,这个窗口将调整大小,这样的假设可以使滚动窗口的内容在一个较小的区域中可见的。这个是主窗口默认的行为设置。
  • adjustResize 该Activity主窗口总是被调整屏幕的大小以便留出软键盘的空间
  • adjustPan 该Activity主窗口并不调整屏幕的大小以便留出软键盘的空间。相反,当前窗口的内容将自动移动以便当前焦点从不被键盘覆盖和用户能总是看到输入内容的部分。这个通常是不期望比调整大小,因为用户可能关闭软键盘以便获得与被覆盖内容的交互操作。

 

Android 数据存储的5种方式介绍

5种方式分别是:

  • 文件
  • sharedPreference
  • SQLite
  • 网络
  • ContentProvider

Preference,File, DataBase这三种方式分别对应的目录是/data/data/Package Name/Shared_Pref, /data/data/Package Name/files, /data/data/Package Name/database 。
在Android中通常使用File存储方式是用Context.openFileOutput(String fileName, int mode)和Context.openFileInput(String fileName)。
Context.openFileOutput(String fileName, int mode)生成的文件自动存储在/data/data/Package Name/files目录下,其全路径是/data/data/Package Name/files/fileName 。注意下,这里的参数fileName不可以包含路径分割符(如"/")。

通常来说,这种方式生成的文件只能在这个apk内访问。但这个结论是指使用Context.openFileInput(String fileName)的方式。使用这种方式,每个apk只可以访问自己的/data/data/Package Name/files目录下的文件,原因很简单,参数fileName中不可以包含路径分割符,Android会自动在/data/data/Package Name/files目录下寻找文件名为fileName的文件。

  1. 使用SharedPreferences存储数据
    首先说明SharedPreferences存储方式,它是Android提供的用来存储一些简单配置信息的一种机制,例如:登录用户的用户名与密码。其采用了Map数据结构来存储数据,以键值的方式存储,可以简单的读取与写入,具体实例如下:
void  ReadSharedPreferences(){
    String  strName,strPassword;
    SharedPreferences   user = getSharedPreferences("user_info",0);
    strName = user.getString("NAME","");
    strPassword = user getString("PASSWORD","");
}
void  WriteSharedPreferences(String  strName,String strPassword){
    SharedPreferences   user = getSharedPreferences(“user_info”,0);
    user.edit();
    user.putString("NAME", strName);
    user.putString("PASSWORD" ,strPassword);
    user.commit();
}

void save(String name, Integer age) {
        SharedPreferences preferences = context.getSharedPreferences("test", Context.MODE_PRIVATE);
        Editor editor = preferences.edit();
        editor.putString("name", name);
        editor.putInt("age", age);
        editor.commit();
    }

数据读取与写入的方法都非常简单,只是在写入的时候有些区别:先调用edit()使其处于编辑状态,然后才能修改数据,最后使用commit()提交修改的数据。实际上SharedPreferences是采用了XML格式将数据存储到设备中,在DDMS中的File Explorer中的/data/data//shares_prefs下。以上面的数据存储结果为例,打开后可以看到一个user_info.xml的文件,打开后可以看到:

<?xml version=”1.0″ encoding=”UTF-8″?>
<map>
    <string name=”NAME”>moandroid</string>
    <string name=” PASSWORD”>SharedPreferences</string>
</map>

使用SharedPreferences是有些限制的:只能在同一个包内使用,不能在不同的包之间使用。

2.文件存储数据
文件存储方式是一种较常用的方法,在Android中读取/写入文件的方法,与Java中实现I/O的程序是完全一样的,提供了openFileInput()和openFileOutput()方法来读取设备上的文件。FilterInputStream, FilterOutputStream等可以到Java io package说明中去详细学习,不再此详细说明,具体实例如下:

    String fn = “moandroid.log”;
    FileInputStream fis = openFileInput(fn);
    FileOutputStream fos = openFileOutput(fn,Context.MODE_PRIVATE);

文件操作模式:

文件(四种操作模式)
FileOutputStream fos =
Context.openFileOutput(filename,Context.MODE_PRIVATE; Context.MODE_APPEND;
Context.MODE_WORLD_READABLE+Context.MODE_WORLD_WRITEABLE )

除此之外,Android还提供了其他函数来操作文件,详细说明请阅读Android SDK。

3.网络存储数据
网络存储方式

利用HttpURLConnection对象,我们可以从网络中获取网页数据.

URL url = new URL("http://www.sohu.com");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5* 1000);//设置连接超时
conn.setRequestMethod(“GET”);//以get方式发起请求
if (conn.getResponseCode() != 200) throw new RuntimeException("请求url失败");
InputStream is = conn.getInputStream();//得到网络返回的输入流
String result = readData(is, "GBK");
conn.disconnect();
//第一个参数为输入流,第二个参数为字符集编码
public static String readData(InputStream inSream, String charsetName) throws Exception{
    ByteArrayOutputStream outStream = new ByteArrayOutputStream();
    byte[] buffer = new byte[1024];
    int len = -1;
    while( (len = inSream.read(buffer)) != -1 ){
        outStream.write(buffer, 0, len);
    }
    byte[] data = outStream.toByteArray();
    outStream.close();
    inSream.close();
    return new String(data, charsetName);
}

4.ContentProvider

1. ContentProvider简介

当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据。虽然使用其他方法也可以对外共享数据,但数据访问方式会因数据存储的方式而不同,如:采用文件方式对外共享数据,需要进行文件操作读写数据;采用sharedpreferences共享数据,需要使用sharedpreferences API读写数据。而使用ContentProvider共享数据的好处是统一了数据访问方式。

2. Uri类简介

Uri代表了要操作的数据,Uri主要包含了两部分信息:1.需要操作的ContentProvider ,2.对ContentProvider中的什么数据进行操作,一个Uri由以下几部分组成:
1.scheme:ContentProvider(内容提供者)的scheme已经由Android所规定为:content://。
2.主机名(或Authority):用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。
3.路径(path):可以用来表示我们要操作的数据,路径的构建应根据业务而定,如下:
要操作contact表中id为10的记录,可以构建这样的路径:/contact/10
要操作contact表中id为10的记录的name字段, contact/10/name
要操作contact表中的所有记录,可以构建这样的路径:/contact
要操作的数据不一定来自数据库,也可以是文件等他存储方式,如下:
要操作xml文件中contact节点下的name节点,可以构建这样的路径:/contact/name
如果要把一个字符串转换成Uri,可以使用Uri类中的parse()方法,如下:
Uri uri = Uri.parse("content://com.changcheng.provider.contactprovider/contact")

3. UriMatcher、ContentUrist和ContentResolver简介

因为Uri代表了要操作的数据,所以我们很经常需要解析Uri,并从Uri中获取数据。Android系统提供了两个用于操作Uri的工具类,分别为UriMatcher 和ContentUris 。掌握它们的使用,会便于我们的开发工作。
UriMatcher:用于匹配Uri,它的用法如下:
1.首先把你需要匹配Uri路径全部给注册上,如下:
//常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码(-1)。
UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
//如果match()方法匹配content://com.changcheng.sqlite.provider.contactprovider/contact路径,返回匹配码为1
uriMatcher.addURI(“com.changcheng.sqlite.provider.contactprovider”, “contact”, 1);//添加需要匹配uri,如果匹配就会返回匹配码
//如果match()方法匹配 content://com.changcheng.sqlite.provider.contactprovider/contact/230路径,返回匹配码为2
uriMatcher.addURI(“com.changcheng.sqlite.provider.contactprovider”, “contact/#”, 2);//#号为通配符

2.注册完需要匹配的Uri后,就可以使用uriMatcher.match(uri)方法对输入的Uri进行匹配,如果匹配就返回匹配码,匹配码是调用addURI()方法传入的第三个参数,假设匹配content://com.changcheng.sqlite.provider.contactprovider/contact路径,返回的匹配码为1。

ContentUris:用于获取Uri路径后面的ID部分,它有两个比较实用的方法:
withAppendedId(uri, id)用于为路径加上ID部分
parseId(uri)方法用于从路径中获取ID部分
ContentResolver:当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询操作时,可以使用ContentResolver 类来完成,要获取ContentResolver 对象,可以使用Activity提供的getContentResolver()方法。 ContentResolver使用insert、delete、update、query方法,来操作数据。

总结说明

以上5中存储方式,在以后的开发过程中,根据设计目标、性能需求、空间需求等找到合适的数据存储方式。Android 中的数据存储都是私有的,其他应用程序都是无法访问的,除非通过ContentResolver获取其他程序共享的数据。采用文件方式对外共享数据,需要进行文件操作读写数据;
采用sharedpreferences共享数据,需要使用sharedpreferences API读写数据。而使用ContentProvider共享数据的好处是统一了数据访问方式。

Android主题theme和风格style总结

用到了Android的主题和风格,感觉很多地方需要总结和记录下来。其实主题和风格是有很大的作用的,特别是界面要求比较高的客户端。

Style:是一个包含一种或者多种格式化属性的集合,我们可以将其用为一个单位用在布局XML单个元素当中。比如,我们可以定义一种风格来定义文本的字号大小和颜色,然后将其用在View元素的一个特定的实例。

如何定义style?
style也属于resource,所以要在resource下定义,就像定义string,color一样
定义style,需要指定name,style通常包含一个或多个item,每个item的name是android view的属性的名字,值则是对应相关属性的值
可以给style指定parent,从而可以继承和覆盖parent style的属性,parent取值是另外一个style,如果是继承自自己定义的style,只需要在命名style时增加前缀,这个前缀就是即将继承的style的名字

例如CodeFont是一个自己定义的style,那么下面的style,CodeFont.Red,则继承了CodeFont,只是文本的颜色修改成了红色

<style name="CodeFont.Red"> 红色  
        <item name="android:textColor">#FF0000</item>   
 </style>  
 <style name="CodeFont.Red.Big">  红色,并且大字体  
        <item name="android:textSize">30sp</item>   
 </style>

也可以继承平台的style,可继承的样式请参照绍docs/guide/topics/ui/themes.html#PlatformStyles

<style name="CodeFont" parent="@android:style/TextAppearance">  

如果父样式的值不符合你的需求,你也可以对它进行修改,和CSS中的覆盖效果一样,都是以最后的为准, 

在style中可以定义的属性
都有哪些属性在style的定义里是有效的呢?具体请参考docs/reference/android/R.attr.html
在view上使用style时,对view有效的属性起作用,无效的则会忽略
有一些属性对view无效,只对theme有效,在R.attr定义中以window开头的一些属性只对theme有效

style的使用
如果给view指定style,那么这个style只对该view有效
如果给viewgroup指定style,那么viewgroup下的元素也不会应用这个style,除非特别指定
给view指定style时,没有android:前缀,而只是style

下面是具体用法:

首先在res/values下新建一style.xml文件:

<?xml version="1.0" encoding="utf-8"?>  
<resources>  
    <style name="TitleStyle">  
        <item name="android:textSize">18sp</item>  
        <item name="android:textColor">#ec9237</item>  
    </style>  
    <style name="Title" parent="@style/TitleStyle">  
        <item name="android:textSize">5sp</item>  
    </style>  
</resources>

在layout.xml中的应用:

<EditText android:layout_height="wrap_content"   
    android:text="EditText"   
    style="@style/Title"  
    android:layout_width="fill_parent"   
    android:id="@+id/editText1"></EditText> 

其实style就像是一组属性的组合, 可以看做当在view中引用style时,是顺序执行style中的item里面的每个属性,对view进行设定而已。因为可能有多个view都是需要设置相同的属性,。所以把这些view的属性单独写出,提高重用性。

theme:就像风格一样,主题依然在<style>元素里边申明,也是以同样的方式引用。不同的是你通过在Android
Manifest中定义的<application>和<activity>元素将主题添加到整个程序或者某个Activity,但是主题是
不能应用在某一个单独的View里,所以配置文件的属性也就是窗口等的主题样式。

定义一个主题:

<?xml version="1.0" encoding="utf-8"?>  
<resources>  
    <style name="theme1">  
        <item name="android:windowNoTitle">true</item>  
        <item name="android:windowFullscreen">?android:windowNoTitle</item>  
    </style>  
</resources> 

 

下面代码显示在AndroidManifest.xml中如何为应用设置上面定义的主题:

<application android:icon="@drawable/iconandroid:label="@string/app_name"    
    android:theme="@style/theme1">    
    <activity android:name=".MessageShowActivity" android:label="@string/app_name"    
        android:windowSoftInputMode="adjustPan" android:screenOrientation="portrait"    
        android:theme="@style/theme2">    
    </activity>    
</application>

除了可以在AndroidManifest.xml中设置主题,同样也可以在代码中设置主题,如下:

setTheme(R.style.theme1);

注意:我们用了@符号和?符号来应用资源。@符号表明了我们应用的资源是前边定义过的(或者在前一个项目
中或者在Android 框架中)。问号?表明了我们引用的资源的值在当前的主题当中定义过。

style和theme的区别:

尽管在定义上,样式和主题基本相同,但是它们使用的地方不同。样式用在单独的View,如:EditText、TextView等;主题通过AndroidManifest.xml中的<application>和<activity>用在整个应用或者某个 Activity,主题对整个应用或某个Activity存在全局性影响。如果一个应用使用了主题,同时应用下的view也使用了样式,那么当主题与样式属性发生冲突时,样式的优先级高于主题。

另外android系统也定义了一些主题,例如:

<activity android:theme=”@android:style/Theme.Dialog”>,该主题可以让Activity看起来像一个对话框,

<activity android:theme=”@android:style/Theme.Black.NoTitleBar”>Variant of the light theme with no title bar,系统自带的黑色主题。如果需要查阅这些主题,可以在文档的reference–>android–>R.style 中查看。

Android API之CheckedTextView demo(单选,多选)

类CheckedTextView继承超类TextView并实现Checkable接口。当ListView的setChoiceMode方法并设定为CHOICE_MODE_SINGLE或者CHOICE_MODE_MULTIPLE,而非CHOICE_MODE_NONE时,使用此类是很有用的。

使用范例:

  1. /res/layout/main.xml中添加相应资源ID
<ListView
    android:id="@+id/listView"  
    android:layout_width="fill_parent"  
    android:layout_height="wrap_content" 
/>
<CheckedTextView 
    android:id="@+id/checkedTextView1"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:checkMark="?android:attr/listChoiceIndicatorMultiple"
    android:text="@string/checkedTextView1"
/>
<CheckedTextView  
    android:id="@+id/checkedTextView2"  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:checkMark="?android:attr/listChoiceIndicatorMultiple" 
    android:text="@string/checkedTextView2" 
/>
<CheckedTextView 
    android:id="@+id/checkedTextView3"  
    android:layout_width="fill_parent"  
    android:layout_height="wrap_content"  
    android:checkMark="?android:attr/listChoiceIndicatorMultiple"
    android:text="@string/checkedTextView3"  
/>

   
<CheckedTextView  
    android:id="@+id/checkedTextView4"  
    android:layout_width="fill_parent"  
    android:layout_height="wrap_content"  
    android:checkMark="?android:attr/listChoiceIndicatorMultiple"  
    android:text="@string/checkedTextView4"
/>
  1. /res/values/strings.xml 资源
<string name="hello">TextView多选框</string>   
<string name="app_name">CheckedTextView</string>   
<string name="checkedTextView1">TextView多选框1</string>   
<string name="checkedTextView2">TextView多选框2</string>  
<string name="checkedTextView3">TextView多选框3</string>  
<string name="checkedTextView4">TextView多选框4</string>
  1. 源代码中使用
listView=(ListView)findViewById(R.id.listView);     
checkedTextView1=(CheckedTextView)findViewById(R.id.checkedTextView1);      
checkedTextView2=(CheckedTextView)findViewById(R.id.checkedTextView2);     
checkedTextView3=(CheckedTextView)findViewById(R.id.checkedTextView3);    
checkedTextView4=(CheckedTextView)findViewById(R.id.checkedTextView4);
      
//设置checkedTextView1为选中状态      
checkedTextView1.setChecked(true);            
//设置checkedTextView2的页边距,即距上/下/左/右各20像素,默认为未选中状态     
checkedTextView2.setPadding(20, 20, 20, 20);     
//设置checkedTextView3为选中状态,并更改其显示图标,使用android系统资源arrow_down_float   
checkedTextView3.setChecked(true);      
checkedTextView3.setCheckMarkDrawable(android.R.drawable.arrow_down_float);     
//设置checkedTextView4反转状态,由默认的未选中反转为选中状态       
checkedTextView4.toggle();
//点击状态后变更相反,如选中变为未选中,未选中的变为选中
checkedTextView1.setOnClickListener(new View.OnClickListener()
{                           
                          
    @Override                           
    public void onClick(View v) {                           
    // TODO Auto-generated method stub                                   
     checkedTextView1.toggle();                        
}
});       

//点击状态后变更相反,如选中变为未选中,未选中的变为选中
checkedTextView2.setOnClickListener(new View.OnClickListener()
{                           
                          
    @Override                           
    public void onClick(View v) {                           
    // TODO Auto-generated method stub                                   
     checkedTextView2.toggle();                        
}
});        


 

 //点击状态后变更相反,即下三角转化为上三角符号
checkedTextView3.setOnClickListener(new View.OnClickListener()
{                  
    @Override                 
    public void onClick(View v) {                           
    // TODO Auto-generated method stub  
checkedTextView3.setCheckMarkDrawable(android.R.drawable.arrow_up_float);               
    }

});

 //点击状态后变更相反,如选中变为未选中,未选中的变为选中
checkedTextView4.setOnClickListener(new View.OnClickListener()
{                           
                          
    @Override                           
    public void onClick(View v) {                           
    // TODO Auto-generated method stub                                   
     checkedTextView4.toggle();                        
}
});        

       
//设置listView的模式为CHOICE_MODE_SINGLE   
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);

转 Android动态显示隐藏密码输入框的内容(实用)

通过设置EditText的setTransformationMethod()方法来实现隐藏密码或这显示密码,示例如下:

  1. private Button mBtnPassword;  
  2. private EditText mEtPassword;  
  3. private boolean mbDisplayFlg = false;  
  4.   
  5.    /** Called when the activity is first created. */  
  6.    @Override  
  7.    public void onCreate(Bundle savedInstanceState) {  
  8.        super.onCreate(savedInstanceState);  
  9.        setContentView(R.layout.main);  
  10.          
  11.        mEtPassword = (EditText)findViewById(R.id.password);  
  12.        mBtnPassword = (Button)findViewById(R.id.btnPassword);  
  13.        mBtnPassword.setOnClickListener(new OnClickListener() {  
  14.   
  15.         @Override  
  16.         public void onClick(View v) {  
  17.             // TODO Auto-generated method stub  
  18.             Log.d(“AndroidTest”“mbDisplayFlg = “ + mbDisplayFlg);  
  19.             if (!mbDisplayFlg) {  
  20.                 // display password text, for example “123456”  
  21.                 mEtPassword.setTransformationMethod(HideReturnsTransformationMethod.getInstance());  
  22.             } else {  
  23.                 // hide password, display “.”  
  24.                 mEtPassword.setTransformationMethod(PasswordTransformationMethod.getInstance());  
  25.             }  
  26.             mbDisplayFlg = !mbDisplayFlg;  
  27.             mEtPassword.postInvalidate();  
  28.         }  
  29.           
  30.        });  
  31.         
  32.    }  

 

 

main.xml

  1. <?xml version=“1.0” encoding=“utf-8”?>  
  2. <LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”  
  3.     android:orientation=“vertical” android:layout_width=“fill_parent”  
  4.     android:layout_height=“fill_parent”>  
  5.     <Button android:id=“@+id/btnPassword”  
  6.         android:layout_width=“wrap_content”  
  7.         android:layout_height=“wrap_content”  
  8.         android:text=“密码” />  
  9.     <EditText android:id=“@+id/password”  
  10.         android:layout_width=“fill_parent”  
  11.         android:layout_height=“wrap_content”  
  12.         android:password=“true”  
  13.         android:textSize=“18sp”  
  14.         android:text=“123456”>  
  15.     </EditText>  
  16. </LinearLayout>  

 

Android自定义Dialog

这段时间在做一个项目,需要使用到自定义Dialog,先在网上找了一下资料,发现还是有很多没有讲清楚的,在此给出一个Demo,一来可以方便广大码农,二来也可以方便自己,以备不时之需。。。

先来一张图吧,很简单,只有一个Activity,当点击Button的时候就弹出这个自定义的Dialog

里面的几张图都比较丑,我不多会美工,随便用powerpoint画了几张图,原理是一样的,先不计较这些。下面正入正题

为了照顾到所有的码农,在些把所有的代码都贴出来

新建工程在此就不贴出来了,只是为了方便大家的复制粘贴,取包名为com.and.mydialog,主Activity取名为MyDialogActivity

package com.and.mydialog;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

public class MyDialogActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Button button = (Button) findViewById(R.id.button1);
        button.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                
                //初始化一个自定义的Dialog
                Dialog dialog = new MyDialog(MyDialogActivity.this,
                        R.style.MyDialog);

                dialog.show();
            }
        });

    }
}

主布局文件main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <Button 
        android:text="显示自定义Dialog" 
        android:id="@+id/button1"
        android:layout_height="wrap_content" 
        android:layout_width="fill_parent"/>
</LinearLayout>

新建一个自定义的Dialog类,取名MyDialog,继承自Dialog

package com.and.mydialog;

import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;

public class MyDialog extends Dialog {

    Context context;
    public MyDialog(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
        this.context = context;
    }
    public MyDialog(Context context, int theme){
        super(context, theme);
        this.context = context;
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        this.setContentView(R.layout.dialog);
    }

}

相应的布局文件dialog.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center_vertical|center_horizontal"
    android:background="@drawable/dialog_bg">
    <RelativeLayout 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="30dip"
        android:paddingTop="10dip">
        <ImageView 
            android:id="@+id/dialog_title_image"
            android:layout_alignParentLeft="true"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/dialog_title_image"/>
        <TextView 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dip"
            android:layout_centerInParent="true"
            android:text="Title"
            android:layout_toRightOf="@id/dialog_title_image"
            android:textColor="#000000"
            android:textSize="30sp"/>
        
    </RelativeLayout>
    <TextView 
            android:layout_width="fill_parent"
            android:layout_height="1dip"
            android:background="@drawable/lins"
            android:layout_marginTop="5dip"/>
    <TextView 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="This is a custom dialog"
        android:textColor="#000000"
        android:layout_marginTop="10dip"
        android:layout_marginLeft="30dip"/>
    <RelativeLayout 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:paddingTop="10dip"
        android:gravity="bottom|center_horizontal"
        android:paddingBottom="10dip">
        <Button 
            android:id="@+id/dialog_button_cancel"
            android:layout_alignParentLeft="true"
            android:layout_width="100dip"
            android:layout_height="wrap_content"
            android:text="确定"/>
        <Button 
            android:id="@+id/dialog_button_ok"
            android:layout_width="100dip"
            android:layout_height="wrap_content"
            android:layout_toRightOf="@id/dialog_button_cancel"
            android:layout_marginLeft="35dip"
            android:text="取消"/>
    </RelativeLayout>
</LinearLayout>

最主要的,是自定义的Style,我们自定义一个式样,用来改变默认的Dialog样式

在values文件夹下新建一个styles.xml文件,如下。。。

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="MyDialog" parent="@android:Theme.Dialog">
        <item name="android:windowFrame">@null</item>
        <item name="android:windowNoTitle">true</item> 
        <item name="android:windowBackground">@drawable/dialog_bg</item>
        <item name="android:windowIsFloating">true</item>
        <item name="android:windowContentOverlay">@null</item>
    </style>
</resources>

这样应该就OK了,为了方便大家测试本示例,在此一并附上不怎么好看的素材。。。

注意,这里有三张图片,第三张图片是一条线,在自定义的式样的时候取消了标题栏,为了美观,添加此线条,看上去还是有标题栏的感觉。。。在此基本上完成了。

由于水平有限,这些内容基本上都是在网上找的,然后自己整理了一下,写了一篇相对比较清晰的,如果大家还有什么疑问的话,随时可以跟我联系,共同学习。。。

———————————————————————————忧伤的分割线——————————————————————————

不好意思,刚刚实测了一下,发现还有一个很简单的方法,在不改变前面的布局前提下,只需要修改主类(MyDialogActivity.java)

package com.and.mydialog;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

public class MyDialogActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Button button = (Button) findViewById(R.id.button1);
        button.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

//                Dialog dialog = new MyDialog(MyDialogActivity.this,
//                        R.style.MyDialog);
                //此处直接new一个Dialog对象出来,在实例化的时候传入主题
                Dialog dialog = new Dialog(MyDialogActivity.this, R.style.MyDialog);
 //设置它的ContentView
                dialog.setContentView(R.layout.dialog);

                dialog.show();
            }
        });

    }
}

Android自定义Switch控件代码示例

 

Switch是Android的一个开关控件,相当于IPhone的UISwitch效果,但是该控件是4.0以后才有得,故而有些项目需要的时候不得不自己去实现该控件功能,网上主要流行的方法是继承View等控件自己在onDraw()里面绘制控件,但是不是效果不太理想就是体验性太差,另外也有修改官方Switch控件的,综合网上资料,觉得修改官方Switch控件比较靠谱,比较体验性方面性能方面都有保证,API接口大都是一致的,本人选择这种方式。

 

修改Switch的主要思想是:

1. Switch中含有高版本SDK代码,需要去掉或者改写这样的代码

2. Switch对应declare-styleable属性声明应该在Android SDK安装目录中找到对应的源码声明片段,基本上copy过来就行了。所在路径:Androidandroid-sdkplatformsandroid-17datares

 

修改后的MySwitch控件接口基本与原Switch控件一致,并且除了可支持所有SDK外,增加了2项小功能:

1. 支持用Track背景图片的方式代替Texton Textoff等文字方式表现开关状态

2.支持调整控制Switch的高度

 

下面贴出Switch修改的关键代码:

 

 

/** 
 * <p>  
 * modified from android SDK 14(4.0) android.widget.Switch. 
 * <br/> 
 * <strong>new feature: </strong> 
 * <ol> 
 * <li>support SDK 1 or higher. </li> 
 * <li>you can use track drawable instead of text to display the changes of off-on state!</li> 
 * <li>you can control the Switch minimum height. </li> 
 * </ol> 
 * </p> 
 *   
 *  @see {@link Switch} 
 *  @author Wison 
 */  
public class MySwitch extends CompoundButton {  
    // Support track drawable instead of text  
    private Drawable mTrackOnDrawable;  
    private Drawable mTrackOffDrawable;  
      
    // Support minimum height  
    private int mSwitchMinHeight;  
  
    /** 
     * Construct a new Switch with a default style determined by the given theme attribute, 
     * overriding specific style attributes as requested. 
     * 
     * @param context The Context that will determine this widget's theming. 
     * @param attrs Specification of attributes that should deviate from the default styling. 
     * @param defStyle An attribute ID within the active theme containing a reference to the 
     *                 default style for this widget. e.g. android.R.attr.switchStyle. 
     */  
    public MySwitch(Context context, AttributeSet attrs, int defStyle) {  
        super(context, attrs, defStyle);  
  
        mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);  
        Resources res = getResources();  
        mTextPaint.density = res.getDisplayMetrics().density;  
        //float scaledDensity = res.getDisplayMetrics().scaledDensity;  
        //mTextPaint.setCompatibilityScaling(res.getCompatibilityInfo().applicationScale);  
  
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Switch, defStyle, 0);  
  
        // off-on 模式: 图片模式或文字模式,图片模式是用Track背景图片表示off-on的状态,文字模式是用文字来表示off-on状态。  
        mTrackOnDrawable = a.getDrawable(R.styleable.Switch_trackOn);  
        mTrackOffDrawable = a.getDrawable(R.styleable.Switch_trackOff);  
        if (checkTrackOffOnDrawable()) {  
            // 如果设定图片模式,则默认显示off状态  
            mTrackDrawable = mTrackOffDrawable;  
        } else {  
            mTrackDrawable = a.getDrawable(R.styleable.Switch_track);  
        }  
          
        mThumbDrawable = a.getDrawable(R.styleable.Switch_thumb);  
        mTextOn = a.getText(R.styleable.Switch_textOn);  
        mTextOff = a.getText(R.styleable.Switch_textOff);  
        mThumbTextPadding = a.getDimensionPixelSize(R.styleable.Switch_thumbTextPadding, 0);  
        mSwitchMinWidth = a.getDimensionPixelSize(R.styleable.Switch_switchMinWidth, 0);  
          
        mSwitchMinHeight = a.getDimensionPixelSize(R.styleable.Switch_switchMinHeight, 0);  
          
        mSwitchPadding = a.getDimensionPixelSize(R.styleable.Switch_switchPadding, 0);  
  
        int appearance = a.getResourceId(R.styleable.Switch_switchTextAppearance, 0);  
        if (appearance != 0) {  
            setSwitchTextAppearance(context, appearance);  
        }  
        a.recycle();  
  
        ViewConfiguration config = ViewConfiguration.get(context);  
        mTouchSlop = config.getScaledTouchSlop();  
        mMinFlingVelocity = config.getScaledMinimumFlingVelocity();  
  
        // Refresh display with current params  
        refreshDrawableState();  
        setChecked(isChecked());  
    }  
  
    private boolean checkTrackOffOnDrawable() {  
        return mTrackOnDrawable != null && mTrackOffDrawable != null;  
    }  
  
    @SuppressLint("NewApi")  
    @Override  
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
        if (mOnLayout == null) {  
            mOnLayout = makeLayout(mTextOn);  
        }  
        if (mOffLayout == null) {  
            mOffLayout = makeLayout(mTextOff);  
        }  
        mTrackDrawable.getPadding(mTempRect);  
        final int maxTextWidth = Math.max(mOnLayout.getWidth(), mOffLayout.getWidth());  
        final int switchWidth = Math.max(mSwitchMinWidth,  
                maxTextWidth * 2 + mThumbTextPadding * 4 + mTempRect.left + mTempRect.right);  
          
//        final int switchHeight = mTrackDrawable.getIntrinsicHeight();  
        int switchHeight;  
        if (mSwitchMinHeight <= 0) {  
            switchHeight = mTrackDrawable.getIntrinsicHeight();  
        } else {  
            switchHeight = Math.max(mSwitchMinHeight, mTempRect.top + mTempRect.bottom);  
        }  
          
        mThumbWidth = maxTextWidth + mThumbTextPadding * 2;  
  
        mSwitchWidth = switchWidth;  
        mSwitchHeight = switchHeight;  
  
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);  
        final int measuredHeight = getMeasuredHeight();  
        if (measuredHeight < switchHeight) {  
            if (Build.VERSION.SDK_INT >= 11) {  
                setMeasuredDimension(getMeasuredWidthAndState(), switchHeight);  
            } else {  
                setMeasuredDimension(getMeasuredWidth(), switchHeight);  
            }  
        }  
    }  
  
    @Override  
    public void setChecked(boolean checked) {  
        if (checkTrackOffOnDrawable()) {  
            mTrackDrawable = checked ? mTrackOnDrawable : mTrackOffDrawable;  
            refreshDrawableState();  
        }  
        super.setChecked(checked);  
        mThumbPosition = checked ? getThumbScrollRange() : 0;  
        invalidate();  
    }  
  
    @Override  
    protected void onDraw(Canvas canvas) {  
        super.onDraw(canvas);  
        // Draw the switch  
        int switchLeft = mSwitchLeft;  
        int switchTop = mSwitchTop;  
        int switchRight = mSwitchRight;  
        int switchBottom = mSwitchBottom;  
          
        if (checkTrackOffOnDrawable()) {  
            mTrackDrawable = getTargetCheckedState() ? mTrackOnDrawable : mTrackOffDrawable;  
            refreshDrawableState();  
        }  
          
        mTrackDrawable.setBounds(switchLeft, switchTop, switchRight, switchBottom);  
        mTrackDrawable.draw(canvas);  
  
        canvas.save();  
          
        mTrackDrawable.getPadding(mTempRect);  
        int switchInnerLeft = switchLeft + mTempRect.left;  
        int switchInnerTop = switchTop + mTempRect.top;  
        int switchInnerRight = switchRight - mTempRect.right;  
        int switchInnerBottom = switchBottom - mTempRect.bottom;  
        canvas.clipRect(switchInnerLeft, switchTop, switchInnerRight, switchBottom);  
  
        mThumbDrawable.getPadding(mTempRect);  
        final int thumbPos = (int) (mThumbPosition + 0.5f);  
        int thumbLeft = switchInnerLeft - mTempRect.left + thumbPos;  
        int thumbRight = switchInnerLeft + thumbPos + mThumbWidth + mTempRect.right;  
  
        mThumbDrawable.setBounds(thumbLeft, switchTop, thumbRight, switchBottom);  
        mThumbDrawable.draw(canvas);  
  
        // mTextColors should not be null, but just in case  
        if (mTextColors != null) {  
            mTextPaint.setColor(mTextColors.getColorForState(getDrawableState(),  
                    mTextColors.getDefaultColor()));  
        }  
        mTextPaint.drawableState = getDrawableState();  
  
        Layout switchText = getTargetCheckedState() ? mOnLayout : mOffLayout;  
  
        if (switchText != null) {  
            canvas.translate((thumbLeft + thumbRight) / 2 - switchText.getWidth() / 2,  
                    (switchInnerTop + switchInnerBottom) / 2 - switchText.getHeight() / 2);  
            switchText.draw(canvas);  
        }  
        canvas.restore();  
    }  
}  

 

 

下面是关键属性声明:

<declare-styleable name="Switch">  
      
    <!-- Drawable to use when the switch is in the checked/"on" state. -->  
    <attr name="trackOn" format="reference" />  
    <!-- Drawable to use when the switch is in the unchecked/"off" state. -->  
    <attr name="trackOff" format="reference" />  
    <!-- Minimum height for the switch component -->  
    <attr name="switchMinHeight" format="dimension" />  
      
    <!-- Drawable to use as the "thumb" that switches back and forth. -->  
    <attr name="thumb" format="reference" />  
    <!-- Drawable to use as the "track" that the switch thumb slides within. -->  
    <attr name="track" format="reference" />  
    <!-- Text to use when the switch is in the checked/"on" state. -->  
    <attr name="textOn" format="string" />  
    <!-- Text to use when the switch is in the unchecked/"off" state. -->  
    <attr name="textOff" format="string" />  
    <!-- Amount of padding on either side of text within the switch thumb. -->  
    <attr name="thumbTextPadding" format="dimension" />  
    <!-- TextAppearance style for text displayed on the switch thumb. -->  
    <attr name="switchTextAppearance" format="reference" />  
    <!-- Minimum width for the switch component -->  
    <attr name="switchMinWidth" format="dimension" />  
    <!-- Minimum space between the switch and caption text -->  
    <attr name="switchPadding" format="dimension" />  
</declare-styleable>  

以下是效果图:

 

android中Actionbar详解

1、什么是Action Bar
Action Bar被认为是新版Android系统中最重要的交互元素,在程序运行中一直置于顶部,主要起到的作用在于:
1)突出显示一些重要操作(如“最新”、“搜索”等)
2)在程序中保持统一的页面导航和切换方式
3)将使用频率低的功能放在Action overflow中,节省页面空间
4)一个固定区域显示程序标示

2、Action Bar分成四个区域
App Icon:可显示软件icon,也可用其他图标代替。当软件不在最高级页面时,图标左侧会显示一个左箭头,用户可以通过这个箭头向上导航。
视图切换:如果你的应用要在不同的View中显示数据,这部分允许用户来切换View。一般的作法是用一个drop-down菜单或者是Tab Controls。如果只有一个界面,那这里可以显示App Title或者更长点的商标信息
Action Buttons:这个放最重要的软件功能,放不下的按钮就自动进入Action overflow了。
Action overflow:把不常用的Actions移到Action overflow

3、屏幕旋转及不同分辨率适配
写一个应用时一个重要的UI问题就是如何适应屏幕旋转和不同尺寸的屏幕。你可以通过使用split action bars来适应这种变化,就是把action bar内容拆分到不同的bars里,拆分后一般包含三个部分:
Main action bar:用户可以通过main action
bar导航至上一级,因此这个操作条是必须的;
Top bar:当页面上有不同的内容视图时,可在这个条上使用TAB或spinner下拉菜单的形式切换;
Bottom bar:要展现更多操作和功能,在页面最下端排列

4、Contextual Action Bar (CAB)

“上下文操作栏”
(contextual action bar,CAB)
是一个浮于操作栏上的临时操作栏,用来放置一些特定的子任务。“上下文操作栏”一般在项目选择和文字选择时出现。


浏览器和
Gmail 应用中的上下文操作栏

长按可选择的内容,进入选择模式,显示上下文操作栏。

此时用户可以:

  • 通过触摸选择项目。
  • 在上下文操作栏中选择操作,并应用于所有已选项目。之后上下文操作栏自动消失。
  • 通过导航栏的“返回”按钮关闭上下文操作栏,也可以通过点击上下文操作栏的选择图标关闭它。关闭上下文操作栏的同时要取消所有的选择。

当您让用户长按来选择项目时,需要使用上下文操作栏。您可以控制上下文操作栏中的图标,使用户可以执行不同的操作。

5、ActionBar包含元素
1)Tabs
如果希望用户经常在几个部分间切换,可以使用Tabs。有两种Tabs:固定的(fixed)跟可滑动的(scrollable)
Scrollable:经常占据整个Bar的宽度,当前的活动View在中间位置,因此需要在一个专用的Bar里。可以自己水平的scroll,来显示更多其他的view。使用情况:如果有很多的Views或者你不确定有多少Views,因为可能是动态添加的。ScrollableTabs应该总是允许用户通过左右Swipe来切换Views。

Fixed Tabs:将所有标签显示在屏幕上,当方向变化时,它可能会被移动到Top bar位置去。

2)Spinners下拉框
官方给出使用spinner而不用tab的情况:
当不希望tab占据太多页面竖直方向上的空间
当用户认为不需要经常在视图之间切换时

3)Action buttons
要分清楚哪些Action是经常使用的,并根据这个来安排它们的位置。应该显示最常用的Actions,把其他不是常用的放到overflow里。
如果一个Action在当前不被使用,把它隐藏掉,而不是显示为不能用。
使用FIT表来分辨优先级。如果FIT中有一个适用,就把它放到Action bar,否则就放到Action overflow里。
F – Frequent 高频
当用户在这个页面时,是否10次中至少有7次会使用这个按钮?
用户是否通常要连续使用很多次?
如果每次使用该功能都要多一步操作,会不会很繁琐?
I– Important重要
你是否希望每个用户都能发现这个功能,或者因为它很酷或者是你的卖点?
你是否认为当需要用到这个按钮时,应该很容易触及?
T –Typical典型
在相似的软件中,这个功能是不是通常是的最重要操作?
在上下文环境下,如果这个操作按键被埋在overflow中,用户会不会惊讶?
下面的链接里包含一些系统自带操作的图标素材,针对不同屏幕分辨率,可以使用在Holo
Light和Holo Dark主题中;
另外包括图标的Adobe Illustrator源文件可供自行修改。
4)Action overflow
Action overflow中存放并不会频繁用到的操作。按照官方网页上的说法,“Overflow图标仅显示在没有MENU硬按键的手机上,而对于有MENU键的手机,
overflow图标是不显示的,当用户点击MENU按键时弹出。”这样的说法比较蹊跷,似乎和Google敦促手机厂商及软件开发商取消MENU的行为不相匹配。
6、Action bar上可以放下多少操作按钮?

如果操作按钮和软件标题等放在一排,放按钮的空间只能最多占用一半空间,如果按钮采用屏幕底部的整行action bar则可以使用整个屏幕宽度。

屏幕宽度值Density-independent Pixels(dp)决定可以放置的图标数:
少于360 dp = 2个图标
360-499 dp = 3个图标
500-599 dp = 4个图标
多于600 dp = 5个图标

本文参考:http://developer.android.com/design/patterns/actionbar.html

欢迎转载,但请注明出处与作者

出处:http://blog.sina.com.cn/staratsky

作者:流星