第二章 布局技巧與列表

1 布局與優(yōu)化

1.1 五大布局

  • LinearLayout:線性布局
  • orientation:vertical:垂直的改化,horizontal:水平的
  • weight:設(shè)置比重時(shí),layout_width="0"枉昏。weightSum總比重陈肛。例如:微信底部四個(gè)tab平分寬帶,可以使其weight 1:1:1:1
  • RelativeLayout:相對布局
  • xmlns:xml的命名空間
  • layout_alignParentRight:與布局容器的右邊對齊
  • layout_alignParentBottom:位于父容器的底部
  • layout_alignLeft:與給出id組件的左邊對齊
  • layout_above/toRightOf:給出id組件的上方/右邊
  • layout_marginTop/toRightOf:外邊距
  • layout_paddingRight:內(nèi)邊距
  • FrameLayout:幀布局凶掰,一層一層疊加起來
  • AbsoluteLayout:絕對布局
  • TableLayout:表格布局
  • TableRow

1.2 布局優(yōu)化

  • 減少布局層次的重要性層次過多會(huì)影響到性能
  • 官方建議布局層次--最多10層燥爷,所以要減少層次,刪除無用布局
  • 學(xué)會(huì)使用相對布局懦窘。布局結(jié)構(gòu)要清晰前翎,選擇合適的布局
  • 組合控件
  • 一些有用的屬性
  • 布局如何引用相同的部分,可以提取出來然后</include>重用布局文件
  • <merge/>減少視圖層級(jí)
  • <ViewStub/>需要是才加載畅涂,介紹ViewStub代碼 ,介紹ViewStub文字港华,兩篇結(jié)合來看。ViewStub指向的布局文件在多數(shù)情況下并不會(huì)被顯示出來午衰,只會(huì)在某種特殊的情況下對ViewStub進(jìn)行inflate操作立宜,而且這種操作只能進(jìn)行一次,此時(shí)會(huì)將ViewStub替換掉臊岸,變成顯示所指向的布局文件橙数。,一旦替換后帅戒,此時(shí)原來的布局文件中就沒有ViewStub控件了灯帮,這就好像ViewStub只是為其所指向的布局占了一個(gè)位子,需要時(shí)才顯示
  • 小技巧
  • 不要嵌套多個(gè)使用layout_weight屬性的LinearLayout
  • Android lint :刪除無用的資源逻住,布局钟哥,類,引用
  • HierarchyViewer:分析性能及其優(yōu)化

2 無比重要的ListView

這里寫圖片描述
  • AdapterView是一個(gè)容器瞎访,把很多的列表項(xiàng)以合適的形式顯示出來腻贰,而列表項(xiàng)的內(nèi)容和格式可以用Adapter指定,調(diào)用AdapterView的setAdapter(Adapter)方法設(shè)置Adapter即可扒秸。

2.1四種設(shè)置Adapter的方法:(以ListView為例子)

  • 使用ArrayAdapter設(shè)置
    1. 告訴大家我要?jiǎng)?chuàng)建列表項(xiàng)了播演,初始化這個(gè)控件
    2. 定義了一個(gè)數(shù)組冀瓦,該數(shù)組是為多個(gè)列表項(xiàng)提供了數(shù)據(jù)
    3. 創(chuàng)建ArrayAdapter(Context,textViewResource,數(shù)組或者List)對象。其中Context代表訪問應(yīng)用的接口写烤,一般是this咕幻。textViewResource代表一個(gè)資源的ID,該資源分ID是指定了每個(gè)列表項(xiàng)的組件顶霞,等于為每個(gè)列表項(xiàng)指定了格式。后面的數(shù)據(jù)就按照組件的格式傳入锣吼。
    4. 最后為該ListView設(shè)置Adapter
public class ArrayAdapterActivity extends Activity{
    ListView mListView1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_arrayadapter);
        //1
        mListView1 = (ListView) findViewById(R.id.listview1);
        //2
        String[] arr1 = {"王俊凱" ,"王源","易烊千璽"};
        //3
        ArrayAdapter<String> adapter1 =
                new ArrayAdapter<String>(this,R.layout.array_item,arr1);
        //4
        mListView1.setAdapter(adapter1);    
    }
}

  • 讓Activity繼承ListActivity來實(shí)現(xiàn)
  1. 創(chuàng)建ArrayAdapter對象之后选浑,直接使用setListActivity(adapter)設(shè)置該窗口顯示列表
