Andorid学习笔记(草稿)


 刚刚接触Android开发时,Activiy、View、ViewGroup、Layout、Intent等等名称全部爆发,一时无从下手。


一、关于名词

  1. Activity:Activity即可视为一个窗口。在任何时候,一个应用程序只能有一个活动的Activity,此情景与模式对话框类似。
  2. View:界面的基本元素,包括图片显示框(ImageView)、文本显示框(TextView)、按钮(Button)等元素。
  3. ViewGroup:界面元素的组合,是所有Layout类的基类。
  4. Layout:界面的布置方案。界面上所有的元素均对应在一个XML文件中,保存在res/layout/目录下。该文件指明各个界面元素(View)是按照什么方式布置在界面上的什么位置的。具体有线性布局(Linear Layout)、相对布局(Relative Layout)、表格布局(Table Layout)、网格视图(Grid View)、标签布局(Tab Layout)、列表视图(List View)、绝对布局(AbsoluteLayout)等。
  5. Intent:用以在Activity之间传递数据(暂时的了解)。一个程序只能有一个活动的Activity,在一个Activity里面启动另一个Activity的方法即是使用Intent来完成。


二、关于Activity

一个Activity要与一个Layout对应。Acitivity里面包含界面逻辑,而Layout包含界面元素的位置。


建立DemoAcitivity的过程如下:

1. 在res/layout/下创建一个Layout,命名为demo_layout.xml,使用任何一种合适的布局,将界面元素按照需要布置在界面中。

2. 创建DemoActivity的代码,继承自Activity类。重写onCreate方法,在onCreate方法中调用

setContentView(R.layout.demo_layout); 

这样,DemoActivity启动的时候,会查找并使用demo_layout来作为其显示的界面。


在多个界面中切换

为了在多个界面中切换程序,可以使用两种方法:

1. 使用Intent切换不同的Activity;

2. 使用setContentView切换不同的Layout;

二者各有好处。其中,

使用Intent切换Activity,各界面的逻辑包含在不同的类代码中,结构清晰。其缺点是Activity切换动作较大,消耗较多。同时,如果需要在不同的窗口之间传递数据,需要使用Intent来完成。

使用setContentView切换Layout,所有的逻辑以及数据均保存在同一个Activity类中,不需要进行数据传递。缺点是不同窗口的逻辑代码可能会混杂在一起。

切换方法1 : 使用Intent切换Activity

首先在layout里建2个xml文件,分别对应两个不同的Activity的界面。每个界面上均有一个按钮,通过点击切换到另一个Activity。

public class Activity01 extends Activity {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
      
        /* 设置显示layout01.xml布局 */
        setContentView(R.layout.layout01);

       /* findViewById(R.id.button1)取得布局layout01.xml中的button1 */
       Button button = (Button) findViewById(R.id.button1);
  
       /* 监听button的事件信息 */
       button.setOnClickListener(new Button.OnClickListener() {
            public void onClick(View v) {
               /* 新建一个Intent对象,并指定要启动的类 */
               Intent intent = new Intent(Activity01.this, Activity02.class);
               /* 启动一个新的Activity */
               startActivity(intent);
               /* 关闭当前的Activity */
               Activity01.this.finish();
           }
       });
    }
}
另一个类的实现代码与此类似,只是把Activity01与Activity02相互交换。

需要注意的是,这两个Activity都必须在AndroidManifest.xml文件中声明,并指定一个默认的启动类。典型的声明如下:

...

<application>
    <activity android:name=".Activity01">
        <intent-filter>
             <action android:name="android.intent.aciton.MAIN" />
             <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity android:name=".Activity02"></activity>
</application>

...


如果要传递数据,可以使用Intent的putExtra来添加信息,然后再启动目标Activity。例如,要传递一个名字为“greeting”的字符串“How do you do”,使用方法是:

intent.putExtra("greeting","How do you do");

而在被启动的Activity中,使用Intent的getExtra来得到消息,如:
Intent intent = getIntent();
String msg = intent.getStringExtra("greeting");
传递其它的信息类似,只是get的时候需要知道信息的类型,如getBooleanExtra等等。


切换方法2:使用setContentView切换Layout

一个Activity可以对应多个Layout,可以根据需要在不同的时间显示不同的Layout来达到切换界面的目的。这样,不需要多个Activity就可以显示不同的界面,也不再需要在Activity间传送数据,变量可以直接引用。

