Android项目ViewPager+Fragment+RadioButton实现底部导航栏切换
Fragment是Android3.0后引入的一个新的API,它出现的初衷是为了适应大屏幕的平板电脑, 当然现在它仍然是平板APP UI设计的宠儿,而且我们普通手机开发也会加入这个Fragment, 我们可以把他看成一个小型的Activity,又称Activity片段。Fragment出现可以把布局进行分块,进行模块化管理,开发效率更高。可以一个Activity对应多个Fragment,真正做到模块化开发。现在来介绍一个Activity多个Fragment。
项目是由一个Activity和三个主Fragment构成,界面如图所示:
项目是一个灯泡控制器,由由一个MainActivity,主界面控制灯泡ControlFragment,连接界面ConnectFragment和扫描Wifi界面WifiFragment构成
。 MainActivity的布局界面的XML文件如下所示,通过ViewPager来替换三个Fragment。
1.1activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.wifi.main.MainActivity" android:orientation="vertical"> <!--中间显示的Fragment--> <LinearLayout android:id="@+id/id_content" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_above="@+id/_bottom" android:orientation="vertical"> <com.qmuiteam.qmui.widget.QMUIViewPager android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="wrap_content"> </com.qmuiteam.qmui.widget.QMUIViewPager> </LinearLayout> <!--底部导航栏--> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/_bottom" android:layout_alignParentBottom="true" android:gravity="center_horizontal"> <include layout="@layout/bottom_bar"></include> </LinearLayout> </RelativeLayout >
其中底部的导航栏是通过include引入的,其布局文件如下所示:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/bottom_bar" android:paddingTop="0dp" android:paddingBottom="0dp" android:layout_width="match_parent" android:layout_height="50dp" android:background="@color/bottom_bar_background" android:gravity="center_horizontal" android:orientation="horizontal" android:tint="@color/qmui_config_color_gray_4"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:layout_width="fill_parent" android:layout_height="1dp" android:background="@color/qmui_config_color_10_pure_black" /> <RadioGroup android:id="@+id/main_radiogroup" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="horizontal"> <RadioButton android:id="@+id/main_rab_house" android:checked="true" android:text="主页" style="@style/main_rbt" android:drawableTop="@drawable/home_drawable"/> <RadioButton android:id="@+id/main_rab_connect" style="@style/main_rbt" android:text="连接" android:drawableTop="@drawable/dashboard_drawable" /> <RadioButton android:id="@+id/main_rab_wifi" style="@style/main_rbt" android:text="配置" android:drawableTop="@drawable/notification_drawable"/> </RadioGroup> </LinearLayout> </LinearLayout>1.2 MainActivity通过ViewPager的滑动来改变RadioButton的选中情况,通过RadioButton的点击事件来设置ViewPager的当前显示的Fragment。代码
如下:
package com.wifi.main; import android.graphics.drawable.Drawable; import android.support.v4.app.Fragment; import android.os.Bundle; import android.support.v4.view.ViewPager; import android.support.v7.app.AppCompatActivity; import android.view.KeyEvent; import android.view.Window; import android.widget.RadioButton; import android.widget.RadioGroup; import android.widget.Toast; import com.wifi.fragment.ConnectFragment; import com.wifi.fragment.ControlFragment; import com.wifi.fragment.WifiFragment; import com.wifi.utils.MyFragmentPagerAdapter; import java.util.ArrayList; public class MainActivity extends AppCompatActivity implements RadioGroup.OnCheckedChangeListener{ //用于滑动切换的ViewPager private ViewPager mPager; private ArrayList<Fragment> fragmentList; private RadioButton home,connect,configwifi; private RadioGroup bottomGroup; private long exitTime = 0; //三个界面的Fragment private ControlFragment homeFragment; private ConnectFragment connectFragment; private WifiFragment wifiFragment; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); initViews(); initViewPager(); } /** * 初始化控件 */ public void initViews(){ mPager=(ViewPager)findViewById(R.id.viewPager); bottomGroup = (RadioGroup)findViewById(R.id.main_radiogroup); home = (RadioButton) findViewById(R.id.main_rab_house); connect = (RadioButton) findViewById(R.id.main_rab_connect); configwifi = (RadioButton) findViewById(R.id.main_rab_wifi); bottomGroup.setOnCheckedChangeListener(this); } private void initViewPager(){ homeFragment = new ControlFragment(); connectFragment = new ConnectFragment(); wifiFragment = new WifiFragment(); fragmentList=new ArrayList<Fragment>(); fragmentList.add(0,homeFragment); fragmentList.add(1,connectFragment); fragmentList.add(2,wifiFragment); //ViewPager设置适配器 mPager.setAdapter(new MyFragmentPagerAdapter(getSupportFragmentManager(), fragmentList)); //ViewPager显示第一个Fragment mPager.setCurrentItem(0); //ViewPager页面切换监听 mPager.addOnPageChangeListener(new MyOnPageChangeListener()); } /** *ViewPager切换Fragment,RadioGroup做相应变化 */ private class MyOnPageChangeListener implements ViewPager.OnPageChangeListener{ @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { switch (position){ case 0: bottomGroup.check(R.id.main_rab_house); break; case 1: bottomGroup.check(R.id.main_rab_connect); break; case 2: bottomGroup.check(R.id.main_rab_wifi); break; } } @Override public void onPageScrollStateChanged(int state) { } } /** * RadioButton切换Fragment * @param group * @param checkedId */ @Override public void onCheckedChanged(RadioGroup group, int checkedId) { switch (checkedId) { case R.id.main_rab_house: //ViewPager显示第一个Fragment且关闭页面切换动画效果 mPager.setCurrentItem(0,true); break; case R.id.main_rab_connect: mPager.setCurrentItem(1,true); break; case R.id.main_rab_wifi: mPager.setCurrentItem(2,true); break; } } /** * 监听Back键按下事件,方法1: * 注意: * super.onBackPressed()会自动调用finish()方法,关闭 * 当前Activity. */ public boolean onKeyDown(int keyCode, KeyEvent event) { // TODO 按两次返回键退出应用程序 if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) { // 判断间隔时间 小于2秒就退出应用 if ((System.currentTimeMillis() - exitTime) > 2000) { // 应用名 String applicationName = getResources().getString( R.string.app_name); String msg = "再按一次返回键退出"; //String msg1 = "再按一次返回键回到桌面"; Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show(); // 计算两次返回键按下的时间差 exitTime = System.currentTimeMillis(); } else { // 关闭应用程序 finish(); } return true; } return super.onKeyDown(keyCode, event); } @Override protected void onDestroy() { super.onDestroy(); } }
2.1接下来就是Fragment的代码和布局了,在这里我就直接介绍ControlFragment了,其他的都是一样的。ControlFragment的布局如下fragment_control.xml:
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/fragment_control" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.wifi.main.MainActivity"> <!--顶部标题栏--> <!--<include layout="@layout/window_title" android:id="@+id/title_home"/>--> <com.qmuiteam.qmui.widget.QMUITopBar android:id="@+id/topbar" android:layout_width="match_parent" android:layout_height="?attr/qmui_topbar_height"/> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginTop="?attr/qmui_topbar_height" android:background="@color/qmui_config_color_white"> <LinearLayout android:id="@+id/control_content" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <RelativeLayout style="@style/button_wrapper_style"> <com.qmuiteam.qmui.alpha.QMUIAlphaTextView android:id="@+id/messageID" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:gravity="center" android:ems="10" android:layout_centerInParent="true" android:textSize="20dp" android:textColor="@color/qmui_config_color_gray_5" android:hint="@string/input_bulb_id"> <requestFocus /> </com.qmuiteam.qmui.alpha.QMUIAlphaTextView> </RelativeLayout> <RelativeLayout style="@style/button_wrapper_style"> <TextView android:id="@+id/information" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:gravity="center" android:text="@string/connect_info" android:textColor="@color/qmui_config_color_gray_5" android:textSize="20dp" tools:layout_editor_absoluteX="135dp" tools:layout_editor_absoluteY="353dp" /> </RelativeLayout> <RelativeLayout style="@style/button_wrapper_style"> <com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton android:id="@+id/send_udp" android:layout_width="120dp" android:layout_height="46dp" android:layout_centerInParent="true" android:textSize="18dp" android:clickable="true" android:gravity="center" android:padding="1dp" android:text="@string/open_bulb" app:qmui_radius="4dp"/> </RelativeLayout> </LinearLayout> </ScrollView> </FrameLayout>2.2 ControlFragment的代码如下:
package com.wifi.fragment; import android.content.Context; import android.content.SharedPreferences; import android.content.res.Resources; import android.support.v4.app.Fragment; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.v4.content.ContextCompat; import android.text.InputType; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.EditText; import android.widget.PopupWindow; import android.widget.TextView; import android.widget.Toast; import com.java.bulb.BulbControl; import com.qmuiteam.qmui.alpha.QMUIAlphaImageButton; import com.qmuiteam.qmui.util.QMUIDisplayHelper; import com.qmuiteam.qmui.widget.QMUITopBar; import com.qmuiteam.qmui.widget.dialog.QMUIDialog; import com.qmuiteam.qmui.widget.dialog.QMUIDialogAction; import com.qmuiteam.qmui.widget.popup.QMUIPopup; import com.wifi.main.R; import com.wifi.utils.CommonUtils; import com.wifi.utils.MyApplication; import java.util.Map; import java.util.Timer; import java.util.TimerTask; import java.util.regex.Pattern; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; public class ControlFragment extends Fragment implements View.OnClickListener { private TextView mTextMessage; public static final String TAG = "MainActivity"; private Button send_udp,receive_udp,coapServer,coapClient; private long exitTime = 0; //发送或者接收的文本 public TextView send_msg,receive_msg; //目的主机IP private String SERVER_IP; private int SERVER_PORT; private TextView infomation; private String message; private byte[] meeeagebyte; //用户输入的灯泡ID private int bulbID; //用来存储全局变量,用于Activity之间的传递 private MyApplication myApplication; //定时器,用来存储全局变量检测是否接收到成功消息 private Timer timer; //灯泡的状态 private String status = "off"; private Thread thread; //灯泡控制类 private BulbControl bulbControl; //顶部标题栏 private QMUITopBar topBar; //普通浮层 private QMUIPopup mNormalPopup; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_control, container, false); initViews(view); //udpUtils = new UDPUtils(SERVER_IP,SERVER_PORT); // infomation.append("目的IP: "+SERVER_IP+"\n"+"目的端口: "+SERVER_PORT+"\n"); return view; } /** * 控件初始化 */ public void initViews(View view){ send_udp = (Button) view.findViewById(R.id.send_udp); // receive_udp = (Button) findViewById(R.id.receive_udp); send_msg = (TextView)view.findViewById(R.id.messageID); // receive_msg = (EditText) view.findViewById(R.id.receive); infomation =(TextView) view.findViewById(R.id.information); // coapServer = (Button) findViewById(R.id.coapServer); // coapClient = (Button) findViewById(R.id.coapClient); //设置标题栏 topBar = (QMUITopBar) view.findViewById(R.id.topbar); TextView title = topBar.setTitle(R.string.app_name); title.setTextSize(23); title.setTextColor(getResources().getColor(R.color.qmui_config_color_white)); topBar.setBackgroundColor(getResources().getColor(R.color.qmui_config_color_blue)); topBar.showTitleView(true); //添加左边返回按钮 // QMUIAlphaImageButton left = topBar.addLeftBackImageButton(); // receive_udp.setOnClickListener(MainActivity.this); send_udp.setOnClickListener(ControlFragment.this); send_msg.setOnClickListener(ControlFragment.this); infomation.setOnClickListener(ControlFragment.this); // coapClient.setOnClickListener(MainActivity.this); // coapServer.setOnClickListener(MainActivity.this); } //初始化普通浮层 public void initNormalPopupIfNeed(){ } public void onClick(View view) { switch (view.getId()) { case R.id.send_udp: } } ...... }
和Activity不同的是,Fragment的初始化是
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_control, container, false); initViews(view); //udpUtils = new UDPUtils(SERVER_IP,SERVER_PORT); // infomation.append("目的IP: "+SERVER_IP+"\n"+"目的端口: "+SERVER_PORT+"\n"); return view; }自定义一个Fragment类,需要继承Fragment或者他的子类,重写onCreateView()方法 在该方法中调用:inflater.inflate()方法加载Fragment的布局文件,接着返回加载的view对象。这样就能调用不同的Fragment实现不同的页面跳转,比多个Activity之间的跳转省事多了。