标签归档:Android

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

作者:流星

 

Android中全屏或者取消标题栏的三种方法

先介绍去掉标题栏的方法:

第一种:也一般入门的时候经常使用的一种方法

requestWindowFeature(Window.FEATURE_NO_TITLE);//去掉标题栏

注意这句一定要写在setContentView()方法的前面,不然会报错的

第二种:在AndroidManifest.xml文件中定义

<application android:icon=@drawable/icon
android:label
=@string/app_name
android:theme
=”@android:style/Theme.NoTitleBar”>

可以看出,这样写的话,整个应用都会去掉标题栏,如果只想去掉某一个Activity的标题栏的话,可以把这个属性加到activity标签里面

第三种:这种在一般的应用中不常用,就是在res/values目录下面新建一个style.xml的文件

例如:

<?xml version=”1.0″ encoding=”UTF-8″ ?>
<resources>
<style name=”notitle>
<item name=”android:windowNoTitle”>true</item>
</style> 
</resources>

这样,我们就自定义了一个style,就相当于一个主题,然后在AndroidManifest.xml文件中定义

<application android:icon=”@drawable/icon”
android:label
=”@string/app_name”
android:theme
=”@style/notitle>

这样也可以达到去掉标题栏的效果

三种去掉标题栏方法的总结

第一种,有的时候我们会看到,会先出现标题栏,然后再消失,因为我们只是在activity的oncreate方法中定义的,第二种相对第一种比较好一些,不会出现这种情况,第三种我个人感觉最好,这样把功能分开,便于维护和扩展

再介绍全屏的方法:

第一种

getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

第二种

android:theme=”@android:style/Theme.NoTitleBar.Fullscreen”

第三种

application android:icon=”@drawable/icon”
android:label
=”@string/app_name”
android:theme
=”@style/fullscreem”

大家自己总结一下吧,个人感觉第三种比较好,看自己的喜欢用吧

Android Fragments的使用

Fragment 表现 Activity 中用UI的一个行为或者一部分.可以组合多个fragment放在一个单独的activity中来创建一个多界面区域的UI,并可以在多个activity里重用某一个fragment.把fragment想象成一个activity的模块化区域, 有它自己的生命周期, 接收属于它的输入事件,并且可以在activity运行期间添加和删除.

Fragment 必须总是被嵌入到一个activity中, 它们的生命周期直接被其所属的宿主activity的生命周期影响.例如, 当activity被暂停,那么在其中的所有fragment也被暂停; 当activity被销毁,所有隶属于它的fragment也被销毁. 然而,当一个activity正在运行时(处于resumed状态),我们可以独立地操作每一个fragment, 比如添加或删除它们. 当处理这样一个fragment事务时,也可以将它添加到activity所管理的back stack — 每一个activity中的backstack实体都是一个发生过的fragment事务的记录. back stack允许用户通过按下 BACK按键从一个fragment事务后退(往后导航).

将一个fragment作为activity布局的一部分添加进来时, 它处在activity的viewhierarchy中的ViewGroup中,并且定义有它自己的view布局.通过在activity的布局文件中声明fragment来插入一个fragment到你的activity布局中,或者可以写代码将它添加到一个已存在的ViewGroup.然而, fragment并不一定必须是activity布局的一部分;也可以将一个fragment作为activity的隐藏的后台工作者.

本文档描述了如何使用fragment创建你的应用程序, 包括:当被添加到activity的back stack后,fragment如何维护他们的状态.在activity中,与activity和其他fragment共享事件.构建到activity的actionbar.以及更多内容.

设计哲学


Android在3.0中引入了fragments的概念,主要目的是用在大屏幕设备上–例如平板电脑上,支持更加动态和灵活的UI设计.平板电脑的屏幕要比手机的大得多,有更多的空间来放更多的UI组件,并且这些组件之间会产生更多的交互.Fragment允许这样的一种设计,而不需要你亲自来管理viewhierarchy的复杂变化. 通过将activity的布局分散到fragment中, 你可以在运行时修改activity的外观,并在由activity管理的back stack中保存那些变化.

例如, 一个新闻应用可以在屏幕左侧使用一个fragment来展示一个文章的列表,然后在屏幕右侧使用另一个fragment来展示一篇文章 – 2个fragment并排显示在相同的一个activity中,并且每一个fragment拥有它自己的一套生命周期回调方法,并且处理它们自己的用户输入事件. 因此, 取代使用一个activity来选择一篇文章,而另一个activity来阅读文章 的方式,用户可以在相同的activity中选择一篇文章并且阅读, 如图所示:

fragment在你的应用中应当是一个模块化和可重用的组件.即,因为fragment定义了它自己的布局, 以及通过使用它自己的生命周期回调方法定义了它自己的行为,你可以将fragment包含到多个activity中. 这点特别重要, 因为这允许你将你的用户体验适配到不同的屏幕尺寸.举个例子,你可能会仅当在屏幕尺寸足够大时,在一个activity中包含多个fragment,并且,当不属于这种情况时,会启动另一个单独的,使用不同fragment的activity.

继续之前那个新闻的例子 — 当运行在一个特别大的屏幕时(例如平板电脑),app可以在Activity A中嵌入2个fragment.然而,在一个正常尺寸的屏幕(例如手机)上,没有足够的空间同时供2个fragment用, 因此, Activity A会仅包含文章列表的fragment, 而当用户选择一篇文章时, 它会启动Activity B,它包含阅读文章的fragment. 因此, 应用可以同时支持图1中的2种设计模式.

创建Fragment


    要创建一个fragment, 必须创建一个 Fragment 的子类 (或者继承自一个已存在的它的子类). Fragment类的代码看起来很像 Activity .它包含了和activity类似的回调方法, 例如 onCreate(), onStart(),onPause, 以及 onStop(). 事实上, 如果你准备将一个现成的Android应用转换到使用fragment,你可能只需简单的将代码从你的activity的回调函数分别移动到你的fragment的回调方法.

    通常, 应当至少实现如下的生命周期方法:

 

 

  • onCreate()
    当创建fragment时, 系统调用此方法.
    在实现代码中,应当初始化想要在fragment中保持的必要组件, 当fragment被暂停或者停止后可以恢复.
  • onCreateView()
    fragment第一次绘制它的用户界面的时候, 系统会调用此方法. 为了绘制fragment的UI,此方法必须返回一个View, 这个view是你的fragment布局的根view. 如果fragment不提供UI, 可以返回null.
  • onPause()
    用户将要离开fragment时,系统调用这个方法作为第一个指示(然而它不总是意味着fragment将被销毁.) 在当前用户会话结束之前,通常应当在这里提交任何应该持久化的变化(因为用户有可能不会返回).

    大多数应用应当为每一个fragment实现至少这3个方法,但是还有一些其他回调方法你也应当用来去处理fragment生命周期的各种阶段.全部的生命周期回调方法将会在后面章节 Handlingthe Fragment Lifecycle 中讨论.

    除了继承基类 Fragment , 还有一些子类你可能会继承:

 

  • DialogFragment
    显示一个浮动的对话框.
    用这个类来创建一个对话框,是使用在Activity类的对话框工具方法之外的一个好的选择,
    因为你可以将一个fragment对话框合并到activity管理的fragment back stack中,允许用户返回到一个之前曾被摒弃的fragment.
  • ListFragment
    显示一个由一个adapter(例如 SimpleCursorAdapter)管理的项目的列表, 类似于ListActivity.
    它提供一些方法来管理一个list view, 例如 onListItemClick()回调来处理点击事件.
  • PreferenceFragment
    显示一个 Preference对象的层次结构的列表, 类似于PreferenceActivity.
    这在为你的应用创建一个”设置”activity时有用处.

