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è)置
- 告訴大家我要?jiǎng)?chuàng)建列表項(xiàng)了播演,初始化這個(gè)控件
- 定義了一個(gè)數(shù)組冀瓦,該數(shù)組是為多個(gè)列表項(xiàng)提供了數(shù)據(jù)
- 創(chuàng)建
ArrayAdapter(Context,textViewResource,數(shù)組或者List)
對象。其中Context代表訪問應(yīng)用的接口写烤,一般是this咕幻。textViewResource代表一個(gè)資源的ID,該資源分ID是指定了每個(gè)列表項(xiàng)的組件顶霞,等于為每個(gè)列表項(xiàng)指定了格式。后面的數(shù)據(jù)就按照組件的格式傳入锣吼。 - 最后為該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)
- 創(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
- 前面都是創(chuàng)建提供列表內(nèi)容的數(shù)組
- 創(chuàng)建一個(gè)List集合,集合元素是Map玄叠,把前面的內(nèi)容數(shù)組封裝成一個(gè)List集合
- 創(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ù)
- 設(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è)方法
- int getCount():返回值控制Adapter會(huì)有多少個(gè)列表項(xiàng)
- Object getItem(int i):返回第i處的列表項(xiàng)的內(nèi)容
- getItemId(int i):返回第i除列表項(xiàng)的id
- 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()
- 推薦一篇寫的好而且我看的懂的博客Adapter的getViewTypeCount()和getItemViewType()
- 微信的聊天列表
- 聊天框使用.9圖,用getItemViewType()設(shè)置不同的ListView
- 小demo非正式仿聊天界面
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:
- ScrolView了解不是很多刨肃,需要進(jìn)一步去了解
- ListView很重要,和BaseAdapter搭配起來箩帚,天生一對
- 布局應(yīng)快要學(xué)完了真友,16.7.23