如果使用setContentView(int layoutResID)方法切换Layout,在切换后再切换回,程序相当于重新显示一个界面,并非是把原来的界面隐藏后再显示。我们可以先用LayoutInflater把布局xml文件引入成View对象,再通过setContentView(View view)方法来切换视图。因为所有对View的修改都保存在View对象里,所以,当切换回原来的布局时,就可以直接显示原来修改后的样子。

例如有如下的两个Layout:

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

    <TextView  android:id="@+id/tv1"
        android:layout_width="fill_parent" android:layout_height="wrap_content"
        android:text="Some Message" />

    <Button android:id="@+id/b1"
        android:layout_width="fill_parent" android:layout_height="wrap_content"
        android:text="切换到layout2"/>

    <Button android:id="@+id/b3"
        android:layout_width="fill_parent" android:layout_height="wrap_content"
        android:text="修改tv1"/>
</LinearLayout> 

<?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:id="@+id/b2"
        android:layout_width="fill_parent" android:layout_height="wrap_content"
        android:text="切换到layout1"/>
</LinearLayout> 

在一个Activity中使用这两个Layout的方法如下:

import android.app.Activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class Main extends Activity {
    /** Called when the activity is first created. */
    TextView tv1, tv2;
    Button b1, b2,b3;
    View layout1, layout2;
    boolean view2Load = false;//main2是否载入过的flag
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        LayoutInflater inflater = LayoutInflater.from(this);
        layout1 = inflater.inflate(R.layout.layout1, null);
        layout2 = inflater.inflate(R.layout.layout2, null);
 
        setView1();
        
        tv1 = (TextView) findViewById(R.id.tv1);
        b1 = (Button) findViewById(R.id.b1);
        b3 = (Button) findViewById(R.id.b3);
        b3.setOnClickListener(l3);
        b1.setOnClickListener(l1);
        //控件及监听器只需一次查找绑定,切换view不影响
    }

    private void setView1() {
        setContentView(layout1);
    }

    private void setView2() {
        setContentView(layout2);
        setView2Btn();
    }
   
    private void setView2Btn(){
        if(!view2Load){   //如果首次显示layout2,查找控件并绑定监听器
             b2 = (Button) findViewById(R.id.b2);
             b2.setOnClickListener(l2);
             view2Load=true;//flag设为true
        }
    }

    OnClickListener l1 = new OnClickListener() {
         @Override
         public void onClick(View v) {
             setView2();
         }
    };

    OnClickListener l2 = new OnClickListener() {
         @Override
         public void onClick(View v) {
             setView1();
         }
    };

    OnClickListener l3 = new OnClickListener() {
         @Override
         public void onClick(View v) {
              tv1.setText("Another Message");
              //修改tv1的值,切换到layout2后再切换回来到layout1,可以发现tv1的值被保存了
         }
    };
} 


Tips: android:layout_weight="1"可以在LinearLayout中表示某元素的权重,默认都为”0“。在默认情况下,如果屏幕排不下所有的元素,则屏幕外面的将会丢失。设置了权重值之后,系统将自动为各个元素分配其权重值对应的空间,数值大小表示其权重大小。

SplashForm的效果

有这两种切换方式,想要做到自动切换,达到SplashForm的效果也很简单了。以第一种切换方式为例,将Activity01画成SplashForm,AndroidManiefest.xml文件保证了Activity01是最先显示出来的。接着,将Activity01的实现代码改成:

public class Activity01 extends Activity {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
      
        /* 设置显示layout01.xml布局 */
        setContentView(R.layout.layout01);

        final int nWelcomeScreenDisplay = 3000;  //默认3秒
        new Handler().postDelayed(new Runnable() {  
            @Override  
            public void run() {  
                Intent intent = new Intent(Activity01.this, Activity02.class);  
                startActivity(intent);  
                Activity01.this.finish();  
            }  
        }, nWelcomeScreenDisplay);  
    }
}

即可在3秒之后,自动切换到Activity02显示。

使用切换Layout的方式来完成SplashForm与此类似,只是将切换Activity的代码改成切换Layout的代码即可。

三、关于ListView和ListAdapter

ListView中将要显示的数据由ListAdapter来提供。ListAdapter分为三种:使用ArrayAdapter显示一个数组形式的数据;SimpleAdapter能定义各种各样的布局出来,可以放上ImageView(图片)、Button(按钮)、CheckBox(复选框)等等;SimpleCursorAdapter用以显示数据库的内容。

1. ArrayAdapter最简单,只能显示一行文字,示例:

public class Activity01 extends Activity {
    private ListView listView;
    private String[] data = {"a","b","c","d"};

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
      
        listView = new ListView(this);
        listView.setAdapter(new ArrayAdapter<String>(this, R.layout.list_item,getData()));
        