添加一个用户界面


fragment通常用来作为一个activity的用户界面的一部分,并将它的layout提供给activity.为了给一个fragment提供一个layout,你必须实现 onCreateView()回调方法, 当到了fragment绘制它自己的layout的时候,Android系统调用它.你的此方法的实现代码必须返回一个你的fragment的layout的根view.

       注意: 如果你的fragment是ListFragment的子类,它的默认实现是返回从onCreateView()返回一个ListView,所以一般情况下不必实现它.

从onCreateView()返回的View, 也可以从一个xmllayout资源文件中读取并生成. 为了帮助你这么做, onCreateView() 提供了一个LayoutInflater 对象.

举个例子, 这里有一个Fragment的子类, 从文件 example_fragment.xml 加载了一个layout:

public static class ExampleFragment extends Fragment { 
         @Override 
         public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
             // Inflate the layout for this fragment 
             return inflater.inflate(R.layout.example_fragment, container, false); 
         } 
     }

 

传入 onCreateView() 的 container 参数是你的fragmentlayout将被插入的父ViewGroup(来自activity的layout).savedInstanceState 参数是一个Bundle, 如果fragment是被恢复的,它提供关于fragment的之前的实例的数据,

inflate() 方法有3个参数:

 

  • 想要加载的layout的resource ID.
  • 加载的layout的父ViewGroup.
    传入container是很重要的, 目的是为了让系统接受所要加载的layout的根view的layout参数,
    由它将挂靠的父view指定.
  • 布尔值指示在加载期间, 展开的layout是否应当附着到ViewGroup (第二个参数).
    (在这个例子中, 指定了false, 因为系统已经把展开的layout插入到container –传入true会在最后的layout中创建一个多余的view group.)

将fragment添加到activity
通常地, fragment为宿主activity提供UI的一部分, 被作为activity的整个viewhierarchy的一部分被嵌入. 有2种方法你可以添加一个fragment到activitylayout:

在activity的layout文件中声明fragment
你可以像为View一样, 为fragment指定layout属性.
例子是一个有2个fragment的activity:

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

<fragment> 中的 android:name属性指定了在layout中实例化的Fragment类.

当系统创建这个activity layout时,它实例化每一个在layout中指定的fragment,并调用每一个上的onCreateView()方法,来获取每一个fragment的layout.系统将从fragment返回的 View直接插入到<fragment>元素所在的地方.

        注意: 每一个fragment都需要一个唯一的标识,如果activity重启,系统可以用来恢复fragment(并且你也可以用来捕获fragment来处理事务,例如移除它.)

有3种方法来为一个fragment提供一个标识:

 

  • 为 android:id 属性提供一个唯一ID.
  • 为 android:tag 属性提供一个唯一字符串.
  • 如果以上2个你都没有提供, 系统使用容器view的ID.

撰写代码将fragment添加到一个已存在的ViewGroup.
当activity运行的任何时候, 都可以将fragment添加到activitylayout.只需简单的指定一个需要放置fragment的ViewGroup.为了在你的activity中操作fragment事务(例如添加,移除,或代替一个fragment),必须使用来自FragmentTransaction 的API.

可以按如下方法,从你的Activity取得一个 FragmentTransaction 的实例:

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

然后你可以使用 add() 方法添加一个fragment, 指定要添加的fragment, 和要插入的view.

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

 

add()的第一个参数是fragment要放入的ViewGroup, 由resource ID指定,第二个参数是需要添加的fragment.一旦用FragmentTransaction做了改变,为了使改变生效,必须调用commit().

添加一个无UI的fragment

之前的例子展示了对UI的支持, 如何将一个fragment添加到activity. 然而,也可以使用fragment来为activity提供后台行为而不用展现额外的UI.

要添加一个无UI的fragment, 需要从activity使用 add(Fragment, String) 来添加fragment (为fragment提供一个唯一的字符串”tag”, 而不是一个view ID).这么做添加了fragment,但因为它没有关联到一个activity layout中的一个view, 所以不会接收到onCreateView()调用.因此不必实现此方法.

为fragment提供一个字符串tag并不是专门针对无UI的fragment的 –也可以提供字符串tag给有UI的fragment – 但是如果fragment没有UI,那么这个tag是仅有的标识它的途径.如果随后你想从activity获取这个fragment, 需要使用 findFragmentByTag().

管理Fragment


要在activity中管理fragment,需要使用FragmentManager. 通过调用activity的getFragmentManager()取得它的实例.

可以通过FragmentManager做一些事情, 包括:

 

 

  • 使用findFragmentById() (用于在activitylayout中提供一个UI的fragment)或findFragmentByTag()(适用于有或没有UI的fragment)获取activity中存在的fragment
  • 将fragment从后台堆栈中弹出, 使用 popBackStack() (模拟用户按下BACK 命令).
  • 使用addOnBackStackChangeListener()注册一个监听后台堆栈变化的listener.

处理Fragment事务


关于在activity中使用fragment的很强的一个特性是:根据用户的交互情况,对fragment进行添加,移除,替换,以及执行其他动作.提交给activity的每一套变化被称为一个事务,可以使用在 FragmentTransaction 中的 API 处理.我们也可以保存每一个事务到一个activity管理的backstack,允许用户经由fragment的变化往回导航(类似于通过activity往后导航).

从 FragmentManager 获得一个FragmentTransaction的实例 :

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

每一个事务都是同时要执行的一套变化.可以在一个给定的事务中设置你想执行的所有变化,使用诸如 add(), remove(),和 replace().然后, 要给activity应用事务, 必须调用 commit().
在调用commit()之前, 你可能想调用 addToBackStack(),将事务添加到一个fragment事务的backstack. 这个back stack由activity管理, 并允许用户通过按下 BACK按键返回到前一个fragment状态.

举个例子, 这里是如何将一个fragment替换为另一个, 并在后台堆栈中保留之前的状态:

// Create new fragment and transaction
Fragment newFragment = new ExampleFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();

在这个例子中, newFragment替换了当前layout容器中的由R.id.fragment_container标识的fragment.通过调用addToBackStack(), replace事务被保存到back stack,因此用户可以回退事务,并通过按下BACK按键带回前一个fragment.

如果添加多个变化到事务(例如add()或remove())并调用addToBackStack(),然后在你调用commit()之前的所有应用的变化会被作为一个单个事务添加到后台堆栈, BACK按键会将它们一起回退.

添加变化到 FragmentTransaction的顺序不重要, 除以下例外:

 

 

  • 必须最后调用 commit().
  • 如果添加多个fragment到同一个容器, 那么添加的顺序决定了它们在view hierarchy中显示的顺序.

 

当执行一个移除fragment的事务时, 如果没有调用 addToBackStack(), 那么当事务提交后,那个fragment会被销毁,并且用户不能导航回到它. 有鉴于此, 当移除一个fragment时,如果调用了addToBackStack(), 那么fragment会被停止, 如果用户导航回来,它将会被恢复.

提示: 对于每一个fragment事务, 你可以应用一个事务动画,通过在提交事务之前调用setTransition()实现.

调用 commit() 并不立即执行事务.恰恰相反, 它将事务安排排期, 一旦准备好,就在activity的UI线程上运行(主线程).如果有必要, 无论如何, 你可以从你的UI线程调用executePendingTransactions()来立即执行由commit()提交的事务. 但这么做通常不必要,除非事务是其他线程中的job的一个从属.

       警告:你只能在activity保存它的状态(当用户离开activity)之前使用commit()提交事务.

