精华内容
下载资源
问答
  • Fragment使用

    千次阅读 2019-01-18 14:37:06
    1:如何在一个activity中添加fragment 2:如何动态的添加fragment 3:fragment与activity之间的通信 4:fragment的生命周期 1:一个完整的fragment需要有xml文件和java文件 xml文件自己随便加点东西就可以(它与一般...

    1:如何在一个activity中添加fragment
    2:如何动态的添加fragment
    3:fragment与activity之间的通信
    4:fragment的生命周期

    1:一个完整的fragment需要有xml文件和java文件
    xml文件自己随便加点东西就可以(它与一般的xml文件没啥两样);
    java文件需要继承Fragment如下图:在这里插入图片描述
    继承Fragment之后重写它的onCreateView()方法,将你的xml添加进去

    然后在activity_main中加上fragment:
    在这里插入图片描述
    这样就完成了一个Fragment的添加,按这个步骤再添加一个Fragment,运行程序就可以看到Activity中有两个Fragment了!(如果想要效果明显可以把第二个的Fragment的xml文件更换一个背景哦)

    2:动态添加Fragment:
    话不多说上代码!

    改一下activiy_main
    在这里插入图片描述
    将其中一个改为FrameLayout,属性不用改。

    好了现在来看java代码:
    transaction.replace(); //一参:是你想将fragment添加上去的布局的id 二参:是你要添加的fragment对象!!不要弄错!
    在这里插入图片描述

    前边就是一个按钮点击时间就不再介绍,主要看一下ADD方法里边的内容
    ADD方法参数中new了一个Fragment 为下面的添加做准备
    先通过getActivity获取一个fragment管理器
    然后通过管理器对象新建一个事务对象
    最后通过事务对象的replace方法加上要加的fragment和fragment对象
    再利用事务对象的commit提交一下就OK了!

    注意:transaction.addToBackStack(null);//添加返回栈,按下back后不会直接退出程序,而是返回上一个碎片

    现在的效果是你点击有这个按钮的Fragment另一个Fragment才会添加到Activtiy中。

    3:fragment与activity之间的通信:
    在acivtiy中用到fragment时用下面的方法获取fragment对象:

     Fragment_right fragment_right= (Fragment_right) getSupportFragmentManager().findFragmentById(R.id.frame_right);
    

    在fragment中用到activity用下面方法:

    MainActivity activity=(MainActivity)getActivtiy;
    

    这里的通信可以自己做个小demo,例如:fragment1点击按钮来设置fragmen2里的TextView

    4:Fragment生命周期!!!非常重要!!!!
    很重要但是也很简单,需要自己去摸清它的运作方式,这对以后编程工作影响很大,希望刚入门的小伙伴一定将其弄明白。
    在这里插入图片描述

    这里就不做过多的详细解说,你们可以去参考其他的博客,有很多写的很详细的,
    最后希望大家都能学好一门技术走向人生巅峰!
    本人初学android,写博客也是为了加深记忆,便于以后查看,如果有写的不对的地方,请为我指点迷津!

    展开全文
  • Fragment使用手势操作

    热门讨论 2014-01-03 14:26:50
    Fragment使用Gestdetctor时会遇到的问题,主要是这个操作只能由父Activity传递到子Fragment,所以我们通过设置接口的模式来将这种机制来传递下来
  • Android Fragment使用案例

    千次阅读 2020-03-03 18:47:52
    fragment加载方式 1. 静态加载( 不行,没有 试出来) 2. 动态加载 1. Fragent使用 效果图: Java代码 MainActivity: *************************************************************************************...

    fragment加载方式

    1. 静态加载( 不行,没有 试出来)

    2. 动态加载

    案例1: 使用上面按钮实现 Fragent的左右切换

    效果图:

      Java代码  MainActivity:

    ***********************************************************************************************************************

    public class MainActivity extends AppCompatActivity {
        LinearLayout mainContext;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mainContext = findViewById(R.id.mainContext);
            AFragment aFragment=new AFragment();
            FragmentManager manager=getFragmentManager();
            // Fragment 添加事务
            FragmentTransaction transaction= manager.beginTransaction();
            // 把Fragment 添加到指定容器中,提交才有效果
            transaction.add(R.id.mainContext,aFragment).commit();
        }

        public void  f1(View view){
            AFragment aFragment=new AFragment();
            FragmentManager manager=getFragmentManager();
            // Fragment 添加事务
            FragmentTransaction transaction= manager.beginTransaction();
            // 把Fragment 添加到指定容器中,提交才有效果
            transaction.replace(R.id.mainContext,aFragment).commit();
        }

        public void f2(View view){
            BFragment bFragment=new BFragment();
            FragmentManager manager=getFragmentManager();
            // Fragment 添加事务
            FragmentTransaction transaction= manager.beginTransaction();
            // 把当前操作添加到回退栈,点击back键盘可以回退到上一个Fragment
            transaction.addToBackStack(null);
            // 把Fragment 添加到指定容器中,提交才有效果
            // 首先 remove,然后在add
            transaction.replace(R.id.mainContext,bFragment).commit();
         //    transaction.remove(bFragment).commit();

        }
    }
    ***********************************************************************************************************************

      activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout 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:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="mk.denganzhi.com.test.MainActivity"
        android:orientation="vertical">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
    
            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:onClick="f1"
                android:text="回调第一个界面" />
    
            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:onClick="f2"
                android:text="f2" />
    
        </LinearLayout>
         <LinearLayout
             android:id="@+id/mainContext"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
             android:layout_weight="1"
             android:orientation="horizontal">
    
    </LinearLayout>
    </LinearLayout>
    

     BFragment

    
    public class BFragment extends Fragment {
    
    
        @Override
        public void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
        }
    
    
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
    
            View view = View.inflate(getActivity(),R.layout.afragment,null);
            Button btn1 = view.findViewById(R.id.btn1);
            btn1.setTextColor(Color.BLACK);
            btn1.setText("BFragment");
            return view;
        }
    }
    

    afragment.xml

    <?xml version="1.0" encoding="utf-8"?>
    <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">
    
        <Button
            android:id="@+id/btn1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="aFragment......."
            tools:layout_editor_absoluteX="249dp"
            tools:layout_editor_absoluteY="112dp" />
    </LinearLayout>

     案例2:ListFragment + Fragment 配合使用    

    代码实现:Main2Activity 

    public class Main2Activity extends FragmentActivity {
    
    
        LinearLayout fl_main_first;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main2);
            fl_main_first = findViewById(R.id.fl_main_first);
    
             TitleListFragment aFragment=new TitleListFragment();
             FragmentManager manager=getFragmentManager();
            // Fragment 添加事务
              FragmentTransaction transaction= manager.beginTransaction();
          // 把Fragment 添加到指定容器中,提交才有效果
              transaction.add(R.id.fl_main_first,aFragment).commit();
    
        }
    }
    

    布局:

    <?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="horizontal" >
    
        <LinearLayout
            android:id="@+id/fl_main_first"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="match_parent"
            android:orientation="horizontal">
        </LinearLayout>
    
        <FrameLayout
            android:id="@+id/fl_main_container"
            android:layout_width="0dp"
            android:layout_weight="3"
            android:layout_height="match_parent" >
        </FrameLayout>
    
    </LinearLayout>
    TitleListFragment 代码实现:
    package mk.denganzhi.com.test.new1;
    
    
    
    
    import android.app.ListFragment;
    import android.os.Bundle;
    
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ArrayAdapter;
    import android.widget.ListView;
    
    
    import mk.denganzhi.com.test.R;
    
    
    public class TitleListFragment extends ListFragment {
    
    	public static final String[] TITLES = {"title1","title2","title3","title4","title5"};
    	public static final String[] DETAILS = {"This is title1","This is title2",
    			"This is title3","This is title4","This is title5"};
    
    	@Override
    	public View onCreateView(LayoutInflater inflater, ViewGroup container,
    							 Bundle savedInstanceState) {
    		return super.onCreateView(inflater, container, savedInstanceState);
    	}
    
    	@Override
    	public void onActivityCreated(Bundle savedInstanceState) {
    		super.onActivityCreated(savedInstanceState);
    		
    		//设置ListView为单选模式,内部封装了ListView
    		getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
    		
    		// 给listView设置adapter显示列表
    		setListAdapter(new ArrayAdapter<String>(getActivity(),
    				R.layout.list_item, TITLES));
    		
    		//默认选中第一个item
    		getListView().setItemChecked(0, true);
    		//显示第一个详情
    		showDetail(0);
    	}
    	
    	@Override
    	public void onListItemClick(ListView l, View v, int position, long id) {
    		showDetail(position);
    	}
    
    	/**
    	 * 显示指定下标的详情
    	 * @param position
    	 */
    	private void showDetail(int position) {
    		//创建DetailFragment
    		DetailFragment fragment = new DetailFragment();
    		//将对应的详情数据携带过去
    		Bundle args = new Bundle();
    		args.putString("DETAIL", DETAILS[position]);
    		fragment.setArguments(args);
    		//将其替换到id为fl_main_container的容器布局中
    		getFragmentManager().beginTransaction().replace(R.id.fl_main_container, fragment).commit();
    	}
    }
    
    DetailFragment:
    package mk.denganzhi.com.test.new1;
    
    import android.app.Fragment;
    import android.os.Bundle;
    
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.TextView;
    
    /**
     *显示详情的Fragment
     * @author 张晓飞
     *
     */
    public class DetailFragment extends Fragment {
    
    	@Override
    	public View onCreateView(LayoutInflater inflater, ViewGroup container,
    			Bundle savedInstanceState) {
    		TextView textView = new TextView(getActivity());
    		//取出保存的数据
    		String detail = getArguments().getString("DETAIL");
    		//设置
    		textView.setText(detail);
    		return textView;
    	}
    }
    

     

      案例3:fragment生命周期:

         启动应用:onAttach  onCreate  onCreateView onActivityCreated onStart onResume
          HOME键:onPause()-->onStop()
          回到应用: onStart  onResume 
          replace为其它Fragment:onPause()-->onStop()-->onDestroyView()
    返回到本身的Fragment:    onCreateView()-->onActivityCreated()-->onstart()-->onResume()
          退出应用:onPause onStop  onDestroyView  onDetach onDestroy

    源码路径:https://download.csdn.net/download/dreams_deng/12254692 

    展开全文
  • Fragment使用姿势之NoFragment

    万次阅读 多人点赞 2017-01-15 15:39:36
    NoFragment支持传统Fragment用法,支持startFragmentForResult,支持一个Fragment启动多个实例,自持自动维护Back Stack,顺序不会错乱,支持Fragment中直接setToolbar()、setTitle()、displayHomeButton()、支持...

    版权声明:转载必须注明本文转自严振杰的博客:http://blog.yanzhenjie.com

    我还算是个比较传统的人,所以我一直觉得明年是从春节开始,所以这是我今年最后一骗博客了,当然也是我阳历2017年第一骗博客,希望大家可以吸收到对自己有帮助的东西,因此这是一骗承上启下的文章。对了,你没看错,是骗(反正你也不能顺着网线来打我)。

    今天会先介绍Fragment通常的四种用法,然后再介绍一个开源项目NoFragment的特点和用法。

    对于Fragment大家一定不陌生,记得第一次接触时我还是个大三的学生。是在2013年底参加Google全国大学生Android应用设计大赛时,初赛获得华中五省第二名,有资格参加全国总决赛。总决赛是现场编码,需求大概是这样的:要求使用的技术FragmentSocketNFC二维码识别,远程控制一个装有摄像头的小车沿着规定的路线做task,并且一路拍照并上传到Android端,Android端分析图片颜色,根据指定颜色再进行下一个随机任务,重点是,Android端手动发送一个start命令后,人就不能触碰手机了,剩下的事情全部由我们开发的Android端智能完成。项目和任务都完成了,遗憾的是由于其它人耗时更短,所以只获得了15/34。不过从那个比赛也收获了很多,从此从JavaWeb跳入了Android的坑,但是我一直很庆幸自己在从事Android开发。当时印象最深的是玩FragmentNFC,网上没有任何文章,就只好从官网看文档,后来也养成了自己喜欢看官网的文档的习惯。

    回到正题,不少被Fragment的生命周期、相互跳转、参数传递、stack回退等问题困扰。如果是结合ViewPager还好说。然而很多同学的项目结构是一个Activity + 多个Fragment的形式,这样会加快页面之间的跳转,但是也带来不少问题,请往下看。

    因此顺理成章的安利一个开源项目NoFragment,代码开源在Github:https://github.com/yanzhenjie/NoFragment

    NoFragment 特点

    1. 支持传统Fragment的所有用法。
    2. 支持startFragmentForResult(Fragment)onFragmentResult(int, int, Bundle),原生只有Activity。
    3. 支持同一个Fragment启动多个实例。
    4. 支持自动维护Back Stack,不会错乱。
    5. 支持在Fragment中直接setToolbar()setTitle()displayHomeButton()
    6. 返回键和homeButton自动处理,支持开发者拦截处理。
    7. 支持ActionBar Menu、溢出Menu等。

    当然最基本的是一个Activity + 多个Fragment。

    依赖方法

    • Gradle一句话远程依赖
    compile 'com.yanzhenjie:fragment:1.0.0'
    • Maven:
    <dependency>
      <groupId>com.yanzhenjie</groupId>
      <artifactId>fragment</artifactId>
      <version>1.0.0</version>
      <type>pom</type>
    </dependency>
    • Eclipse ADT
      请放弃治疗。

    通常使用Fragment 4个姿势

    一般我们使用Fragment大概有四种方法,第一种:ViewPager + Fragment,第二种:layout.xml{framgent},第三种:FragmetManager#replace(),第四种:FragmentManager#show()/hide(),下面我们一个个来看看用法和他们的优缺点。

    一、ViewPager + Fragment

    先来看一张图:

    ViewPager + Fragment

    当然了,代码也是超级无敌的简单(纯手写,小错请忽略):

    ViewPager viewPager = findViewById(R.id.view_pager);
    List<Fragment> fragmentList = new ArrayList<>();
    fragmentList.add(new MyFragment());
    ...
    FragmentManager fManager = getSupportFragmentManager();
    FragmentAdapter adapter = new FragmentAdapter(fManager, fragmentList);
    viewPager.setAdapter(adapter);
    
    ------------------------------------------------------------------------------
    
    public class FragmentAdapter extends FragmentPagerAdapter {
    
        private List<Fragment> mFragmentList;
    
        public FragmentAdapter(FragmentManager fm, List<Fragment> fragmentList) {
            super(fm);
            mFragmentList = fragmentList;
        }
    
        @Override
        public Fragment getItem(int position) {
            return mFragmentList.get(position);
        }
    
        @Override
        public int getCount() {
            return mFragmentList.size();
        }
    }

    这种玩法应该是最简单的一种了,ViewPager的Adapter会自动为我们管理show()hide(),生命周期的调用我们也完全不用担心,由于这种方法太简单了,就不说了,对此用法遇到问题的同学也可以在文章下留言,我会一一解答。

    二、layout.xml {framgent}

    这种玩法也很简单,在布局中写一个framgent,name填我们fragment完整包名就可以了,这种用法我们可以简单粗暴的把fragment理解为一个view:

    <?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">
    
        <fragment
            android:id="@+id/fragment_sign_in"
            android:name="com.yanzhenjie.fragment.SignInFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    </LinearLayout>

    上述代码中的framgent完整包名:android:name="com.yanzhenjie.fragment.SignInFragment",这样布局会自动加载fragment进来,我们在java代码中可以通过如下方法拿到这个fragment

    FragmetnManager fManager = getSupportFragmentManager();
    SignInFragment signInFragment = (SignInFragment)fManager.findFragmentById(R.id.fragment_sign_in);
    // TODO Then, do anything.

    这种玩法常用的是大屏手机上,左边一个MenuFragment,右边一个ContentFragment,左边控制右边的内容。当然也有一个Fragment占满全屏的用法,比如高德地图MapView提供的MapFragment

    三、FragmetManager#replace()

    我最开始玩Fragment就是这么玩的,一般是在布局中提供一个空的FrameLayout,再用FragmetManager#replace()替换要显示的Fragment

    // 调用
    replaceFragment(new SignInFragment());
    
    --------------------------------------------------------------
    
    public <T extends Fragment> void replaceFragment(T fragment) {
        FragmentManager fManager = getSupportFragmentManager();
        fManager
            .beginTransaction()
            .replace(R.id.fragment_root, fragment)
            .commitAllowingStateLoss();
    }

    这种用法可以做到项目只有一个Activity,然后多个Fragment做为切换的页面。比较省内存,页面之间的跳转速度比较快,由于使用replace()方法它的缺点是:

    • 所以无法保存fragment的状态。
    • Back Stack错乱,没有ActivityBack Stack的好用。
    • 没有startFragmetnForResult()用法。

    四、FragmentManager#show()/hide()

    我们先来看看这种方法怎么玩:

    /**
     * 显示一个新的fragment,并且隐藏旧的fragment。
     *
     * @param outFragment display fragment。
     * @param inFragment  hide fragment。
     * @param <T>         {@link Fragment}.
     */
    public <T extends Fragment> void showHideFragment(T outFragment, T inFragment) {
        FragmentManager fManager = getSupportFragmentManager();
        // 如果要隐藏的fragment非空,隐藏。
        if (outFragment != null) {
            fManager
                .beginTransaction()
                .hide(outFragment)
                .commit();
        }
        // 先从栈中看是否存在要显示的fagment。
        String tag = inFragment.getClass().getClass().getSimpleName();
        Fragment tempFragment = fManager.findFragmentByTag(tag);
        if(tempFragment != null) { // 存在则直接显示。
            fManager
                .beginTransaction()
                .show(inFragment)
                .commitAllowingStateLoss();
        } else { // 不存在就添加并显示。
            fManager
                .beginTransaction()
                .add(R.id.fragment_root, inFragment, tag)
                .addToBackStack(tag)
                .commitAllowingStateLoss();
        }
    }
    
    /**
     * Destroy self.
     */
    public <T extends Fragment> void finish(T fragment) {
        FragmentManager fManager = getSupportFragmentManager();
        fManager
            .beginTransaction()
            .remove(fragment)
            .commitAllowingStateLoss();
        }

    经过上面的封装,其实已经变的很好用了:
    Activity中:

    showHideFragment(null, new SignInFragment());

    Fragment中:

    showHideFragment(this, new RegisterFragment());

    当需要退出的时候:

    finish(this);

    结合注释看应该是看得懂的,调用show()hide()方法可以保存fragment的状态,但是逻辑复杂,同样存在以下缺点:

    • 没有startFragmetnForResult()用法。
    • 没有Activitystandard模式,也就是同一个Fragment启动多个实例。

    因此我结合support包中的Fragment开发了NoFragment,没错它和NoHttp是同一个系列,就是为了让你忘记Fragment

    NoFragment新姿势新玩法

    其实Fragment的用法上图是没法很直观的了解的,所以建议大家去下载Demo看看,如果觉得好用的话,顺便点个Star:https://github.com/yanzhenjie/NoFragment

    特点

    1. 支持传统Fragment的所有用法。
    2. 支持startFragmentForResult(Fragment)onFragmentResult(int, int, Bundle),原生只有Activity。
    3. 支持同一个Fragment启动多个实例。
    4. 支持自动维护Back Stack,不会错乱。
    5. 支持在Fragment中直接setToolbar()setTitle()displayHomeButton()
    6. 返回键和homeButton自动处理,支持开发者拦截处理。
    7. 支持ActionBar Menu、溢出Menu等。
    8. 开发者不用管跳转逻辑、back键处理、Toolbar加载菜单等。

    图示

    第一种,结合ToolBar、Menu的演示:

    这里写图片描述

    第二种,结合Toolbar、Menu + OverFlower的演示:

    这里写图片描述

    第三种,startFragmentForResult()onFragmentResult()演示:

    这里写图片描述

    第四种,不保存的在回退栈的演示:

    这里写图片描述

    用法

    你的宿主Activity需要继承CompatActivity,然后启动一个Fragment

    public class MainActivity extends CompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            /*
             * 一句话即可,不要怀疑自己的眼睛,这是真的。
             */
            startFragment(MainFragment.class);
        }
    
        @Override
        protected int fragmentLayoutId() {
            return R.id.fragment_root;
        }
    
    }

    之后在Fragment中互相跳转,你可以不同管物理Back键被按下之类的:

    一、以standard模式启动一个Fragment

    startFragment(MoreMenuFragment.class);

    二、以startActivityForResult()方式启动一个Fragment

    // 启动,等待回调结果。
    startFragmentForResquest(StartResultFragment.class, 100);
    
    // 不论怎样回来都会回调onFragmentResult()。
    @Override
    public void onFragmentResult(int requestCode, int resultCode, @Nullable Bundle result) {
        switch (requestCode) {
            case 100: {
                if (resultCode == RESULT_OK) {
                    // 操作成功:result就是调用的Fragment返回的结果。
                } else if (resultCode == RESULT_CANCELED) {
                    // 操作取消。
                }
                break;
            }
        }
    }

    StartResultFragment中如果要返回结果,那么:

    Bundle bundle = new Bundle();
    bundle.putString("message", result);
    setResult(RESULT_OK, bundle);
    finish();

    当然你也不设置,那么resultCode的默认值是RESULT_CANCELED

    三、跳转时带参数

    // 封装参数:
    Bundle bundle = new Bundle();
    bundle.putString("hehe", "呵呵哒");
    bundle.putString("meng", "萌萌哒");
    bundle.putString("bang", "棒棒哒");
    bundle.putString("meme", "么么哒");
    
    // 第一种:
    NoFragment fragment = NoFragment.instantiate(getContext(), ArgumentFragment.class, bundle);
    
    // 第二种:
    ArgumentFragment fragment = new ArgumentFragment();
    fragment.setArgument(bundle);
    
    // 最后启动:
    startFragment(fragment);

    四、跳转的Fragment不保存在Back Stack

    这种方式显示的fragment中如果调用了其它fragment,从其它fragment中回来时,这个fragment将会跳过,不会显示,也就是说:A-B-C-[back]-A,从A到B,B不加入回退栈,B再到C,C按下返回键,或者调用finish()方法,将会直接回到A。

    startFragment(StackFragment.class, false);

    五、同一个Fragment,启动多个实例

    startFragment(MoreMenuFragment.class);
    startFragment(MoreMenuFragment.class);
    startFragment(MoreMenuFragment.class);
    startFragment(MoreMenuFragment.class);

    比如我们这里调用四次,那么回退栈中有四个MoreMenuFragment,按下返回键时将一个个退出。

    六、Toolbar菜单的加载和处理

    我们知道MD设计中,Toolbar的菜单很好看,而且利用Toolbar也很好加载,那么NoFragment也是完美支持的,当重写了onCreateOptionsMenu()方法后,调用setToolbar(Toolbar)方法时,将会调用onCreateOptionsMenu()方法,此时你就该加载菜单了,当然也只需要一句话。

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        // Load your menu.
        inflater.inflate(R.menu.menu_fragment_main, menu);
    }

    当用户点击meun的item时将会回调这个方法,和原生Activity是一样的。

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle menu item click.
        int id = item.getItemId();
        switch (id) {
            case R.id.action_settings: {
                Snackbar.make(mToolbar, R.string.action_settings, Snackbar.LENGTH_SHORT).show();
                break;
            }
            case R.id.action_exit: {
                Snackbar.make(mToolbar, R.string.action_exit, Snackbar.LENGTH_SHORT).show();
                break;
            }
        }
        return true;
    }

    七、Toolbar的返回按钮的处理

    在正常开发中给Toolbar设置返回按钮也要好几行代码的,如果使用了NoFragment,那么:

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
    
        // 首先设置Toolbar:
        setToolbar(mToolbar);
    
        // 设置标题:
        setTitle(R.string.title_fragment_main);
    
        // 显示返回按钮,图标开发者指定:
        displayHomeAsUpEnabled(R.drawable.ic_close_white);
    }

    设置了返回按钮后,用户点击返回按钮将自动杀死当前Fragment,当然你也可以拦截用户的返回行为:

    @Override
        public boolean onInterceptToolbarBack() {
            // 返回true将拦截,返回false将不拦截。
            return true;
        }

    混淆

    -keep public class * extends android.support.v4.app.Fragment

    好啦,到这里就完了,希望这个项目可以帮到需要的同学。


    版权声明:转载必须注明本文转自严振杰的博客:http://blog.yanzhenjie.com

    展开全文
  • 几来着,就是google新出的androidx环境,写项目的时候发现,Fragment的导包居然有两个,刚开始使用android下面的包,会出现方法过期,怎么看怎么不顺眼,然后就导入androidx,一系列报错,这是最尴尬的! 比如: private ...

    从不久之前,我把我的android stuidio软件更新到3.几来着,就是google新出的androidx环境,写项目的时候发现,Fragment的导包居然有两个,刚开始使用android下面的包,会出现方法过期,怎么看怎么不顺眼,然后就导入androidx,一系列报错,这是最尴尬的!

    比如:

    private var mfragmentManager: FragmentManager? = null
    mfragmentManager = getSupportFragmentManager();  //获得FragmentManager的对象

    可不能使用之前的 getChildFragmentManager() 以及getFragmentManager(),首先你这个activity还得继承

     FragmentActivity(),注意是导包
    import androidx.fragment.app.FragmentActivity

    主要就是这个,接下来看代码:

    package com.airiche.nixplay.Activity
    
    import android.content.Intent
    import android.os.Bundle
    import com.airiche.nixplay.MainApplication
    
    import android.util.Log
    import androidx.fragment.app.FragmentActivity
    import androidx.fragment.app.FragmentManager
    import androidx.fragment.app.FragmentTransaction
    import com.airiche.nixplay.FragMent.FriendsFragment
    import com.airiche.nixplay.FragMent.MoreFragment
    import com.airiche.nixplay.FragMent.NixPlayFragment
    import com.airiche.nixplay.FragMent.PhotoFragment
    import com.airiche.nixplay.R
    import com.airiche.nixplay.Utils.StatusBarutrl
    import kotlinx.android.synthetic.main.activity_main_interface.*
    
    
    class MainInterfaceActivity : FragmentActivity() {
        private var mfragmentManager: FragmentManager? = null
    
        //创建的四个碎片
        private var mNixPlayFragment: NixPlayFragment? = null
        private var mPhotoFragment: PhotoFragment? = null
        private var mFriendsFragment: FriendsFragment? = null
        private var mMoreFragment: MoreFragment? = null
    
        private var TAG: String = "MainInterfaceActivity"
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main_interface)
     
            Initialization()
        }
    
    
        private fun Initialization() {
            mfragmentManager = getSupportFragmentManager();  //获得FragmentManager的对象
            setTabSelection(0)
    
            //这是这个activity的点击事件 四个button
            NixPlayButton.setOnClickListener {
                setTabSelection(0)
            }
            PhotoButton.setOnClickListener {
                setTabSelection(1)
            }
            FriendButton.setOnClickListener {
                setTabSelection(2)
            }
            MoreButton.setOnClickListener {
                setTabSelection(3)
            }
        }
    
    
    
        /**
         * 根据传入的index参数来设置选中的tab页。
         * @param index
         * 每个tab页对应的下标。
         **/
        private fun setTabSelection(index: Int) {
            Log.e(TAG, "index===" + index)
            CleanImageState()
            var mFragmentTransaction = mfragmentManager!!.beginTransaction()
            // 每次选中之前先清楚掉上次的选中状态
            hideAllFragment(mFragmentTransaction)
            when (index) {
                0 -> {
                    NixPlayButton.setImageResource(R.drawable.nixplay)
                    if (null == mNixPlayFragment) {
                        mNixPlayFragment = NixPlayFragment()
                        mFragmentTransaction!!.add(R.id.InterFace_FrameLayout, mNixPlayFragment!!)
                    } else {
                        mFragmentTransaction!!.show(mNixPlayFragment!!)
                    }
                }
                1 -> {
                    PhotoButton.setImageResource(R.drawable.photo)
                    if (null == mPhotoFragment) {
                        mPhotoFragment = PhotoFragment()
                        mFragmentTransaction!!.add(R.id.InterFace_FrameLayout, mPhotoFragment!!)
                    } else {
                        mFragmentTransaction!!.show(mPhotoFragment!!)
                    }
                }
                2 -> {
                    FriendButton.setImageResource(R.drawable.friend)
                    if (null == mFriendsFragment) {
                        mFriendsFragment = FriendsFragment()
                        mFragmentTransaction!!.add(R.id.InterFace_FrameLayout, mFriendsFragment!!)
                    } else {
                        mFragmentTransaction!!.show(mFriendsFragment!!)
                    }
                }
                3 -> {
                    MoreButton.setImageResource(R.drawable.more)
                    if (null == mMoreFragment) {
                        mMoreFragment = MoreFragment()
                        mFragmentTransaction!!.add(R.id.InterFace_FrameLayout, mMoreFragment!!)
                    } else {
                        mFragmentTransaction!!.show(mMoreFragment!!)
                    }
                }
            }
            mFragmentTransaction!!.commit();  //提交
        }
    
        /**
         * 将所有的Fragment都置为隐藏状态。
         * @param transaction
         * 用于对Fragment执行操作的事务
         */
        private fun hideAllFragment(mFragmentTransaction: FragmentTransaction) {
            if (null != mNixPlayFragment) {
                mFragmentTransaction!!.hide(mNixPlayFragment!!)
            }
            if (null != mPhotoFragment) {
                mFragmentTransaction!!.hide(mPhotoFragment!!)
            }
            if (null != mFriendsFragment) {
                mFragmentTransaction!!.hide(mFriendsFragment!!)
            }
            if (null != mMoreFragment) {
                mFragmentTransaction!!.hide(mMoreFragment!!)
            }
        }
    
        private fun CleanImageState() {
            //这是四个点击事件的背景图更改 你们视情况而定
            NixPlayButton.setImageResource(R.drawable.nixplay_box)
            PhotoButton.setImageResource(R.drawable.photo_box)
            FriendButton.setImageResource(R.drawable.friend_box)
            MoreButton.setImageResource(R.drawable.more_box)
        }
    }
    

    这就是些主要代码了,别的就不贴了,从android包到androidx,对应的TabLayout+Fragment+ViewPager也会有影响: 

    注释:MainInterfaceActivity 这个activity主要内容就是Fragment,里面包含四个碎片,然后TabLayout在碎片PhotoFragment 里面,那么接下来我们就来看一下这个Fragment

    接下来我们再来看下TabLayout+Fragment+ViewPager的操作:

    首先导包:

    implementation 'com.android.support:design:26.1.0'

     布局:布局当中主要有TabLayout以及ViewPager两个控件

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                  xmlns:app="http://schemas.android.com/apk/res-auto"
                  android:layout_width="match_parent" android:layout_height="match_parent"
                  android:orientation="vertical"
                  android:layout_marginTop="@dimen/x20"
                  android:background="@color/MainInterFace_background">
    
        <com.google.android.material.tabs.TabLayout
                android:id="@+id/Pnoto_Table"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@null"/>
    
      
    
        <androidx.viewpager.widget.ViewPager
                android:id="@+id/Pnoto_vp"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"/>
    
    
    </LinearLayout>

    接下来我们就看一下布局所对应的PhotoFragment碎片代码,这个碎片里面是主要的代码,里面Viewpager关联TabLayout,碎片关联ViewPager

    package com.airiche.nixplay.FragMent
    
    import android.graphics.Color
    import android.os.Bundle
    import android.view.LayoutInflater
    import android.view.View
    import android.view.ViewGroup
    import android.widget.TextView
    import androidx.core.content.ContextCompat
    import androidx.core.content.ContextCompat.getColor
    import androidx.core.view.setPadding
    import androidx.fragment.app.Fragment
    import com.airiche.nixplay.FragMent.Adpate.FramentManagerAdapter
    import com.airiche.nixplay.MainApplication
    
    import com.airiche.nixplay.R
    import com.google.android.material.tabs.TabLayout
    import kotlinx.android.synthetic.main.fragment_photo.view.*
    import java.util.ArrayList
    
    
    class PhotoFragment : Fragment() {
        private var mFramentManagerAdapter: FramentManagerAdapter? = null
    
        override fun onCreateView(inflater: LayoutInflater,
                                  container: ViewGroup?, savedInstanceState: Bundle?): View? {
            var view = inflater.inflate(R.layout.fragment_photo, container, false)
    
            Initialization(view)
            return view
        }
    
        public fun Initialization(view: View){
            //这个适配器里面主要的是有两个碎片,所对应的TabLayout的两个标题
            mFramentManagerAdapter = FramentManagerAdapter(
                activity!!.getSupportFragmentManager() , activity!!
            )
            
            //存储两个标题 TabLayout的标题
            val strings = ArrayList<String>()
            strings.add("PLAYLISTS")
            strings.add("ALBUMS")
    
            mFramentManagerAdapter!!.setData(strings)
            //ViewPager
            view.Pnoto_vp.setAdapter(mFramentManagerAdapter)
            //这个地方就是关联Viewpager与TabLayout的关键 这个主要是滑动的时候去切换标题
            view.Pnoto_Table.setupWithViewPager(view.Pnoto_vp)
            //同时关联两个碎片 那么点击两个TabLayout的标题的时候切换碎片
            view.Pnoto_Table.setTabsFromPagerAdapter(mFramentManagerAdapter)
        }
    
    }
    

    接下来我们就看一下这个适配器FramentManagerAdapter:

    package com.airiche.nixplay.FragMent.Adpate
    
    import android.content.Context
    import androidx.fragment.app.Fragment
    import androidx.fragment.app.FragmentManager
    import com.airiche.nixplay.Adpate.CustomFragmentPagerAdapter
    import com.airiche.nixplay.FragMent.fragment.PnotoAlbumsFragment
    import com.airiche.nixplay.FragMent.fragment.PnotoPlaylistsFragment
    
    /**
     * Created by yingmuliang on 2019/11/21.
     * 这个碎片主要是用作ViewPager
     */
    class FramentManagerAdapter(fm: FragmentManager, context: Context) : CustomFragmentPagerAdapter<String>(fm, context) {
    
        override fun getItem(position: Int): Fragment {
            return if (position == 0) {
                 //这是你的碎片对象之一 
                PnotoPlaylistsFragment.newInstance()
            } else {
                 //这是你的碎片对象之一
                PnotoAlbumsFragment.newInstance()
            }
        }
    
        override fun getPageTitle(position: Int): CharSequence? {
            return getData(position)
        }
    
    
    }

    再来看一下这个公共的适配器CustomFragmentPagerAdapter,它继承FragmentPagerAdapter 这个适配器

    package com.airiche.nixplay.Adpate;
    
    import android.content.Context;
    import androidx.fragment.app.FragmentManager;
    import androidx.fragment.app.FragmentPagerAdapter;
    
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * Created by yingmuliang on 2019/11/21.
     */
    public abstract class CustomFragmentPagerAdapter<T> extends FragmentPagerAdapter {
    
        protected final List<T> datas = new ArrayList<T>();
        protected final Context context;
        protected T data;
    
        public CustomFragmentPagerAdapter(FragmentManager fm, Context context) {
            super(fm);
            this.context = context;
        }
    
        @Override
        public int getCount() {
            return datas.size();
        }
    
        public T getData(int position) {
            return datas.get(position);
        }
    
        public void setData(List<T> data) {
            if (data != null && data.size() > 0) {
                datas.clear();
                datas.addAll(data);
                notifyDataSetChanged();
            }
        }
    
        public void clear() {
            datas.clear();
        }
    
        public void clearAndNotify() {
            datas.clear();
            notifyDataSetChanged();
        }
    
    }
    

    ViewPager所需的两个碎片,刚刚的适配器里面对应的两个碎片

    package com.airiche.nixplay.FragMent.fragment
    
    import android.os.Bundle
    import androidx.fragment.app.Fragment
    import android.view.LayoutInflater
    import android.view.View
    import android.view.ViewGroup
    
    import com.airiche.nixplay.R
    
    class PnotoAlbumsFragment : Fragment() {
    
        override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            // Inflate the layout for this fragment
            return inflater.inflate(R.layout.fragment_pnoto_albums, container, false)
        }
    
        companion object {
            fun newInstance(): PnotoAlbumsFragment {
                val args = Bundle()
                val fragment = PnotoAlbumsFragment()
                fragment.setArguments(args)
                return fragment
            }
        }
    }
    

     

    package com.airiche.nixplay.FragMent.fragment
    
    
    import android.content.Intent
    import android.os.Bundle
    import androidx.fragment.app.Fragment
    import android.view.LayoutInflater
    import android.view.View
    import android.view.ViewGroup
    import com.airiche.nixplay.Activity.MainInterfaceActivity
    import com.airiche.nixplay.MainApplication
    
    import com.airiche.nixplay.R
    
    class PnotoPlaylistsFragment : Fragment() {
    
    
        override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            // Inflate the layout for this fragment
            return inflater.inflate(R.layout.fragment_pnoto_playlists, container, false)
        }
    
        companion object {
            fun newInstance(): PnotoPlaylistsFragment {
                val args = Bundle()
                val fragment = PnotoPlaylistsFragment()
                fragment.setArguments(args)
                return fragment
            }
        }
    
    }
    

    这两碎片布局我就懒得上布局了!,上面基本就把代码介绍完了!

    扩展:TableLayout中线条改变,以及文字改变

    我们先来改变线条,通过查找api我没找到有直接设置代码设置的,但是我找到个神奇的东西,先在Tablelayout的布局中设置

    app:tabIndicatorHeight="0dp"

     再创建一个tab_selector.xml样式:

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:drawable="@drawable/tab_selected" android:state_selected="true" />
        <item android:drawable="@color/design_fab_shadow_end_color" />
    </selector>
    tab_selected.xml:
    <?xml version="1.0" encoding="UTF-8"?>
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
        <!-- 整个背景色-->
        <item>
            <shape>
                <solid android:color="@color/design_fab_shadow_end_color" />
            </shape>
        </item>
        <!-- 底部圆角,参数是固定的 -->
        <item
                android:width="100dp"
                android:height="2dp"
                android:gravity="bottom|center_horizontal">
            <shape>
                <solid android:color="@color/photo_table_color" />/>
            </shape>
        </item>
    </layer-list>
    

    使用:

    app:tabBackground="@drawable/tab_selector"

    整体布局:

      <com.google.android.material.tabs.TabLayout
                android:id="@+id/Pnoto_Table"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@null"
                app:tabIndicatorHeight="0dp"
                app:tabBackground="@drawable/tab_selector"/>

     这就是那根标签线的设置了,我们再来看标签文字的设置:

    它有两种状态,选中以及未选中:直接上代码吧,不墨迹了:

        <com.google.android.material.tabs.TabLayout
                android:id="@+id/Pnoto_Table"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@null"
                app:tabIndicatorHeight="0dp"
                app:tabBackground="@drawable/tab_selector"
                app:tabSelectedTextColor="@color/Table_enble_TextColor" 
                app:tabTextColor="@color/tabTextColor"/>
    
     app:tabSelectedTextColor="@color/Table_enble_TextColor" //选中颜色
     app:tabTextColor="@color/tabTextColor"  //未选中颜色
    
    //扩展: 去掉点击阴影app:tabRippleColor = "@android:color/transparent" 或者你设置成自己想要的点击颜色

     

    emmmmm.....大概就这么些了,有什么问题直接找我就好了,邮箱地址:1627000323@qq.com 

     

    展开全文
  • fragment有诸多的优势有点,但也存在着不足和一些隐藏的问题,以下是在开发过程中碰到的fragment各类问题,做以总结和分析: 目录: * 1.fragment出栈以及同时多个出栈会导致的问题 * 2.Fragment回退监听问题 * ...
  • Navigation与Fragment使用注意要点

    千次阅读 2020-01-17 20:12:44
    一、底部的三个导航按钮,注意代码的ID要和导航文件Navigation里面的Fragment的id一致,不然那3个按钮点击没反应,或者Fragment切换了,底部导航按钮没更新状态。如图 ...
  • thymeleaf中的fragment使用

    万次阅读 2018-05-03 17:29:18
    https://blog.csdn.net/whatlookingfor/article/details/78321451fragment介绍fragment类似于JSP的...fragment使用定义fragment所有的fragment可以写在一个文件里面,也可以单独存在,例如&lt;footer th:fragme...
  • Fragment中RecyclerView的使用解析,以及监听事件处理,对应博客解释地址:https://blog.csdn.net/zhuchenglin830/article/details/82286109
  • Fragment使用场景

    千次阅读 2014-11-20 22:45:31
    1、Fragment使用场景 针对大屏显示设备而设计,可以实现类似于Html的菜单 + 主显示区域 这种效果 2、Fragment使用(版本修改) Android3.0之后的新特性: 创建: 1、创建Fragment类 Fragment内部显示的是一...
  • 自从Android3.0引入了Fragment之后,使用Activity去嵌套一些Fragment的做法也变得更加流行,这确实是Fragment带来的一些优点,比如说:Fragment可以使你能够将activity分离成多个可重用的组件,每个都有它自己的生命...
  • 就像上面两幅图片一样,当我们点击下面的导航栏按钮时,APP会切换Fragment,且会更改标题栏和状态栏的颜色。这篇文章主要便是记录该效果的实现过程。 activity的布局如下 &lt;?xml version="1.0" ...
  • Android解决Fragment使用replace方法重叠问题今天在使用Fragment进行replace切换的时候,发现居然没反应: 布局是这样的 xmlns:tools="http://schemas.android.co
  • Fragment使用动画问题

    2014-09-01 10:36:39
    但是在使用 mFrgTransaction .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);来给fragment添加动画后,如果快速点击button,则会发现2个fragment都会hide掉,如果不加动画则没有这个问题。
  • 1. 前言 这几天接到一个坑的任务,领导要我做一... 在Android中横屏显示,并且分页,自然而然就想到了Fragment,于是抽空学习一下Fragment的用法,并且在使用过程中遇到findFragmentById 返回为null。 今天遇到这...
  • Toolbar 是谷歌推出在 android 5.0 版本以后取代 ...如果你的app 是在activity之间来回跳转的话,使用Toolbar作为一个导航栏,那么是很简单就能实现的 Manifest.xml配置为 <manifest xmlns:android="http://schemas
  • Fragment与Activity使用Handler进行交互

    千次下载 热门讨论 2014-06-27 12:26:19
    这里简单介绍了Fragment和Activity使用Handler方式进行交互。
  • 嵌套Fragment使用及常见错误 嵌套Fragments (Nested Fragments), 是在Fragment内部又添加Fragment. 使用时, 主要要依靠宿主Fragment的 getChildFragmentManager() 来获取FragmentManger. 虽然看起来和在...
  • fragment 使用过程中单例模式引发的问题 在实际项目开发中,遇到一个这样的问题。 activity结构如下 实际需要实现功能为:在收到一个网络推送的消息后,发出一个notification,在通知栏出现,点击...
  • 广播注册,可以写在Activity(onCreate),也可以写在Fragment(onActivityCreated)里。 LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(getActivity()); IntentFilter intentFilter
  • Fragment使用出现空白页的解决方法

    千次阅读 2016-07-19 14:48:45
    所以在我们的fragment中写上这样的代码: public class AndroidFragment extends Fragment { private View view; @Nullable @Override public View onCreateView (LayoutInflater ...
  • viewPager和Fragment一起使用的时候需要注意Fragment的状态保存和Fragment的数据预加载问题。 上一篇文章我眼中的Fragment基类的写法通过创建Fragment基类解决了Fragment和ViewPager一起使用时的数据预加载问题。...
  • Fragment使用findFragmentById返回null

    万次阅读 2014-09-29 21:53:27
    今天换新版本的ADT之后默认建立工程引入Fragment,之前对Fragment没有做过了解。 想学习一下,在Activity的onCreate方法中无论怎么获取Fragment都是null,代码如下: protected void onCreate(Bundle ...
  • Fragment使用详解

    万次阅读 2015-12-23 09:28:20
    fragment是Google在3.0版本中推出的新功能,现在已经加入到V4包中,如果要使用V4兼容包中的Fragment需要将Activity换成FragmentActivity,调用的getSupportFragmentManager获取FragmentManager而不是...
  • Fragment嵌套Fragment实现多tab页面

    千次下载 热门讨论 2016-03-16 08:04:09
    原来做的一个练手的项目,里面主要是Fragment的嵌套,需要的朋友可以看下,如果遇到不能运行的状况可酌量删除些代码。
  • 使用fragment实现仿微信界面

    热门讨论 2015-12-15 09:59:13
    使用Fragment实现仿微信界面的实现
  • 1、初始化时,VideoView调用setBackgroundColor(颜色) 2、开始播放时,VideoView调用setBackgroundColor(0)
  • android fragment 使用name关联Fragment

    千次阅读 2018-12-14 15:57:01
    Fragment 可以说是Android 的 第五大组件了 我们通常用法是 给Framelayout 设置ID ,然后到代码里去进行add 或者replace操作,让Fragment去处理数据 除此之外 还有一种形式就是 在布局里加入该fragment的全类名 ...
  • Fragment使用带参数的构造函数,有时候会报如下错误: Unable to instantiate fragment make sure class name exists, is public, and has an empty constructor that is public 所以,Android 官方是不推荐Fragment...
  • Android Fragment 使用详解和源码分析

    千次阅读 2017-06-11 17:06:29
    1,App进程被系统杀死后用户重新进入APP的问题 2,Activity向Fragment中传递参数的问题 3,Fragment的状态保存、Fragment栈 4,Fragment生命周期

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 245,757
精华内容 98,302
关键字:

fragment使用