        setContentView(listView);        
    }
}

需要注意的是,在使用ListView时,不管用哪种Adapter,res/layout/下的list_item.xml文件都只需要指明将要显示的ListView中一个元素的布局格式。比如上例,list_item.xml文件只需要给出每一个字符串该怎么显示,而不用管整个ListView该如何布局。

<?xml version="1.0" encoding="utf-8"?>
<TextView  xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent" android:layout_height="wrap_content"
        android:textSize="16sp" />

ListView在开始绘制的时候,系统首先调用getCount()函数,根据其返回值得到ListView的长度。然后根据这个长度,调用getView()得到每一行的元素,使用list_item.xml里面设置的布局方式逐一绘制每一行。如果getCount()返回值是0的话,列表将不显示。

2. SimpleCursorAdapter中Cursor的意思是游标,与MySQL数据库编程中的游标相同。顾名思义,SimpleCursorAdapter用以将数据库中游标处的数据显示在ListView中。

比如,要开发一个应用程序,以列表的形式显示通讯录数据库中的所有人的姓名。首先定义如下的布局文件simple_cursor_list_item.xml,指明每一个姓名的显示方式:

<?xml version="1.0" encoding="utf-8"?>
<TextView  xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/name"
        android:layout_width="fill_parent" android:layout_height="wrap_content"
        android:textSize="16sp" />

创建SimpleCursorAdapter来获取数据,并显示在ListView中:

public class Activity01 extends Activity {
    private ListView listView;
  
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
      
        listView = new ListView(this);
        
        Cursor cursor = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
        startManagingCursor(cursor);
             
        ListAdapter listAdapter = new SimpleCursorAdapter(this, R.layout.simple_cursor_list_item, cursor,
                    new String[]{ContactsContract.Contacts.DISPLAY_NAME},
                    new int[]{R.id.name});
             
        listView.setAdapter(listAdapter);
        setContentView(listView);        
    }
}

如上例,创建一个Cursor对象,将其指向系统的通讯录数据库。然后调用startManagingCursor,使用Activity来管理该Cursor。创建SimpleCursorAdapter时,前三个参数与ArrayAdapter相同,第四个参数是数据库中将要显示的列的名称所构成的数组,第五个参数指明数据将映射到哪个组件上。第四、第五个参数的长度需要与布局文件中每一行的元素的个数相同。

该例子中还有个要注意的,因为需要访问通讯录,必须在AndroidManifest.xml文件中对该应用进行授权:

<activity android:name=".Activity01">
  ...
      <uses-permission android:name="android.permission.READ_CONTACTS" /> 
  ...
</activity>

3. SimpleAdapter

在SimpleAdapter中,列表的每一行可以显示多个元素。使用SimpleAdapter的数据用一般都是HashMap构成的List,List的每个元素对应ListView的每一行。HashMap的每个键值数据映射到布局文件中对应id的组件上。

SimpleAdapter构造函数的参数依次是:this、数据列表、布局文件ID,HashMap的键值数组、布局文件中对应组件的ID数组。以一个图片加一个字符串为例:

布局文件simple_list_item.xml如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="horizontal" android:layout_width="fill_parent"
        android:layout_height="fill_parent">
        <ImageView android:id="@+id/img"
            android:layout_width="wrap_content" android:layout_height="wrap_content"
            android:layout_margin="5px"/>
        <TextView android:id="@+id/description"
            android:layout_width="fill_parent" android:layout_height="wrap_content"
            android:textSize="16sp" />
</LinearLayout>
该布局文件表示,每一行包含一张图片和一段文字,二者以水平方向线性排列。

对于的Activity如下:

public class Activity01 extends Activity {
    private ListView listView;
  
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
      
        listView = new ListView(this);
                     
        ListAdapter listAdapter = new SimpleAdapter(this, getData(), R.layout.simple_list_item,
                    new String[]{"img","description"},
                    new int[]{R.id.img, R.id.description});
             
        listView.setAdapter(listAdapter);
        setContentView(listView);        
    }
    private List< Map<String, Object> > getData() {
        List< Map<String, Object> > list = new ArrayList< Map<String, Object> >();
        
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("img", R.drawable.img01);
        map.put("description", R.string.des01);
        list.add(map);
        
        map = new HashMap<String, Object>();
        map.put("img", R.drawable.img02);
        map.put("description", R.string.des02);
        list.add(map);
        
        return list;
    }
}

同时,在res/drawable/下放入将要显示的图片,img01.png和img02.png,在res/values/string.xml中,加入将要显示的文字:

<resources>
 ...
     <string name="des01">Description 01</string>
     <string name="des02">Description 02</string>
 ...