如果你试图在那个点之后提交, 会抛出一个异常.这是因为如果activity需要被恢复,提交之后的状态可能会丢失.对于你觉得可以丢失提交的状况, 使用 commitAllowingStateLoss().

与Activity通信


尽管Fragment被实现为一个独立于Activity的对象,并且可以在多个activity中使用,但一个给定的fragment实例是直接绑定到包含它的activity的. 特别的,fragment可以使用 getActivity() 访问Activity实例, 并且容易地执行比如在activitylayout中查找一个view的任务.

View listView = getActivity().findViewById(R.id.list);

同样地,activity可以通过从FragmentManager获得一个到Fragment的引用来调用fragment中的方法, 使用findFragmentById() 或 findFragmentByTag().

ExampleFragment fragment = (ExampleFragment) getFragmentManager().findFragmentById(R.id.example_fragment);

android BottomTabBar 代码示例


 1 在Android app开发过程中,会发现很多App的底部(顶部一样) 会仿效IPHONE的设计。。做一个导航。  如下图黑色部分:


(这个是实现效果)                                                                 这个是设计原型

 

1.1 要是中间部分没有那个拱起来的部分,那么可能设计还简单一些。。 仔细分析下设计原型,,,中间那个 摇摇 的图标要大一些,而且和其他图标没在一个水平线上。

 

1.2  总的思想就是 先封装一个 没有 凸起 的通用,自动适配的组。。。然后。。。在上面 通过 FrameLayout 放置一个 突起的组建。。。

 

1.3 设计细节

1.3.1  自己写一个  BottomTabBar   (extends) LinearLayout .  通过 Inflater 加载一个 自定义的 View (通过xml配置), 在View 的xml 中,注意书写好适配就OK了。

注意 layout_weight 的使用。(参见上一篇 listview)

 

 

自定义LinearLayout:

 

package com.dp.android.widget;
import com.dp.android.elong.shake.R;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
public class BottomTabBar extends LinearLayout {
    //--implements two kinds of constructions--
    public  BottomTabBar(Context context) {
        super(context);
        init(context);
    }
    public BottomTabBar(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }
    private void init(Context context) {
        LayoutParams lp = new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT);
        setLayoutParams(lp);
        LayoutInflater mInflater = LayoutInflater.from(context);
        View v = mInflater.inflate(R.layout.bottom_tabs, null);
        addView(v,lp);
    }
}

 

自定义的View(xml 形式)

<?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
       xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        >
        <!-- 搜索 -->
        <LinearLayout
            android:id="@+id/ll_bottom_tabls_search"
            style = "@style/bottom_tabs_ll"
            >
            <ImageView
                android:id="@+id/im_search"
                style = "@style/bottom_tabs_image"
                android:src="@drawable/bottom_tab_search" />
            <TextView
                style = "@style/bottom_tabs_tv"
                android:text="@string/bottom_tab_search"
                />
         </LinearLayout>
        <!-- 摇过 -->
        <LinearLayout
            android:id="@+id/ll_bottom_tabls_history"
            style = "@style/bottom_tabs_ll"
            >
            <ImageView
                android:id="@+id/im_history"
                style = "@style/bottom_tabs_image"
                android:src="@drawable/bottom_tab_history" />
            <TextView
                style = "@style/bottom_tabs_tv"
                android:text="@string/bootom_tab_shake"
                />
         </LinearLayout>
        <!-- 换一个 -->
        <LinearLayout
            android:id="@+id/ll_bottom_tabls_change"
            style = "@style/bottom_tabs_ll"
            >
            <ImageView
                android:id="@+id/im_change"
                style = "@style/bottom_tabs_image"
                android:src="@drawable/bottom_tab_blank"
                />
            <TextView
                style = "@style/bottom_tabs_tv"
                android:text="@string/bottom_tab_change"
                />
         </LinearLayout>
        <!-- 收藏 -->
        <LinearLayout
            android:id="@+id/ll_bottom_tabls_collection"
            style = "@style/bottom_tabs_ll"
            >
            <ImageView
                android:id="@+id/im_collection"
                style = "@style/bottom_tabs_image"
                android:src="@drawable/bottom_tab_collection"
                />
            <TextView
                style = "@style/bottom_tabs_tv"
                android:text="@string/bootom_tab_collection"
                />
         </LinearLayout>
        <!-- 更多 -->
        <LinearLayout
            android:id="@+id/ll_bottom_tabls_more"
            style = "@style/bottom_tabs_ll"
            >
            <ImageView
                android:id="@+id/im_more"
                style = "@style/bottom_tabs_image"
                android:src="@drawable/bottom_tab_more"
                />
            <TextView
                style = "@style/bottom_tabs_tv"
                android:text="@string/bootom_tab_more"
                />
         </LinearLayout>
    </LinearLayout>

 

view 中用到的 三个 style

<style name="bottom_tabs_ll" >
    <item name="android:layout_width">wrap_content</item>
    <item name="android:layout_height">wrap_content</item>
    <item name="android:background">@color/black</item>
    <item name="android:orientation">vertical</item>
    <item name="android:gravity">center</item>
    <item name="android:layout_gravity">bottom</item>
    <item name="android:layout_weight">1</item>
</style>
<style name="bottom_tabs_image" >
    <item name="android:layout_width">fill_parent</item>
    <item name="android:layout_height">wrap_content</item>
    <item name="android:paddingTop">5dip</item>
</style>
<style name="bottom_tabs_tv" >
    <item name="android:layout_width">fill_parent</item>
    <item name="android:layout_height">wrap_content</item>
    <item name="android:textSize">12sp</item>
    <item name="android:textColor">@color/common_white</item>
    <item name="android:paddingTop">3dip</item>
    <item name="android:gravity">center</item>
</style>

//—————————————————————下面是如何使用自己定义的 组建了————————————-

1: 注意 BottomTabBar ,,, 这里面还用到了自定义的 “凸起” 组件。 MyBottmArc

 

<FrameLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@color/shake_yellow_bg"
android:orientation="vertical"
>
<com.dp.android.widget.BottomTabBar
android:id="@+id/bottom_tab_bar1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingTop="30dip"
/>

<com.dp.android.widget.MyBottmArc
android:id="@+id/im_change"
android:layout_width="80dip"
android:layout_height="60dip"
android:padding="15dip"
android:src="@drawable/bottom_tab_search"
android:layout_gravity="top|center_horizontal"
/>

</FrameLayout>

 

//————————————————————————————–下面看看  凸起 是怎么弄的———————————————————————————

凸起 也是自己定义了一个 ImageView,  这个ImageView 的背景  就是绘制半个 圆弧。。。“拱形”

 

package com.dp.android.widget;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.widget.ImageView;
public class MyBottmArc extends ImageView {
    private static Paint paint = new Paint();
    public MyBottmArc(Context context) {
        super(context);
    }
    public MyBottmArc(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    public MyBottmArc(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }
    protected void onDraw(Canvas canvas) {
        Rect m_rect = canvas.getClipBounds();
        canvas.save();
        paint.setColor(0xff000000);
        float m_left = m_rect.left;
        float m_top = m_rect.top;
        float m_right = m_rect.right;
        float m_bottom = (1.2f)*(m_rect.bottom);
        RectF m_rectf = new RectF(m_left,m_top,m_right,m_bottom);
        canvas.drawOval(m_rectf, paint);
        canvas.restore();
        super.onDraw(canvas);
    }
}

 

 

Android 面试题(答案最全)

  1. Android dvm的进程和Linux的进程, 应用程序的进程是否为同一个概念?

