1、抽取Activity基类:
为什么要抽取基类呢?因为每次都用到相同的东西就可以把相同的操作放到基类里面,可以复用
我们正常在activity的onCreate里面找控件添加事件,显示文本:每个组件基本都是这3步,所以抽基类
a,正常写法:
MainActivity.java:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button bt = (Button) findViewById(R.id.bt);//initView
bt.setOnClickListener(new OnClickListener() {//initListener
public void onClick(View v) {
Toast.makeText(MainActivity.this, "this is a toast", 0).show();
}
});
bt.setText("改变按钮");//initData
}
}
这样写有一个不好的地方就是如果控件多了onCreate方法里面就会有很多的重复代码
b,抽基类后的写法:
将我们的MainActivity所在的包名修改 com.example.test.ui.activity , 再创建一个com.example.test.base用于存放抽取的基类BaseActivity
com.example.test.base/BaseActivity.java:
public abstract class BaseActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//定义好了抽象方法,调用
initView();
initListener();
initData();
}
public abstract void initView();
public abstract void initListener();
public abstract void initData();
}
com.example.test.ui.activity/MainActivity.java:
public class MainActivity extends BaseActivity {
private Button bt;
@Override
public void initView() {
setContentView(R.layout.activity_main);
bt = (Button) findViewById(R.id.bt);
}
@Override
public void initListener() {
bt.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Toast.makeText(MainActivity.this, "this is a toast", Toast.LENGTH_SHORT).show();
}
});
}
@Override
public void initData() {
bt.setText("改变按钮");
}
}
这样我们就基本完成了基类的抽取,但是在MainActivity中的侦听我们也可以放到BaseActivity里面
c,优化后的抽基类:
com.example.test.base/BaseActivity.java:
public abstract class BaseActivity extends Activity implements OnClickListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//定义好了抽象方法,调用
initView();
initListener();
initData();
}
public abstract void initView();
public abstract void initListener();
public abstract void initData();
public abstract void processClick(View v);//记住一定要带一个View参数,便于主activity判断是哪个View
@Override
public void onClick(View v) {
processClick(v);//在主方法里面实现具体的侦听事件处理逻辑
}
}
com.example.test.ui.activity/MainActivity.java:
public class MainActivity extends BaseActivity {
private Button bt;
@Override
public void initView() {
setContentView(R.layout.activity_main);
bt = (Button) findViewById(R.id.bt);
}
@Override
public void initListener() {
//this就是MainActivity,它继承了BaseActivity,而父类实现了OnClickListener接口所以可以
bt.setOnClickListener(this);
}
@Override
public void initData() {
bt.setText("改变按钮");
}
@Override
public void processClick(View v) {//实现父类的点击处理的抽象方法
switch (v.getId()) {
case R.id.bt:
Toast.makeText(MainActivity.this, "this is a toast",Toast.LENGTH_SHORT).show();
break;
}
}
}
这样优化就完成了,在android4.4模拟机上亲测OK
2、去掉界面的标题栏:
我们的应用一般都不想要自带的标题栏,太丑了,在代码里面也可以实现,但是每个activity都去写一遍,太麻烦
我们可以在清单文件定义一个主题
我们在style.xml中定义一个没有标题的style
//系统调用的
<!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme">
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
</style>
//我们定义的
<style name="AppTheme2" parent="@android:style/Theme.NoTitleBar">
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
</style>
但是有个问题,我们如果用了AppTheme2这个主题,那么系统AppTheme里面其它的属性我们就用不了了。
这个时候我们可以进入@android:style/Theme.NoTitleBar里面查看下
里面的主要实现:
<style name="Theme.NoTitleBar">
<item name="android:windowNoTitle">true</item>//我们只需要这个就行
</style>
最后我们只需要在系统主题里面加一个属性就行:
<!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme">
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
<item name="android:windowNoTitle">true</item>
</style>
这样就完成了所有的界面都没有标题的操作
3、实现主界面的tab选项点击切换,也可以滑动切换
滑动切换主要用到ViewPager这个控件
主要的实现方案有2种
ViewPager+Fragment ,一个主的activity里面加上Fragment
tabHost+ViewPager, 不过定义xml布局文件需要注意将FrameLayout的高度定为0dp,只要显示选项卡就行
ViewPager是在v4包里面的,所以写的时候不会有提示的
下面主要分析下ViewPager+Fragment的实现方法,沿用上面的分析代码:
a,定义activity_main.xml的布局文件
这个和之前一样没有什么新的知识,主要就是用线性和相对布局组合来实现的。注意的一点就是ViewPager需要包名的路径
为了能向下兼容,使用的是android.support.v4包
activity_main.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="#292C29"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
>
<!-- 会话 -->
<LinearLayout
android:id="@+id/ll_tab_conversation"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/img_conversation"
/>
<TextView
android:id="@+id/tv_tab_conversation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="会话"
android:textColor="#FFFFFF"
android:textSize="14sp"
/>
</LinearLayout>
<!-- 分组 -->
<LinearLayout
android:id="@+id/ll_tab_group"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/img_group"
/>
<TextView
android:id="@+id/tv_tab_group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="分组"
android:textColor="#FFFFFF"
android:textSize="14sp"
/>
</LinearLayout>
<!-- 搜索 -->
<LinearLayout
android:id="@+id/ll_tab_search"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/img_search"
/>
<TextView
android:id="@+id/tv_tab_search"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="搜索"
android:textColor="#FFFFFF"
android:textSize="14sp"
/>
</LinearLayout>
</LinearLayout>
<View
android:id="@+id/v_indicate_line"
android:layout_width="60dp"
android:layout_height="4dp"
android:background="#CE0000"
android:layout_alignParentBottom="true"
/>
</RelativeLayout>
<android.support.v4.view.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"
></android.support.v4.view.ViewPager>
</LinearLayout>
b,定义一个Fragment基类:
我们在界面ViewPager上面显示Fragment,所以我们先要把Fragment基类创建出来.
所以我们先com.example.test.base包下定义一个BaseFragment基类继承Fragment,注意我们使用的是v4包的那个
BaseFragment.java:
public abstract class BaseFragment extends Fragment implements OnClickListener {
//1-返回一个View对象,这个对象会作为Fragment的显示内容
//2-注意我们填充哪个View不能在基类里面写死,我们要实现类中去填充。
//3-所以我们要定义一个抽象的initView方法,便于实现类去实现
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//5-这里我们就直接调用initView去返回一个填充的View对象
return initView(inflater, container, savedInstanceState);
}
//4-定义这个抽象的方法时,类也需要时抽象的,不过可以通过ctrl+1提示完成,注意参数和onCreateView保持一致
public abstract View initView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState);
//6-view对象的侦听和初始化数据也定义一个抽象的方法,调用的时机就时在FragmentActivity创建的时候调用,所以我们要重写下onActivityCreated方法
public abstract void initListener();
public abstract void initData();
//10-定义一个抽象的方法在onClick里面调用,给子类实现逻辑
public abstract void processClick(View v);//记得参数是View对象
//7-重写onActivityCreated方法,调用initListener 和 initData 初始化侦听和数据
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initListener();
initData();
}
//8-我们Fragment里面有侦听,所以我们要像抽取基类一样也去实现下OnClickListener侦听接口,在类名上加 implements OnClickListener
@Override
public void onClick(View v) {
//9-onClick里面的具体实现的逻辑是要子类实现的,所以我们定义一个抽象的方法去让子类实现
processClick(v);
}
}
c,定义一个ViewPager的适配器
ViewPager是一个ViewGroup,要实现切换是要有子节点的,这里不是addView,而是要设置一个adpter,和listView是一样的。
所以我们先在com.example.test.adpter包下定义一个adpter
MainPagerAdapter.java:
public class MainPagerAdapter extends FragmentPagerAdapter {
//3-定义一个framents用来保存传进来的需要显示的Fragment View对象
List<Fragment> fragments ;
//6-framents不可能自己创造,需要从外面传进来,所以在构造函数中添加参数
public MainPagerAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
this.fragments = fragments;
}
//1-返回的fragment对象会作为viewpager的条目,和ListViewAdpter里面的getView类似,系统调用。
@Override
public Fragment getItem(int position) {
//5-返回Fragment View对象
return fragments.get(position);
}
//2-我们不知道需要显示多少个Fragment的View对象,所以我们要创建一个集合,从外面传进来
@Override
public int getCount() {
//4-返回有多少个Fragment View对象
return fragments.size();
}
}
d,定义3个Fragment的布局文件
我们要显示3个Fragment,所以需要3个布局文件,用于显示不同的界面
fragment_conversatoin.xml fragment_group.xml fragment_search.xml
里面的内容自己定义,这里只显示一个模板,其它的复制粘贴就好了
fragment_conversation.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" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="会话"
android:textSize="40sp"
/>
</LinearLayout>
e,定义3个Fragment类,每个类就是一个tab下面显示的内容了
现在我们的基类都创建好了,可以创建3个Fragment类了
首先重新定义一个包 com.example.test.ui.fragment 里面再创建3个Fragment类
ConversationFragment.java:演示一个类的写法,其它复制粘贴
//1-创建的时候继承BaseFragment,自动就会生成下面4个方法需要实现
public class ConversationFragment extends BaseFragment {
@Override
public View initView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//2-填充布局文件,初始化会话的界面,返回的View对象就会给到基类的onCreateView返回
View view = inflater.inflate(R.layout.fragment_conversation, null);
return view;
}
@Override
public void initListener() {
// 暂时这3个方法先不写
}
@Override
public void initData() {
// TODO Auto-generated method stub
}
@Override
public void processClick(View v) {
// TODO Auto-generated method stub
}
}
d,MainActivity设置ViewPager的adpter(注意把BaseActivity里面改成继承FragmentActivity,不然拿不到FragmentManager)
现在我们adpter创建好了,3个fragment的类也创建好了,可以new fragment对象和设置adpter了
public class MainActivity extends BaseActivity {
private ViewPager viewPager;
private List<Fragment> fragments;
@Override
public void initView() {
setContentView(R.layout.activity_main);
//1-在xml中找到viewPager
viewPager = (ViewPager) findViewById(R.id.viewPager);
}
@Override
public void initListener() {
}
@Override
public void initData() {
//2-创建fragments 集合,定义一个全局变量
fragments = new ArrayList<Fragment>();
ConversationFragment fragment1 = new ConversationFragment();
GroupFragment fragment2 = new GroupFragment();
SearchFragment fragment3 = new SearchFragment();
fragments.add(fragment1);
fragments.add(fragment2);
fragments.add(fragment3);
//3-创建一个MainPagerAdapter,设置adapter
//fm是一个FragmentManager,要获得FragmentManager需要基类去继承FragmentActivity,而不是继承Activity
//这样才可以拿到FragmentManager
MainPagerAdapter adapter = new MainPagerAdapter(getSupportFragmentManager(), fragments);
viewPager.setAdapter(adapter);
}
@Override
public void processClick(View v) {
}
}
到这里我们就可以实现了界面滑动的整个流程,测试OK。大体的框架已经