今天這篇文章,主要是為了快速搭建一個項目主體架構!
目前好多應用的主界面都是,底部幾個切換按鈕,點選不同的按鈕,切換不同的界面,先來幾張截圖,如下,
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIyVGduV2QvwVe0lmdhJ3ZvwFM38CXlZHbvN3cpR2Lc1TPB10QGtWUCpEMJ9CXsxWam9CXwADNvwVZ6l2c052bm9CXUJDT1wkNhVzLcRnbvZ2LcZXUYpVd1kmYr50MZV3YyI2cKJDT29GRjBjUIF2LcRHelR3LcJzLctmch1mclRXY39TM4QjMxkTN3EDMzITM1EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
這三張截圖,分别來自淘寶、京東、網易新聞,都是目前使用者使用量比較多的,并且,我在實際的項目中,用這個樣式的也比較多。那麼今天,我們就簡單實作這樣一個項目架構。
先看2張我實作的效果圖,
這是我仿照網易新聞用戶端做的!看着效果還行!O(∩_∩)O!那麼我們就開始今天的學習。
一.建立項目;
二.建立布局檔案,activity_home.xml,該布局檔案代碼如下,
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:id="@+id/navigation_tab_ll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="@color/color_aaaaaa"
android:orientation="horizontal"
android:paddingTop="1dp"
android:weightSum="5" >
<LinearLayout
android:id="@+id/id_news_ll"
style="@style/style_navigation_tab_ll" >
<ImageView
android:id="@+id/id_news_iv"
style="@style/style_navigation_tab_iv"
android:background="@drawable/biz_navigation_tab_news_selected" />
<TextView
android:id="@+id/id_news_tv"
style="@style/style_navigation_tab_tv"
android:text="新聞"
android:textColor="@color/color_eb413d" />
</LinearLayout>
<LinearLayout
android:id="@+id/id_read_ll"
style="@style/style_navigation_tab_ll" >
<ImageView
android:id="@+id/id_read_iv"
style="@style/style_navigation_tab_iv"
android:background="@drawable/biz_navigation_tab_read" />
<TextView
android:id="@+id/id_read_tv"
style="@style/style_navigation_tab_tv"
android:text="閱讀"
android:textColor="@color/color_aaaaaa" />
</LinearLayout>
<LinearLayout
android:id="@+id/id_va_ll"
style="@style/style_navigation_tab_ll" >
<ImageView
android:id="@+id/id_va_iv"
style="@style/style_navigation_tab_iv"
android:background="@drawable/biz_navigation_tab_va" />
<TextView
android:id="@+id/id_va_tv"
style="@style/style_navigation_tab_tv"
android:text="視聽"
android:textColor="@color/color_aaaaaa" />
</LinearLayout>
<LinearLayout
android:id="@+id/id_topic_ll"
style="@style/style_navigation_tab_ll" >
<ImageView
android:id="@+id/id_topic_iv"
style="@style/style_navigation_tab_iv"
android:background="@drawable/biz_navigation_tab_topic" />
<TextView
android:id="@+id/id_topic_tv"
style="@style/style_navigation_tab_tv"
android:text="話題"
android:textColor="@color/color_aaaaaa" />
</LinearLayout>
<LinearLayout
android:id="@+id/id_pc_ll"
style="@style/style_navigation_tab_ll" >
<ImageView
android:id="@+id/id_pc_iv"
style="@style/style_navigation_tab_iv"
android:background="@drawable/biz_navigation_tab_pc" />
<TextView
android:id="@+id/id_pc_tv"
style="@style/style_navigation_tab_tv"
android:text="我"
android:textColor="@color/color_aaaaaa" />
</LinearLayout>
</LinearLayout>
<FrameLayout
android:id="@+id/home_fl"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@id/navigation_tab_ll" />
</RelativeLayout>
底部是5個可以選擇的控件,這些布局之上是一個FrameLayout,FrameLayout是用來當點選底部不同的控件顯示不同的布局。這個很簡單!
我們這個裡面用到Fragment(當你點選不同的控件時,顯示的是不同Fragment),這是Android3.0後給出的,它很友善的解決了在pad或者大螢幕上app适配的問題(也就是說,隻要你在代碼中控制,那麼一套代碼就可以在手機、平闆等裝置上都可以适用,并且顯出的效果會根據裝置有所調整),官方也大力推薦我們在項目中使用它。現在v4包裡面已經有Fragment,當我們向下相容時,導入v4包就可以了。
接着,我們需要建立5個fragment_*.xml布局檔案,這5個布局檔案都差不多,隻是顯示的文字不一樣,是以,那看其中一個的布局,fragment_news.xml,代碼如下,
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="新聞"
android:textSize="20sp"
android:textColor="@color/color_eb413d" />
</RelativeLayout>
該布局就隻顯示一個TextView,fragment_*.xml其他的布局都差不多。
三.建立Fragment,我們就隻看看NewsFragment的實作,
/**
* 新聞
*/
public class NewsFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// TODO Auto-generated method stub
View view=inflater.inflate(R.layout.fragment_news, container, false);
return view;
}
/* (non-Javadoc)
* 當Fragment隐藏或者顯示的時候調用
* @see android.support.v4.app.Fragment#onHiddenChanged(boolean)
*/
@Override
public void onHiddenChanged(boolean hidden) {
// TODO Auto-generated method stub
super.onHiddenChanged(hidden);
if(hidden){// 不在最前端界面顯示
}else{// 重新顯示到最前端中
}
}
}
onCreateView(),這個方法是當Fragment加載布局時調用的,onHiddenChanged(),該方法當Fragment隐藏或者顯示的時候調用(我們在某些時候每次當顯示Fragment時都應該顯示最新的資料就可以用,詳細的可以看這篇文章:Fragment hide,show方法後,會調用什麼方法)。其他的Fragment的實作和這個都類似,唯一不一樣的地方就是加載的布局檔案不一樣。
四.建立Activity,我在項目中,定義了一個Activity基類,BaseActivity,,讓它繼承FragmentActivity
/**
* activity基類
*/
public class BaseActivity extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView();
initView();
setListener();
loadData();
}
/**
* 加載布局
*/
protected void setContentView() {
}
/**
* 綁定控件
*/
protected void initView() {
}
/**
* 設定監聽事件
*/
protected void setListener() {
}
/**
* 加載資料
*/
protected void loadData() {
}
}
定義了一些方法,把代碼分類。我們建立HomeAcivity,繼承BaseActivity,代碼如下,
/**
* 主布局
*/
@SuppressWarnings("deprecation")
public class HomeAcivity extends BaseActivity implements OnClickListener {
private FragmentManager fragmentManager;// Fragment管理
private NewsFragment newsFragment;//新聞
private ReadFragment readFragment;//閱讀
private VaFragment vaFragment;//視聽
private TopicFragment topicFragment;//話題
private MemberFragment memberFragment;//我
private ImageView newsIv;
private ImageView readIv;
private ImageView vaIv;
private ImageView topicIv;
private ImageView memberIv;
private TextView newsTv;
private TextView readTv;
private TextView vaTv;
private TextView topicTv;
private TextView memberTv;
private String tag = "0";//目前位置的辨別
private boolean isAppExit; // app退出标志位
public static final int APPEXIT = -1;//
@Override
protected void setContentView() {
setContentView(R.layout.activity_home);
}
@Override
protected void initView() {
newsIv = (ImageView) findViewById(R.id.id_news_iv);
readIv = (ImageView) findViewById(R.id.id_read_iv);
vaIv = (ImageView) findViewById(R.id.id_va_iv);
topicIv = (ImageView) findViewById(R.id.id_topic_iv);
memberIv = (ImageView) findViewById(R.id.id_pc_iv);
newsTv = (TextView) findViewById(R.id.id_news_tv);
readTv = (TextView) findViewById(R.id.id_read_tv);
vaTv = (TextView) findViewById(R.id.id_va_tv);
topicTv = (TextView) findViewById(R.id.id_topic_tv);
memberTv = (TextView) findViewById(R.id.id_pc_tv);
}
@Override
protected void setListener() {
findViewById(R.id.id_news_ll).setOnClickListener(this);
findViewById(R.id.id_read_ll).setOnClickListener(this);
findViewById(R.id.id_va_ll).setOnClickListener(this);
findViewById(R.id.id_topic_ll).setOnClickListener(this);
findViewById(R.id.id_pc_iv).setOnClickListener(this);
newsIv.setOnClickListener(this);
readIv.setOnClickListener(this);
vaIv.setOnClickListener(this);
topicIv.setOnClickListener(this);
memberIv.setOnClickListener(this);
}
@Override
protected void loadData() {
fragmentManager = getSupportFragmentManager();
setTabSelection(0);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.id_news_ll:
case R.id.id_news_iv:
setTabSelection(0);
break;
case R.id.id_read_ll:
case R.id.id_read_iv:
setTabSelection(1);
break;
case R.id.id_va_ll:
case R.id.id_va_iv:
setTabSelection(2);
break;
case R.id.id_topic_ll:
case R.id.id_topic_iv:
setTabSelection(3);
break;
case R.id.id_pc_ll:
case R.id.id_pc_iv:
setTabSelection(4);
break;
default:
break;
}
}
/**
* @param index
*/
private void setTabSelection(int index) {
// 每次選中之前先清除掉上次的選中狀态
clearSelection();
// 開啟一個Fragment事務
FragmentTransaction transaction = fragmentManager.beginTransaction();
// 先隐藏掉所有的Fragment,以防止有多個Fragment顯示在界面上的情況
hideFragments(transaction);
switch (index) {
case 0:
tag = "0";
newsIv.setBackgroundResource(R.drawable.biz_navigation_tab_news_selected);
newsTv.setTextColor(getResources().getColor(R.color.color_eb413d));
if (newsFragment == null) {
// 如果BrandSaleFragment為空,則建立一個并添加到界面上
newsFragment = new NewsFragment();
// mallFragment.setArguments(bundle);
transaction.add(R.id.home_fl, newsFragment);
} else {
// 如果MessageFragment不為空,則直接将它顯示出來
transaction.show(newsFragment);
}
break;
case 1:
tag = "1";
readIv.setBackgroundResource(R.drawable.biz_navigation_tab_read_selected);
readTv.setTextColor(getResources().getColor(R.color.color_eb413d));
if (readFragment == null) {
// 如果BrandSaleFragment為空,則建立一個并添加到界面上
readFragment = new ReadFragment();
// mallFragment.setArguments(bundle);
transaction.add(R.id.home_fl, readFragment);
} else {
// 如果MessageFragment不為空,則直接将它顯示出來
transaction.show(readFragment);
}
break;
case 2:
tag = "2";
vaIv.setBackgroundResource(R.drawable.biz_navigation_tab_va_selected);
vaTv.setTextColor(getResources().getColor(R.color.color_eb413d));
if (vaFragment == null) {
// 如果BrandSaleFragment為空,則建立一個并添加到界面上
vaFragment = new VaFragment();
// mallFragment.setArguments(bundle);
transaction.add(R.id.home_fl, vaFragment);
} else {
// 如果MessageFragment不為空,則直接将它顯示出來
transaction.show(vaFragment);
}
break;
case 3:
tag = "3";
topicIv.setBackgroundResource(R.drawable.biz_navigation_tab_topic_selected);
topicTv.setTextColor(getResources().getColor(R.color.color_eb413d));
if (topicFragment == null) {
// 如果BrandSaleFragment為空,則建立一個并添加到界面上
topicFragment = new TopicFragment();
// mallFragment.setArguments(bundle);
transaction.add(R.id.home_fl, topicFragment);
} else {
// 如果MessageFragment不為空,則直接将它顯示出來
transaction.show(topicFragment);
}
break;
case 4:
tag = "4";
memberIv.setBackgroundResource(R.drawable.biz_navigation_tab_pc_selected);
memberTv.setTextColor(getResources().getColor(R.color.color_eb413d));
if (memberFragment == null) {
// 如果BrandSaleFragment為空,則建立一個并添加到界面上
memberFragment = new MemberFragment();
// mallFragment.setArguments(bundle);
transaction.add(R.id.home_fl, memberFragment);
} else {
// 如果MessageFragment不為空,則直接将它顯示出來
transaction.show(memberFragment);
}
break;
}
transaction.commit();
}
/**
* 清除掉所有的選中狀态。
*/
private void clearSelection() {
newsIv.setBackgroundResource(R.drawable.biz_navigation_tab_news);
readIv.setBackgroundResource(R.drawable.biz_navigation_tab_read);
topicIv.setBackgroundResource(R.drawable.biz_navigation_tab_topic);
vaIv.setBackgroundResource(R.drawable.biz_navigation_tab_va);
memberIv.setBackgroundResource(R.drawable.biz_navigation_tab_pc);
newsTv.setTextColor(getResources().getColor(R.color.color_aaaaaa));
readTv.setTextColor(getResources().getColor(R.color.color_aaaaaa));
topicTv.setTextColor(getResources().getColor(R.color.color_aaaaaa));
vaTv.setTextColor(getResources().getColor(R.color.color_aaaaaa));
memberTv.setTextColor(getResources().getColor(R.color.color_aaaaaa));
}
/**
* 将所有的Fragment都置為隐藏狀态。
*
* @param transaction
* 用于對Fragment執行操作的事務
*/
private void hideFragments(FragmentTransaction transaction) {
if (newsFragment != null) {
transaction.hide(newsFragment);
}
if (readFragment != null) {
transaction.hide(readFragment);
}
if (topicFragment != null) {
transaction.hide(topicFragment);
}
if (vaFragment != null) {
transaction.hide(vaFragment);
}
if (memberFragment != null) {
transaction.hide(memberFragment);
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (tag.equals("1") || tag.equals("2") || tag.equals("3")|| tag.equals("4")) {
setTabSelection(0);
} else if (tag.equals("0")) {
appExit();
}
return true;
}
return super.onKeyDown(keyCode, event);
}
/**
* 退出app
*/
public void appExit() {
if (!isAppExit) {
isAppExit = true;
Toast.makeText(this, "再按一次,退出應用", Toast.LENGTH_SHORT).show();
handler.sendEmptyMessageDelayed(APPEXIT, 2000);
} else {
// 2s内再次按back時,isExit= true,執行以下操作,app退出
System.exit(0);
}
}
Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case APPEXIT:
isAppExit = false;
break;
default:
break;
}
};
};
}
首先設定布局,接着綁定控件,設定監聽事件,當點選不同的控件時,調用setTabSelection()方法,在該方法中,
1.清除控件之前的狀态,clearSelection();
2.隐藏所有的 Fragment,hideFragments();
3.根據傳遞的index參數,進入到相應的case中,先改變目前控件的狀态,接着,判斷目前Fragment是否為null,當為null時,建立該Fragment,并将該Fragment加入到FragmentManager,管理起來,當不為null時,就直接顯示該Fragment,記得還要送出該事務,transaction.commit()。
經過上面這幾步,就可以實作基本的功能了!我還實作了,onKeyDown()監聽事件(點選手機傳回鍵時的監聽),當點選傳回鍵時,如果目前顯示的不是主Fragment,那麼先跳轉到主Fragment,此時,再次點選傳回鍵時,便會看到提示“再按一次,退出應用”,若果是主Fragment,就如前面所說的。
至此,經過上面的流程,我們就能大緻實作文章開頭時,展示的項目樣式,我們在實際開發中,隻需要更換圖檔等一些簡單的操作,就可以很快實作這樣的項目樣式!該項目樣式的實作,得益于很早之前看郭霖大牛的部落格,是以,在此感謝郭霖大牛!
如果該文章你已經了解,那麼可以去看看這些文章,打造屬于你的萬能擴充卡和Android 滑動切換!
如果你也需要實作這樣的項目架構樣式,那麼請下載下傳源碼吧!
ps:源碼下載下傳位址