    DVM指dalivk的虚拟机。每一个Android应用程序都在它自己的进程中运行,都拥有一个独立的Dalvik虚拟机实例。而每一个DVM都是在Linux 中的一个进程,所以说可以认为是同一个概念。

  2. sim卡的EF 文件有何作用?

    sim卡的文件系统有自己规范,主要是为了和手机通讯,sim本 身可以有自己的操作系统,EF就是作存储并和手机通讯用的

  3. 嵌入式操作系统内存管理有哪几种, 各有何特性?

    页式,段式,段页,用到了MMU,虚拟空间等技术

  4. 什么是嵌入式实时操作系统, Android 操作系统属于实时操作系统吗?

    嵌入式实时操作系统是指当外界事件或数据产生时,能够接受并以足够快的速度予以处理,其处理的结果又能在规定的时间之内来控制生产过程或对处理系统作出快速响应,并控制所有实时任务协调一致运行的嵌入式操作系统。主要用于工业控制、 军事设备、 航空航天等领域对系统的响应时间有苛刻的要求,这就需要使用实时系统。又可分为软实时和硬实时两种,而android是基于linux内核的,因此属于软实时。

  5. 一条最长的短信息约占多少byte?

    中文70(包括标点),英文160,160个字节。

  6. android中的动画有哪几类,它们的特点和区别是什么?

    两种,一种是Tween动画、还有一种是Frame动画。Tween动画,这种实现方式可以使视图组件移动、放大、缩小以及产生透明度的变化;另一种Frame动画,传统的动画方法,通过顺序的播放排列好的图片来实现,类似电影。

  7. handler机制的原理

    andriod提供了 Handler 和 Looper 来满足线程间的通信。Handler 先进先出原则。Looper类用来管理特定线程内对象之间的消息交换(Message Exchange)。
    1)Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的Message Queue(消息队列)。
    2)Handler: 你可以构造Handler对象来与Looper沟通,以便push新消息到Message Queue里;或者接收Looper从Message Queue取出)所送来的消息。
    3) Message Queue(消息队列):用来存放线程放入的消息。
    4)线程:UI thread 通常就是main thread,而Android启动程序时会替它建立一个Message Queue。

  8. 说说mvc模式的原理,它在android中的运用

android的官方建议应用程序的开发采用mvc模式。何谓mvc?
mvc是model,view,controller的缩写,mvc包含三个部分:
* 模型(model)对象:是应用程序的主体部分,所有的业务逻辑都应该写在该层。
* 视图(view)对象:是应用程序中负责生成用户界面的部分。也是在整个mvc架构>中用户唯一可以看到的一层,接收用户的输入,显示处理结果。
* 控制器(control)对象:是根据用户的输入,控制用户界面数据显示及更新>model对象状态的部分,控制器更重要的一种导航功能,想用用户出发的相关事件,交给m哦得了处理。

android鼓励弱耦合和组件的重用,在android中mvc的具体体现如下:

  • 视图层(view):一般采用xml文件进行界面的描述,使用的时候可以非常方便的引入,当然,如何你对android了解的比较的多了话,就一定 可以想到在android中也可以使用javascript+html等的方式作为view层,当然这里需要进行java和javascript之间的通 信,幸运的是,android提供了它们之间非常方便的通信实现。
  • 控制层(controller):android的控制层的重 任通常落在了众多的acitvity的肩上,这句话也就暗含了不要在acitivity中写代码,要通过activity交割model业务逻辑层处理, 这样做的另外一个原因是android中的acitivity的响应时间是5s,如果耗时的操作放在这里,程序就很容易被回收掉。
  • 模型层(model):对数据库的操作、对网络等的操作都应该在model里面处理,当然对业务计算等操作也是必须放在的该层的。

9.Activity的生命周期

和其他手机 平台 的应用 程序 一样,Android的应用程序 的生命周期是被统一掌控 的,也就是说我们写的应用程序命运掌握在别人(系统)的手里,我们不能改变它,只能学习 并适应它。
简单地说一下为什么是这样:我们手机在运行 一个应用程序的时候,有可能打进来电话发进来短信 ,或者没有电了,这时候程序都会被中断,优先去服务电话的基本功能 ,另外系统也不允许你占用太多资源 ,至少要保证电话功能吧,所以资源不足的时候也就有可能被干掉。
言归正传,Activity的基本生命周期如下代码 所示:

public class MyActivity extends Activity {
  protected void onCreate(Bundle savedInstanceState);
  protected void onStart();
  protected void onResume();
  protected void onPause();
  protected void onStop();
  protected void onDestroy();
}

你自己写的Activity会按需要 重载这些方法,onCreate是免不了的,在一个Activity正常启动的过程中,他们被调用的顺序是
onCreate -> onStart -> onResume,
在Activity被干掉的时候顺序是onPause -> onStop -> onDestroy ,这样就是一个完整的生命周期。
但是有人问了,程序正运行着呢来电话了,这个程序咋办?中止了呗,如果中止的时候新出的一个Activity是全屏的,那么:onPause->onStop ,恢复的时候onStart->onResume ,如果打断 这个应用程序的是一个Theme为Translucent 或者Dialog 的Activity那么只是onPause ,恢复 的时候onResume 。
详细介绍一下这几个方法中系统在做什么以及我们应该做什么:

onCreate: 在这里创建界面 ,做一些数据 的初始化工作
onStart: 到这一步变成用户可见不可交互 的
onResume: 变成和用户可交互 的,(在activity 栈系统通过栈的方式管理这些个
Activity的最上面,运行完弹出栈,则回到上一个Activity)
onPause: 到这一步是可见但不可交互 的,系统会停止动画 等消耗CPU 的事情
从上文的描述已经知道,应该在这里保存你的一些数据,因为这个时候
你的程序的优先级降低,有可能被系统收回。在这里保存的数据,应该在
onResume里读出来,注意:这个方法里做的事情时间要短,因为下一
个activity不会等到这个方法完成才启动
onstop: 变得不可见 ,被下一个activity覆盖了
onDestroy: 这是activity被干掉前最后一个被调用方法了,可能是外面类调用finish方法或者是系统为了节省空间将它暂时性的干掉,可以用isFinishing()来判断它,如果你有一个Progress Dialog在线程中转动,请在onDestroy里
把他cancel掉,不然等线程结束的时候,调用Dialog的cancel方法会抛
异常的。

onPause,onstop, onDestroy,三种状态 下 activity都有可能被系统干掉
为了保证程序的正确性,你要在onPause()里写上持久层操作的代码,将用户编辑的内容都保存到存储介质上(一般都是数据库 )。实际工作中因为生命周期的变化而带来的问题也很多,比如你的应用程序起了新的线程在跑,这时候中断了,你还要去维护那个线程,是暂停还是杀掉还是数据 回滚,是吧?因为Activity可能被杀掉,所以线程中使用的变量和一些界面元素就千万要注意了,一般都是采用Android的消息机制 [Handler,Message]来处理多线程和界面交互的问题。

10.让Activity变成一个窗口:Activity属性设定

讲点轻松的吧,可能有人希望做出来的应用程序是一个漂浮在手机主界面的东西,那么很简单你只需要设置 一下Activity的主题就可以了在AndroidManifest.xml 中定义 Activity的地方一句话:

android :theme=”@android:style/Theme.Dialog”
android:theme=”@android:style/Theme.Dialog”

这就使你的应用程序变成对话框的形式弹出来了,或者

android:theme=”@android:style/Theme.Translucent”
android:theme=”@android:style/Theme.Translucent”

