天天看点

Android 项目开发框架

    今天这篇文章,主要是为了快速搭建一个项目主体框架!

    目前好多应用的主界面都是,底部几个切换按钮,点击不同的按钮,切换不同的界面,先来几张截图,如下,

Android 项目开发框架
Android 项目开发框架
Android 项目开发框架

这三张截图,分别来自淘宝、京东、网易新闻,都是目前用户使用量比较多的,并且,我在实际的项目中,用这个样式的也比较多。那么今天,我们就简单实现这样一个项目框架。

    先看2张我实现的效果图,

Android 项目开发框架
Android 项目开发框架

这是我仿照网易新闻客户端做的!看着效果还行!O(∩_∩)O!那么我们就开始今天的学习。

一.新建项目;

Android 项目开发框架

二.新建布局文件,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:源码下载地址