今天这篇文章,主要是为了快速搭建一个项目主体框架!
目前好多应用的主界面都是,底部几个切换按钮,点击不同的按钮,切换不同的界面,先来几张截图,如下,
这三张截图,分别来自淘宝、京东、网易新闻,都是目前用户使用量比较多的,并且,我在实际的项目中,用这个样式的也比较多。那么今天,我们就简单实现这样一个项目框架。
先看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:源码下载地址