就变成半透明的,[友情提示-.-]类似的这种activity的属性可以在android.R.styleable 类的AndroidManifestActivity 方法中看到,AndroidManifest.xml中所有元素的属性的介绍都可以参考这个类android.R.styleable上面说的是属性名称,具体有什么值是在android.R.style中 可以看到,比如这个”@android:style/Theme.Dialog” 就对应于android.R.style.Theme_Dialog ,(‘_’换成’.’ < –注意:这个是文章内容不是笑脸)就可以用在描述文件 中了,找找类定义和描述文件中的对应关系就都明白了。

11.你后台的Activity被系统回收怎么办?

onSaveInstanceState
当你的程序中某一个Activity A 在运行时中,主动或被动地运行另一个新的Activity B. 这个时候A会执行

public void onSaveInstanceState(Bundle outState) {
  super.onSaveInstanceState(outState);
  outState.putLong("id", 1234567890);
}

B 完成以后又会来找A, 这个时候就有两种情况,一种是A被回收,一种是没有被回收,被回收的A就要重新调用onCreate()方法,不同于直接启动的是这回onCreate()里是带上参数savedInstanceState,没被收回的就还是onResume就好了。
savedInstanceState是一个Bundle对象,你基本上可以把他理解为系统帮你维护的一个Map对象。在onCreate()里你可能会用到它,如果正常启动onCreate就不会有它,所以用的时候要判断一下是否为空。

if(savedInstanceState != null){
  long id = savedInstanceState.getLong("id");
}

就像官方的Notepad教程 里的情况,你正在编辑某一个note,突然被中断,那么就把这个note的id记住,再起来的时候就可以根据这个id去把那个note取出来,程序就完整一些。这也是看你的应用需不需要保存什么,比如你的界面就是读取一个列表,那就不需要特殊记住什么,哦, 没准你需要记住滚动条的位置…

12.调用与被调用:我们的通信使者Intent

要说Intent了,Intent就是这个这个意图 ,应用程序间Intent进行交流,打个电话啦,来个电话啦都会发Intent, 这个是Android架构的松耦合的精髓部分,大大提高了组件的复用性,比如你要在你的应用程序中点击按钮,给某人打电话,很简单啊,看下代码先:

Intent intent = new Intent();
intent.setAction(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:" + number));
startActivity(intent);

扔出这样一个意图,系统看到了你的意图就唤醒了电话拨号程序,打出来电话。什么读联系人,发短信啊,邮件啊,统统只需要扔出intent就好了,这个部分设计 地确实很好啊。
那Intent通过什么来告诉系统需要谁来接受他呢?
通常使用Intent有两种方法,第一种是直接说明需要哪一个类来接收代码如下:

Intent intent = new Intent(this, MyActivity.class);
intent.getExtras().putString("id", "1");
tartActivity(intent);

第一种方式很明显,直接指定了MyActivity为接受者,并且传了一些数据给MyActivity,在MyActivity里可以用getIntent()来的到这个intent和数据。
第二种就需要先看一下AndroidMenifest中的intentfilter的配置了


< action android:name="android.intent.action.VIEW"/>
< action android:value="android.intent.action.EDIT"/>
< action android:value="android.intent.action.PICK"/>
< category android:name="android.intent.category.DEFAULT"/>
< data android:mimeType="vnd.android.cursor.dir/vnd.google.note"/>

这里面配置用到了action, data, category这些东西,那么聪明的你一定想到intent里也会有这些东西,然后一匹配不就找到接收者了吗?
action其实就是一个意图的字符串名称。
上面这段intent-filter的配置文件说明了这个Activity可以接受不同的Action,当然相应的程序逻辑也不一样咯,提一下那个 mimeType,他是在ContentProvider里定义的,你要是自己实现一个ContentProvider就知道了,必须指定 mimeType才能让数据被别人使用。
不知道原理说明白没,总结一句,就是你调用别的界面不是直接new那个界面,而是通过扔出一个intent,让系统帮你去调用那个界面,这样就多么松藕合啊,而且符合了生命周期被系统管理的原则。
想知道category都有啥,Android为你预先定制好的action都有啥等等,请亲自访问官方链接Intent
ps:想知道怎么调用系统应用程序的同学,可以仔细看一下你的logcat,每次运行一个程序的时候是不是有一些信息比如:

Starting activity: Intent { action=android.intent.action.MAINcategories={android.intent.category.LAUNCHER} flags=x10200000comp={com.android.camera/com.android.camera.GalleryPicker} }

再对照一下Intent的一些set方法,就知道怎么调用咯,希望你喜欢:)

13.如何退出Activity?如何安全退出已调用多个Activity的Application?

对于单一Activity的应用来说,退出很简单,直接finish()即可。
当然,也可以用killProcess()和System.exit()这样的方法。

但是,对于多Activity的应用来说,在打开多个Activity后,如果想在最后打开的Activity直接退出,上边的方法都是没有用的,因为上边的方法都是结束一个Activity而已。
当然,网上也有人说可以。
就好像有人问,在应用里如何捕获Home键,有人就会说用keyCode比较KEYCODE_HOME即可,而事实上如果不修改framework,根本不可能做到这一点一样。
所以,最好还是自己亲自试一下。

那么,有没有办法直接退出整个应用呢?
在2.1之前,可以使用ActivityManager的restartPackage方法。
它可以直接结束整个应用。在使用时需要权限android.permission.RESTART_PACKAGES。
注意不要被它的名字迷惑。

可是,在2.2,这个方法失效了。
在2.2添加了一个新的方法,killBackgroundProcesses(),需要权限 android.permission.KILL_BACKGROUND_PROCESSES。
可惜的是,它和2.2的restartPackage一样,根本起不到应有的效果。

另外还有一个方法,就是系统自带的应用程序管理里,强制结束程序的方法,forceStopPackage()。
它需要权限android.permission.FORCE_STOP_PACKAGES。
并且需要添加android:sharedUserId=”android.uid.system”属性
同样可惜的是,该方法是非公开的,他只能运行在系统进程,第三方程序无法调用。
因为需要在Android.mk中添加LOCAL_CERTIFICATE := platform。
而Android.mk是用于在Android源码下编译程序用的。

从以上可以看出,在2.2,没有办法直接结束一个应用,而只能用自己的办法间接办到。

现提供几个方法,供参考:

1、抛异常强制退出:
该方法通过抛异常,使程序Force Close。
验证可以,但是,需要解决的问题是,如何使程序结束掉,而不弹出Force Close的窗口。

2、记录打开的Activity:
每打开一个Activity,就记录下来。在需要退出时,关闭每一个Activity即可。

3、发送特定广播:
在需要结束应用时,发送一个特定的广播,每个Activity收到广播后,关闭即可。

4、递归退出
在打开新的Activity时使用startActivityForResult,然后自己加标志,在onActivityResult中处理,递归关闭。

除了第一个,都是想办法把每一个Activity都结束掉,间接达到目的。
但是这样做同样不完美。
你会发现,如果自己的应用程序对每一个Activity都设置了nosensor,在两个Activity结束的间隙,sensor可能有效了。
但至少,我们的目的达到了,而且没有影响用户使用。

为了编程方便,最好定义一个Activity基类,处理这些共通问题。
摘自:http://blog.csdn.net/debug2/archive/2011/02/18/6193644.aspx