public class MainActivity extends ListActivity{
    @override
    public void onCreate(Bundle saveIdnstanceState){
        supert.onCreate(savedInstanceState);
        String[] arr = {"劉詩詩", "趙麗穎", "楊冪"};
        ArrayAdapter<String> adapter1 = new ArrayAdapter<String>(this, R.layout.item, arr);
        setListAdapter(adapter);
         
    }
}
  • 使用SimpleAdapter
  1. 前面都是創(chuàng)建提供列表內(nèi)容的數(shù)組
  2. 創(chuàng)建一個(gè)List集合,集合元素是Map玄叠,把前面的內(nèi)容數(shù)組封裝成一個(gè)List集合
  3. 創(chuàng)建SimpleAdapter對象古徒。后面有5個(gè)參數(shù),第一個(gè)是Context读恃。第二個(gè)是一個(gè)元素是Map的List集合隧膘,每個(gè)Map對象生成一個(gè)列表項(xiàng)。第三個(gè)參數(shù)是指定界面布局的ID寺惫。第四個(gè)是一個(gè)String[]對象的參數(shù)疹吃,決定提取Map中那些key對應(yīng)的value來生成列表項(xiàng)。第五個(gè)參數(shù)是對應(yīng)于value填充的組件西雀,該組件是來源與第三個(gè)參數(shù)的布局萨驶。是int[]類型的參數(shù)
  4. 設(shè)置Adapter
public class MainActivity extends AppCompatActivity {
    //1
    private  String[] names = new String[]{"lisa" , "linda" , "july" , "anna"};

    private String[] describe = new String[]{"a cute child" , "a beautiful girl" , "a smart student" , "a handsome boy"};

    private int[] imageId = new int[]{R.drawable.libai,R.drawable.nongyu,R.drawable.qingzhao,R.drawable.tiger};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //2
        List<Map<String,Object>> listItems = new ArrayList<Map<String, Object>>();

        for (int i = 0 ; i < names.length ; i++){
           Map<String , Object> listItem = new HashMap<String, Object>();
            listItem.put("header" ,imageId[i]);
            listItem.put("name" , names[i]);
            listItem.put("describe" , describe[i]);
            listItems.add(listItem);
        }
        //3
        SimpleAdapter simpleAdapter = new SimpleAdapter(this ,
                listItems ,R.layout.simple_item ,
                new String[]{"header","name","describe"} ,
                new int[]{R.id.header,R.id.name,R.id.desc});

        ListView listView =(ListView) findViewById(R.id.mylist);
        //4
        listView.setAdapter(simpleAdapter);

        Intent intent = getIntent();
        if (intent != null) {
            String string = intent.getStringExtra(SplashActivity.TITLE);
            setTitle(string);
        }
    }
}
  • 擴(kuò)展BaseAdapter實(shí)現(xiàn) ,需要重寫4個(gè)方法
  1. int getCount():返回值控制Adapter會(huì)有多少個(gè)列表項(xiàng)
  2. Object getItem(int i):返回第i處的列表項(xiàng)的內(nèi)容
  3. getItemId(int i):返回第i除列表項(xiàng)的id
  4. View getView(int i, View view, ViewGroup viewGroup):返回第i除列表項(xiàng)的組件
 BaseAdapter baseAdapter = new BaseAdapter() {
            @Override
            public int getCount() {
                //指定40個(gè)選項(xiàng)
                return 40;
            }

            @Override
            public Object getItem(int i) {
                return null;
            }

            @Override
            public long getItemId(int i) {
                return i;
            }

            @Override
            public View getView(int i, View view, ViewGroup viewGroup) {
                LinearLayout linearLayout = new LinearLayout(MainActivity.this);
                linearLayout.setOrientation(LinearLayout.VERTICAL);
                ImageView imageView = new ImageView(MainActivity.this);
                imageView.setImageResource(R.mipmap.ic_launcher);
                TextView text = new TextView(MainActivity.this);
                text.setText("this is" + i + "listview");
                text.setTextSize(20);
                linearLayout.addView(imageView);
                linearLayout.addView(text);
                return linearLayout;
            }
        };

2.2 優(yōu)化

  • 不必每次都要加載視圖艇肴,只需要第一次的時(shí)候加載腔呜,所以可以加個(gè)判斷
@Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        ViewHolder viewHolder;
        //優(yōu)化
        if(view == null){
            view = mLayoutInflater.inflate(R.layout.activity_items,null);
            viewHolder = new ViewHolder();
            //獲取控件
            viewHolder.phone_name = (TextView) view.findViewById(R.id.item_name);
            viewHolder.phone_age = (TextView) view.findViewById(R.id.item_age);
            viewHolder.phone_image = (ImageView) view.findViewById(R.id.item_image);
            view.setTag(viewHolder);
        }else {
            viewHolder = (ViewHolder) view.getTag();
        }
        //數(shù)據(jù)綁定,mInfoList是一個(gè)類型為用戶的List,該用戶有Age和Name屬性
        viewHolder.phone_name.setText(mInfoList.get(i).getmName());
        viewHolder.phone_age.setText(String.valueOf(mInfoList.get(i).getmAge()));
        viewHolder.phone_image.setImageResource(R.mipmap.ic_launcher);
        return view;
    }
  • 設(shè)置類來保存所加載視圖的控件
class ViewHolder{
    TextView phone_name;
    TextView phone_age ;
    ImageView phone_image ;
}
  • 所以只有第一次加載的時(shí)候,會(huì)去加載視圖獲取控件再悼,當(dāng)前視圖不為空時(shí)核畴,只會(huì)去獲取視圖里控件,節(jié)約內(nèi)存冲九。

2.3 item不同怎么辦谤草,getItemViewType()

2.4 風(fēng)格不同的分割線

  • ListView的 android:divider屬性來設(shè)置娘侍,所以可以用自定義的Drawable來設(shè)置分割線的風(fēng)格

3 GridView和ScrollView

3.1 GridView與ListView的相似之處

  • 需要設(shè)置Adapter
  • 它們倆的parent都實(shí)現(xiàn)了AdapterView

3.2 GridView的常用實(shí)現(xiàn)

  • 常用屬性:
  • android:numColums:設(shè)置列數(shù)
  • android:horizontalSpacing:設(shè)置各元素之間的水平間距
  • android:verticalSpacing:設(shè)置各元素之間的垂直間距
  • android:gravity:設(shè)置對齊方式
  • 使用了SimpleAdapter咖刃,ImageSwitcher是圖片切換器,在切換ImgeView時(shí)使用動(dòng)畫
  • activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center_horizontal">

    <GridView
        android:id="@+id/grid01"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:horizontalSpacing="2dp"
        android:verticalSpacing="2dp"
        android:numColumns="4"
        android:gravity="center"/>
    <ImageSwitcher
        android:id="@+id/switcher"
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:layout_gravity="center_horizontal"
        android:inAnimation="@android:anim/fade_in"
        android:outAnimation="@android:anim/fade_out"/>
</LinearLayout>

  • cell.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="50dp"
        android:layout_height="50dp"
        />

</LinearLayout>
  • java源代碼
package com.example.w.myapplication;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.ImageSwitcher;
import android.widget.ImageView;
import android.widget.SimpleAdapter;
import android.widget.Toast;
import android.widget.ViewSwitcher;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MainActivity extends AppCompatActivity {

    GridView gridView;
    ImageSwitcher imageSwitcher;

    int[] imageIds = new int[] {
            R.drawable.bomb5,R.drawable.bomb6,R.drawable.bomb7,R.drawable.bomb8,
            R.drawable.bomb9,R.drawable.bomb10,R.drawable.bomb11,R.drawable.bomb12,
            R.drawable.bomb13,R.drawable.bomb14,R.drawable.bomb15,R.drawable.bomb16,
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        gridView = (GridView)findViewById(R.id.grid01);

        //創(chuàng)建一個(gè)List對象憾筏,List對象的元素是Map
        List<Map<String,Object>> listItems = new ArrayList<Map<String, Object>>();
        for (int i = 0 ; i < imageIds.length ; i++){
            Map<String,Object> listItem = new HashMap<String, Object>();
            listItem.put("image" , imageIds[i]);
            listItems.add(listItem);
        }
        //為ImageSwitcher提供一個(gè)ViewFactory,由其生成View
        imageSwitcher = (ImageSwitcher)findViewById(R.id.switcher);
        imageSwitcher.setFactory(new ViewSwitcher.ViewFactory() {
            @Override
            public View makeView() {
                //創(chuàng)建ImageView對象
                ImageView imageView = new ImageView(MainActivity.this);
                imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
                imageView.setLayoutParams(new ImageSwitcher.LayoutParams(
                        ViewGroup.LayoutParams.WRAP_CONTENT,
                        ViewGroup.LayoutParams.WRAP_CONTENT));
                return imageView;
            }
        });
        SimpleAdapter simpleAdapter = new SimpleAdapter(this , listItems ,R.layout.cell
                ,new String[]{"image"},new int[]{R.id.imageView});

        gridView.setAdapter(simpleAdapter);

        //列表被單擊
        gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                imageSwitcher.setImageResource(imageIds[i]);
                Toast.makeText(MainActivity.this,"圖片" + i +"被點(diǎn)擊了" , Toast.LENGTH_LONG).show();
            }
        });

        //列表被選中
        gridView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
                imageSwitcher.setImageResource(imageIds[i]);
                Toast.makeText(MainActivity.this,"圖片" + i +"被選中了" , Toast.LENGTH_LONG).show();
            }

            @Override
            public void onNothingSelected(AdapterView<?> adapterView) {

            }
        });
    }
}