</resources>

4.比SimpleAdapter稍微复杂一点的Adapter

如果需要在每一行加上一个可以相应的按钮,则稍微复杂一点。此时,需要自己写一个Adapter类,继承自BaseAdapter。以一个图片一个按钮为例:

布局文件complex_list_item.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="horizontal" android:layout_width="fill_parent"
        android:layout_height="fill_parent">
        <ImageView android:id="@+id/img"
            android:layout_width="wrap_content" android:layout_height="wrap_content"
            android:layout_margin="5px"/>
        <Button android:id="@+id/btn"
            android:layout_width="fill_parent" android:layout_height="wrap_content"
            android:text="@string/btn_text" />
</LinearLayout>

对应的代码如下:

public class Activity01 extends Activity {
    private List<Map<String, Object>> mData;
    private ListView listView;
       
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        listView = new ListView(this);
        mData = getData();
	ComplexAdapter adapter = new ComplexAdapter(this);
	listView.setListAdapter(adapter);

        setContentView(listView); 

    } 
    private List< Map<String, Object> > getData() {
        List< Map<String, Object> > list = new ArrayList< Map<String, Object> >();
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("img", R.drawable.img01);
        list.add(map);
        map = new HashMap<String, Object>();
        map.put("img", R.drawable.img02);
        list.add(map);
        return list; 
    } 
    public final class ViewHolder{
        public ImageView img;
        public Button btn; 
    } 

    public class ComplexAdapter extends BaseAdapter{
        private LayoutInflater mInflater;
        public ComplexAdapter(Context context){ 
            this.mInflater = LayoutInflater.from(context);
        }

        @Override
        public int getCount() { return mData.size();}

        @Override
        public Object getItem(int arg0) { return null;}
 
        @Override
        public long getItemId(int arg0) { return 0;}

        @Override
        public View getView(int position, View convertView, ViewGroup parent) { 
             ViewHolder holder = null; 
             if (convertView == null) { 
                  holder=new ViewHolder(); 
                  convertView = mInflater.inflate(R.layout.complex_list_item, null);
                  holder.img = (ImageView)convertView.findViewById(R.id.img);
                  holder.btn = (Button)convertView.findViewById(R.id.btn);
 
                  convertView.setTag(holder); 
             }else {
                  holder = (ViewHolder)convertView.getTag(); 
             } 
             holder.img.setBackgroundResource((Integer)mData.get(position).get("img")); 
             holder.btn.setOnClickListener(new View.OnClickListener() { 
                  @Override
                  public void onClick(View v) { 
                        //On Click Logic...
                  } }); 
             return convertView;
        } 
    }
}


四、关于GridView和ListAdapter

GridView即网格布局,与ListView一样,使用ListAdapter来提供数据。以GridView结合SimpleAdapter为例:

首先,在grid_layout.xml中定义整个GridView的布局:

<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/grid" android:layout_width="wrap_content"
    android:layout_height="wrap_content" android:verticalSpacing="10dp"
    android:horizontalSpacing="10dp" android:numColumns="auto_fit"
    android:columnWidth="90dp" android:stretchMode="columnWidth">
</GridView>
在grid_item.xml中定义GridView中各个元素的布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="fill_parent" android:layout_width="fill_parent"
    android:orientation="vertical">
    <ImageView android:id="@+id/griditem_pic"
	android:layout_width="wrap_content" android:layout_height="wrap_content"
	android:layout_centerHorizontal="true" />
    <TextView android:id="@+id/griditem_title"
	android:layout_width="wrap_content" android:layout_height="wrap_content"
	android:layout_centerHorizontal="true" />
</LinearLayout>

如grid_item.xml所示,网格中的每一个元素包括一张图片和一段文件,二者纵向排列。

Activity的代码如下:

public class GridActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
	setContentView(R.layout.grid_layout);
	GridView gridView = (GridView) findViewById(R.id.grid_layout);

	List< Map<String, Object> > contents = new ArrayList< Map<String, Object> >();
	for (int i = 0; i < 10; i++) {
            Map<String, Object> map = new HashMap<String, Object>();
	    map.put("img", R.drawable.img);
	    map.put("title", "Image Title");
	    contents.add(map);
	}
	
        SimpleAdapter adapter = new SimpleAdapter(this, contents, R.layout.grid_item,
				       new String[] { "img", "title" }, 
                                       new int[] { R.id.griditem_pic,R.id.griditem_title,});
        gridView.setAdapter(adapter);
    }
}

最后,在res/drawable/下放入将要显示的图片,img.png。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值