14.请介绍下Android中常用的五种布局。

  1. LinearLayout – 线性布局。
    orientation – 容器内元素的排列方式。vertical: 子元素们垂直排列;horizontal: 子元素们水平排列
    gravity – 内容的排列形式。
    常用的有 top, bottom, left, right, center 等
  2. AbsoluteLayout – 绝对布局。
    layout_x – x 坐标。以左上角为顶点
    layout_y – y 坐标。以左上角为顶点
  3. TableLayout – 表格式布局
    表格布局主要以行列的形式来管理子控件,其中每一行即一个TableRow对象,每个TableRow对象可以添加子控件,并且每加入一个空间即相当于添加了一列
  4. RelativeLayout – 相对布局。
    layout_centerInParent – 将当前元素放置到其容器内的水平方向和垂直方向的中央位置(类似的属性有 :layout_centerHorizontal, layout_alignParentLeft 等)
    layout_marginLeft – 设置当前元素相对于其容器的左侧边缘的距离
    layout_below – 放置当前元素到指定的元素的下面
    layout_alignRight – 当前元素与指定的元素右对齐
  5. FrameLayout – 层叠布局。以左上角为起点,将 FrameLayout 内的元素一层覆盖一层地显示,在帧布局中,先添加的图片会被后添加的图片覆盖。
    摘自:http://javalover00000.javaeye.com/blog/851266

15.请介绍下Android的数据存储方式。

Android提供了5种方式存储数据:
* 使用SharedPreferences存储数据;
* 文件存储数据;
* SQLite数据库存储数据;
* 使用ContentProvider存储数据;
* 网络存储数据;
Android 中的数据存储都是私有的,其他应用程序都是无法访问的,除非通过ContentResolver获取其他程序共享的数据。
摘自:http://www.moandroid.com/?p=319

16.请介绍下ContentProvider是如何实现数据共享的。

一个程序可以通过实现一个Content provider的抽象接口将自己的数据完全暴露出去,而且Content providers是以类似数据库中表的方式将数据暴露。Content providers存储和检索数据,通过它可以让所有的应用程序访问到,这也是应用程序之间唯一共享数据的方法。要想使应用程序的数据公开化,可通过2种方法:创建一个属于你自己的Content provider或者将你的数据添加到一个已经存在的Content provider中,前提是有相同数据类型并且有写入Content provider的权限。

如何通过一套标准及统一的接口获取其他应用程序暴露的数据?Android提供了ContentResolver,外界的程序可以通过ContentResolver接口访问ContentProvider提供的数据。
参考:http://www.moandroid.com/?p=319

17.如何启用Service,如何停用Service。

1.第一种是通过调用Context.startService()启动,调用Context.stopService()结束,startService()可以传递参数给Service

2.第二种方式是通过调用Context.bindService()启动,调用Context.unbindservice()结束,还可以通过ServiceConnection访问Service。
在Service每一次的开启关闭过程中,只有onStart可被多次调用(通过多次startService调用),其他onCreate,onBind,onUnbind,onDestory在一个生命周期中只能被调用一次。
参考:http://www.cnblogs.com/feisky/archive/2010/06/14/1758336.html

18.注册广播有几种方式,这些方式有何优缺点?请谈谈Android引入广播机制的用意。

android中,不同进程之间传递信息要用到广播,可以有两种方式来实现。
第一种方式:在Manifest.xml中注册广播,是一种比较推荐的方法,因为它不需要手动注销广播(如果广播未注销,程序退出时可能会出错)。
具体实现在Manifest的application中添加:

上面两个android:name分别是广播名和广播的动作(这里的动作是表示系统启动完成),如果要自己发送一个广播,在代码中为:

Intent i = new Intent(“android.intent.action.BOOT_COMPLETED”);
sendBroadcast(i);

这样,广播就发出去了,然后是接收。
接收可以新建一个类,继承至BroadcastReceiver,也可以建一个BroadcastReceiver的实例,然后得写onReceive方法,实现如下:

protected BroadcastReceiver mEvtReceiver = new BroadcastReceiver() {
  @Override
  public void onReceive(Context context, Intent intent) {
      String action = intent.getAction();
      if (action.equals(“android.intent.action.BOOT_COMPLETED”))      {
      //Do something
      }
  }
};

第二种方式,直接在代码中实现,但需要手动注册注销,实现如下:

IntentFilter filter = new IntentFilter();
filter.addAction(“android.intent.action.BOOT_COMPLETED”);
registerReceiver(mEvtReceiver, filter); 

这时注册了一个recevier ,名为mEvtReceiver,然后同样用上面的方法以重写onReceiver,
最后在程序的onDestroy中要注销广播,实现如下:

@Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(mPlayerEvtReceiver);
}

Android系统中的广播是广泛用于应用程序之间通信的一种手段,它类似于事件处理机制,不同的地方就是广播的处理是系统级别的事件处理过程(一般事件处理是控件级别的)。在此过程中仍然是离不开Intent对象,理解广播事件的处理过程,灵活运用广播处理机制,在关键之处往往能实现特别的效果,
在Android 中如果要发送一个广播必须使用sendBroadCast 向系统发送对其感兴趣的广播接收器中。
使用广播必须要有一个intent 对象必设置其action动作对象
使用广播必须在配置文件中显式的指明该广播对象
每次接收广播都会重新生成一个接收广播的对象
在BroadCast 中尽量不要处理太多逻辑问题,建议复杂的逻辑交给Activity 或者 Service 去处理
转自:http://www.dengdeng.name/u/deng/archives/2010/92.html

http://www.cnblogs.com/TerryBlog/archive/2010/08/16/1801016.html

19.请解释下在单线程模型中Message、Handler、Message Queue、Looper之间的关系。

简单的说,Handler获取当前线程中的looper对象,looper用来从存放Message的MessageQueue中取出Message,再有Handler进行Message的分发和处理
参见:http://hi.baidu.com/%C1%F7%C0˲%BB%D0%DD/blog/item/4e576b7c58d742360cd7dac9.html

http://blog.csdn.net/xuxinyl/archive/2010/12/25/6097560.aspx

20.AIDL的全称是什么?如何工作?能处理哪些类型的数据?

AIDL全称Android Interface Definition Language(AndRoid接口描述语言) 是一种接口描述语言; 编译器可以通过aidl文件生成一段代码,通过预先定义的接口达到两个进程内部通信进程跨界对象访问的目的.AIDL的IPC的机制和COM或CORBA类似, 是基于接口的,但它是轻量级的。它使用代理类在客户端和实现层间传递值. 如果要使用AIDL, 需要完成2件事情:
1. 引入AIDL的相关类.;
2. 调用aidl产生的class.
理论上, 参数可以传递基本数据类型和String, 还有就是Bundle的派生类, 不过在Eclipse中,目前的ADT不支持Bundle做为参数,
具体实现步骤如下:

1、创建AIDL文件, 在这个文件里面定义接口, 该接口定义了可供客户端访问的方法和属性。

2、编译AIDL文件, 用Ant的话, 可能需要手动, 使用Eclipse plugin的话,可以根据adil文件自动生产java文件并编译, 不需要人为介入.

3、在Java文件中, 实现AIDL中定义的接口. 编译器会根据AIDL接口, 产生一个JAVA接口。这个接口有一个名为Stub的内部抽象类,它继承扩展了接口并实现了远程调用需要的几个方法。接下来就需要自己去实现自定义的几个接口了.
4、向客户端提供接口ITaskBinder, 如果写的是service,扩展该Service并重载onBind ()方法来返回一个实现上述接口的类的实例。
5、在服务器端回调客户端的函数. 前提是当客户端获取的IBinder接口的时候,要去注册回调函数, 只有这样, 服务器端才知道该调用那些函数

AIDL语法很简单,可以用来声明一个带一个或多个方法的接口,也可以传递参数和返回值。 由于远程调用的需要, 这些参数和返回值并不是任何类型.下面是些AIDL支持的数据类型:

  1. 不需要import声明的简单Java编程语言类型(int,boolean等)
  2. String, CharSequence不需要特殊声明
  3. List, Map和Parcelables类型, 这些类型内所包含的数据成员也只能是简单数据类型, String等其他比支持的类型.