3.3 ScrollView

  • 最多只能包含一個(gè)組件嚎杨,或只支持垂直滾動(dòng),若需要水平滾動(dòng)氧腰,則可借助另一個(gè)滾動(dòng)視圖-HorizontalScrollView

你可看可不看枫浙,但我必須得看的Tips:

  1. ScrolView了解不是很多刨肃,需要進(jìn)一步去了解
  2. ListView很重要,和BaseAdapter搭配起來箩帚,天生一對
  3. 布局應(yīng)快要學(xué)完了真友,16.7.23
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市紧帕,隨后出現(xiàn)的幾起案子盔然,更是在濱河造成了極大的恐慌,老刑警劉巖是嗜,帶你破解...
    沈念sama閱讀 222,104評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件愈案,死亡現(xiàn)場離奇詭異,居然都是意外死亡鹅搪,警方通過查閱死者的電腦和手機(jī)站绪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來丽柿,“玉大人恢准,你說我怎么就攤上這事「μ猓” “怎么了馁筐?”我有些...
    開封第一講書人閱讀 168,697評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長坠非。 經(jīng)常有香客問我眯漩,道長,這世上最難降的妖魔是什么麻顶? 我笑而不...
    開封第一講書人閱讀 59,836評(píng)論 1 298
  • 正文 為了忘掉前任赦抖,我火速辦了婚禮,結(jié)果婚禮上辅肾,老公的妹妹穿的比我還像新娘队萤。我一直安慰自己,他們只是感情好矫钓,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評(píng)論 6 397
  • 文/花漫 我一把揭開白布要尔。 她就那樣靜靜地躺著,像睡著了一般新娜。 火紅的嫁衣襯著肌膚如雪赵辕。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,441評(píng)論 1 310
  • 那天概龄,我揣著相機(jī)與錄音还惠,去河邊找鬼。 笑死私杜,一個(gè)胖子當(dāng)著我的面吹牛蚕键,可吹牛的內(nèi)容都是我干的救欧。 我是一名探鬼主播,決...
    沈念sama閱讀 40,992評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼锣光,長吁一口氣:“原來是場噩夢啊……” “哼笆怠!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起誊爹,我...
    開封第一講書人閱讀 39,899評(píng)論 0 276
  • 序言:老撾萬榮一對情侶失蹤蹬刷,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后频丘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體箍铭,經(jīng)...
    沈念sama閱讀 46,457評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評(píng)論 3 341
  • 正文 我和宋清朗相戀三年椎镣,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片兽赁。...
    茶點(diǎn)故事閱讀 40,664評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡状答,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出刀崖,到底是詐尸還是另有隱情惊科,我是刑警寧澤,帶...
    沈念sama閱讀 36,346評(píng)論 5 350
  • 正文 年R本政府宣布亮钦,位于F島的核電站馆截,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏蜂莉。R本人自食惡果不足惜蜡娶,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評(píng)論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望映穗。 院中可真熱鬧窖张,春花似錦、人聲如沸蚁滋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽辕录。三九已至睦霎,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間走诞,已是汗流浹背副女。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蚣旱,地道東北人肮塞。 一個(gè)月前我還...
    沈念sama閱讀 49,081評(píng)論 3 377
  • 正文 我出身青樓襟齿,卻偏偏與公主長得像,于是被迫代替她去往敵國和親枕赵。 傳聞我的和親對象是個(gè)殘疾皇子猜欺,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容