(另外: 我没尝试Parcelables, 在Eclipse+ADT下编译不过, 或许以后会有所支持).

实现接口时有几个原则:

.抛出的异常不要返回给调用者. 跨进程抛异常处理是不可取的.

.IPC调用是同步的。如果你知道一个IPC服务需要超过几毫秒的时间才能完成地话,你应该避免在Activity的主线程中调用。 也就是IPC调用会挂起应用程序导致界面失去响应. 这种情况应该考虑单起一个线程来处理.

.不能在AIDL接口中声明静态属性。

IPC的调用步骤:

  1. 声明一个接口类型的变量,该接口类型在.aidl文件中定义。
  2. 实现ServiceConnection。
  3. 调用ApplicationContext.bindService(),并在ServiceConnection实现中进行传递.
  4. 在ServiceConnection.onServiceConnected()实现中,你会接收一个IBinder实例(被调用的Service). 调用

YourInterfaceName.Stub.asInterface((IBinder)service)将参数转换为YourInterface类型。

  1. 调用接口中定义的方法。 你总要检测到DeadObjectException异常,该异常在连接断开时被抛出。它只会被远程方法抛出。
  2. 断开连接,调用接口实例中的ApplicationContext.unbindService()
    参考:http://buaadallas.blog.51cto.com/399160/372090

21.请解释下Android程序运行时权限与文件系统权限的区别。

apk程序是运行在虚拟机上的,对应的是Android独特的权限机制,只有体现到文件系统上时才使用linux的权限设置。
android系统有的权限是基于签名的。
具体参见:http://blog.csdn.net/Zengyangtech/archive/2010/07/20/5749999.aspx

22.系统上安装了多种浏览器,能否指定某浏览器访问指定页面?请说明原由。

通过直接发送Uri把参数带过去,或者通过manifest里的intentfilter里的data属性

23.有一个一维整型数组int[]data保存的是一张宽为width,高为height的图片像素值信息。请写一个算法,将该图片所有的白色不透明(0xffffffff)像素点的透明度调整为50%。

24.什么是ANR 如何避免它?

ANR:Application Not Responding,五秒在Android中,活动管理器和窗口管理器这两个系统服务负责监视应用程序的响应。当出现下列情况时,Android就会显示ANR对话框了:
对输入事件(如按键、触摸屏事件)的响应超过5秒
意向接受器(intentReceiver)超过10秒钟仍未执行完毕
Android应用程序完全运行在一个独立的线程中(例如main)。这就意味着,任何在主线程中运行的,需要消耗大量时间的操作都会引发ANR。因为此时,你的应用程序已经没有机会去响应输入事件和意向广播(Intent broadcast)。
因此,任何运行在主线程中的方法,都要尽可能的只做少量的工作。特别是活动生命周期中的重要方法如onCreate()和 onResume()等更应如此。潜在的比较耗时的操作,如访问网络和数据库;或者是开销很大的计算,比如改变位图的大小,需要在一个单独的子线程中完成 (或者是使用异步请求,如数据库操作)。但这并不意味着你的主线程需要进入阻塞状态已等待子线程结束 — 也不需要调用Therad.wait()或者Thread.sleep()方法。取而代之的是,主线程为子线程提供一个句柄(Handler),让子线程 在即将结束的时候调用它(xing:可以参看Snake的例子,这种方法与以前我们所接触的有所不同)。使用这种方法涉及你的应用程序,能够保证你的程序 对输入保持良好的响应,从而避免因为输入事件超过5秒钟不被处理而产生的ANR。这种实践需要应用到所有显示用户界面的线程,因为他们都面临着同样的超时 问题。

25.什么情况会导致Force Close ?如何避免?能否捕获导致其的异常?

一般像空指针啊,可以看起logcat,然后对应到程序中 来解决错误

26.Android本身的api并未声明会抛出异常,则其在运行时有无可能抛出runtime异常,你遇到过吗?诺有的话会导致什么问题?如何解决?
27.简要解释一下activity、 intent 、intent filter、service、Broadcase、BroadcaseReceiver

一个activity呈现了一个用户可以操作的可视化用户界面
一个service不包含可见的用户界面,而是在后台无限地运行
可以连接到一个正在运行的服务中,连接后,可以通过服务中暴露出来的借口与其进行通信
一个broadcast receiver是一个接收广播消息并作出回应的component,broadcast receiver没有界面
intent:content provider在接收到ContentResolver的请求时被激活。
activity, service和broadcast receiver是被称为intents的异步消息激活的。
一个intent是一个Intent对象,它保存了消息的内容。对于activity和service来说,它指定了请求的操作名称和待操作数据的URI
Intent对象可以显式的指定一个目标component。如果这样的话,android会找到这个component(基于 manifest文件中的声明)并激活它。但如果一个目标不是显式指定的,android必须找到响应intent的最佳component。
它是通过将Intent对象和目标的intent filter相比较来完成这一工作的。一个component的intent filter告诉android该component能处理的intent。intent filter也是在manifest文件中声明的。

28.IntentService有何优点?

IntentService 的好处
* Acitivity的进程,当处理Intent的时候,会产生一个对应的Service
* Android的进程处理器现在会尽可能的不kill掉你
* 非常容易使用

29.横竖屏切换时候activity的生命周期?

  1. 不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次
  2. 设置Activity的android:configChanges=”orientation”时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次
  3. 设置Activity的android:configChanges=”orientation|keyboardHidden”时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法

30.如何将SQLite数据库(dictionary.db文件)与apk文件一起发布?

可以将dictionary.db文件复制到Eclipse Android工程中的res aw目录中。所有在res aw目录中的文件不会被压缩,这样可以直接提取该目录中的文件。可以将dictionary.db文件复制到res aw目录中

31.如何将打开res aw目录中的数据库文件?

在Android中不能直接打开res aw目录中的数据库文件,而需要在程序第一次启动时将该文件复制到手机内存或SD卡的某个目录中,然后再打开该数据库文件。复制的基本方法是使用getResources().openRawResource方法获得res aw目录中资源的 InputStream对象,然后将该InputStream对象中的数据写入其他的目录中相应文件中。在Android SDK中可以使用SQLiteDatabase.openOrCreateDatabase方法来打开任意目录中的SQLite数据库文件。

32.Android引入广播机制的用意?

  1. 从MVC的角度考虑(应用程序内) 其实回答这个问题的时候还可以这样问,android为什么要有那4大组件,现在的移动开发模型基本上也是照搬的web那一套MVC架构,只不过 是改了点嫁妆而已。android的四大组件本质上就是为了实现移动或者说嵌入式设备上的MVC架构,它们之间有时候是一种相互依存的关系,有时候又是一 种补充关系,引入广播机制可以方便几大组件的信息和数据交互。
  2. 程序间互通消息(例如在自己的应用程序内监听系统来电)
  3. 效率上(参考UDP的广播协议在局域网的方便性)
  4. 设计模式上(反转控制的一种应用,类似监听者模式) 转自:http://www.cnmsdn.com/html/201101/1295431222ID9251.html

33.android 的优势与不足

Android平台手机 5大优势:
1. 开放性
在优势方面,Android平台首先就是其开发性,开发的平台允许任何移动终端厂商加入到Android联盟中来。显著的开放性可以使其拥有更多的开发者,随着用户和应用的日益丰富,一个崭新的平台也将很快走向成熟
开发性对于Android的发展而言,有利于积累人气,这里的人气包括消费者和厂商,而对于消费者来讲,随大的受益正是丰富的软件资源。开放的平台也会带来更大竞争,如此一来,消费者将可以用更低的价位购得心仪的手机。
2. 挣脱运营商的束缚
在 过去很长的一段时间,特别是在欧美地区,手机应用往往受到运营商制约,使用什么功能接入什么网络,几乎都受到运营商的控制。从去年iPhone 上市 ,用户可以更加方便地连接网络,运营商的制约减少。随着EDGE、HSDPA这些2G至3G移动网络的逐步过渡和提升,手机随意接入网络已不是运营商口中 的笑谈,当你可以通过手机IM软件方便地进行即时聊天时,再回想不久前天价的彩信和图铃下载业务,是不是像噩梦一样?
互联网巨头Google推动的Android终端天生就有网络特色,将让用户离互联网更近。
3. 丰富的硬件选择
这 一点还是与Android平台的开放性相关,由于Android的开放性,众多的厂商会推出千奇百怪,功能特色各具的多种产品。功能上的差异和特色,却不 会影响到数据同步、甚至软件的兼容,好比你从诺基亚 Symbian风格手机 一下改用苹果 iPhone ,同时还可将Symbian中优秀的软件带到iPhone上使用、联系人等资料更是可以方便地转移,是不是非常方便呢?
4. 不受任何限制的开发商
Android平台提供给第三方开发商一个十分宽泛、自由的环境,不会受到各种条条框框的阻扰,可想而知,会有多少新颖别致的软件会诞生。但也有其两面性,血腥、暴力、情色方面的程序和游戏如可控制正是留给Android难题之一。
5. 无缝结合的Google应用
如今叱诧互联网的Google已经走过10年度历史,从搜索巨人到全面的互联网渗透,Google服务如地图、邮件、搜索等已经成为连接用户和互联网的重要纽带,而Android平台手机将无缝结合这些优秀的Google服务。
再说Android的5大不足:
1. 安全和隐私
由于手机 与互联网的紧密联系,个人隐私很难得到保守。除了上网过程中经意或不经意留下的个人足迹,Google这个巨人也时时站在你的身后,洞穿一切,因此,互联网的深入将会带来新一轮的隐私危机。
2. 首先开卖Android手机的不是最大运营商
众 所周知,T-Mobile在23日,于美国纽约发布 了Android首款手机G1。但是在北美市场,最大的两家运营商乃AT&T和Verizon,而目前所知取得Android手机销售权的仅有 T-Mobile和Sprint,其中T-Mobile的3G网络相对于其他三家也要逊色不少,因此,用户可以买账购买G1,能否体验到最佳的3G网络服 务则要另当别论了!
3. 运营商仍然能够影响到Android手机
在国内市场,不少用户对购得移动定制机不满,感觉所购的手机被人涂画了广告一般。这样的情况在国外市场同样出现。Android手机的另一发售运营商Sprint就将在其机型中内置其手机商店程序。
4. 同类机型用户减少
在 不少手机论坛都会有针对某一型号的子论坛,对一款手机的使用心得交流,并分享软件资源。而对于Android平台手机,由于厂商丰富,产品类型多样,这样 使用同一款机型的用户越来越少,缺少统一机型的程序强化。举个稍显不当的例子,现在山寨机泛滥,品种各异,就很少有专门针对某个型号山寨机的讨论和群组, 除了哪些功能异常抢眼、颇受追捧的机型以外。
5. 过分依赖开发商缺少标准配置
在 使用PC端的Windows Xp系统的时候,都会内置微软Windows Media Player这样一个浏览器程序,用户可以选择更多样的播放器,如Realplay或暴风影音等。但入手开始使用默认的程序同样可以应付多样的需要。在 Android平台中,由于其开放性,软件更多依赖第三方厂商,比如Android系统的SDK中就没有内置音乐 播放器,全部依赖第三方开发,缺少了产品的统一性。

34.android 中有哪几种解析xml的类?官方推荐哪种?以及它们的原理和区别。

XML解析主要有三种方式,SAX、DOM、PULL。常规在PC上开发我们使用Dom相对轻松些,但一些性能敏感的数据库或手机上还是主要采用SAX方 式,SAX读取是单向的,优点:不占内存空间、解析属性方便,但缺点就是对于套嵌多个分支来说处理不是很方便。而DOM方式会把整个XML文件加载到内存 中去,这里Android开发网提醒大家该方法在查找方面可以和XPath很好的结合如果数据量不是很大推荐使用,而PULL常常用在J2ME对于节点处 理比较好,类似SAX方式,同样很节省内存,在J2ME中我们经常使用的KXML库来解析。
详细情况请参考 http://blog.csdn.net/Android_Tutor/archive/2010/09/17/5890835.aspx

http://www.linuxidc.com/Linux/2010-11/29768.htm

http://littlefermat.blog.163.com/blog/static/59771167200981853037951/

35.DDMS和TraceView的区别?

DDMS是一个程序执行查看器,在里面可以看见线程和堆栈等信息,TraceView是程序性能分析器

36.Activity被回收了怎么办?

只有另启用了

37.java中如何引用本地语言

可以用JNI接口

38.谈谈Android的IPC机制

IPC是内部进程通信的简称, 是共享”命名管道”的资源。Android中的IPC机制是为了让Activity和Service之间可以随时的进行交互,故在Android中该机制,只适用于Activity和Service之间的通信,类似于远程方法调用,类似于C/S模式的访问。通过定义AIDL接口文件来定义IPC接口。Servier端实现IPC接口,Client端调用IPC接口本地代理。

39.NDK是什么

NDK是一些列工具的集合,
NDK提供了一系列的工具,帮助开发者迅速的开发C/C++的动态库,并能自动将so和java 应用打成apk包。
NDK集成了交叉编译器,并提供了相应的mk文件和隔离cpu、平台等的差异,开发人员只需简单的修改mk文件就可以创建出so

40.描述一下android的系统架构

android系统架构分从下往上为linux 内核层、运行库、应用程序框架层、和应用程序层
linuxkernel:负责硬件的驱动程序、网络、电源、系统安全以及内存管理等功能。

libraries和 androidruntime:libraries:即c/c++函数库部分,大多数都是开放源代码的函数库,例如webkit,该函数库负责 android网页浏览器的运行,例如标准的c函数库libc、openssl、sqlite等,当然也包括支持游戏开发2dsgl和 3dopengles,在多媒体方面有mediaframework框架来支持各种影音和图形文件的播放与显示,例如mpeg4、h.264、mp3、 aac、amr、jpg和png等众多的多媒体文件格式。android的runtime负责解释和执行生成的dalvik格式的字节码。

applicationframework(应用软件架构),java应用程序开发人员主要是使用该层封装好的api进行快速开发。

applications:该层是java的应用程序层,android内置的googlemaps、e-mail、即时通信工具、浏览器、mp3播放 器等处于该层,java开发人员开发的程序也处于该层,而且和内置的应用程序具有平等的位置,可以调用内置的应用程序,也可以替换内置的应用程序。

上面的四个层次,下层为上层服务,上层需要下层的支持,调用下层的服务,这种严格分层的方式带来的极大的稳定性、灵活性和可扩展性,使得不同层的开发人员可以按照规范专心特定层的开发。

android应用程序使用框架的api并在框架下运行,这就带来了程序开发的高度一致性,另一方面也告诉我们,要想写出优质高效的程序就必须对整个 applicationframework进行非常深入的理解。精通applicationframework,你就可以真正的理解android的设计 和运行机制,也就更能够驾驭整个应用层的开发。