简体   繁体   English

从片段访问和使用活动导航抽屉

[英]Access and use activity nav drawer from fragment

Is there a way possible to access the navigation drawer I created in my activity from my fragment? 有没有办法从片段中访问我在活动中创建的导航抽屉? I also want to be able to use the back pressed feature. 我还希望能够使用后按功能。 My activity is launched on handsets and my fragment is launched on tablets. 我的活动在手机上启动,而我的片段在平板电脑上启动。

activity class 活动课

public class BakerlooHDNActivity extends AppCompatActivity {

    private Drawer result = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bakerloo_hdn);


        final String actionBarColor = "#B36305";

        Toolbar mToolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(mToolbar);

        if(getSupportActionBar()!=null) {
            getSupportActionBar().setDisplayHomeAsUpEnabled(true);
            getSupportActionBar().setDisplayShowHomeEnabled(false);
            getSupportActionBar().setTitle(Html.fromHtml("<font color='#FFFFFF'>" + getResources().getString(R.string.hdn) + "</font>"));
            getSupportActionBar().setSubtitle(Html.fromHtml("<font color='#FFFFFF'>" + getResources().getString(R.string.zone_3) + "</font>"));

            final Drawable upArrow = ContextCompat.getDrawable(this, R.drawable.abc_ic_ab_back_mtrl_am_alpha);
            upArrow.setColorFilter(getResources().getColor(R.color.white), PorterDuff.Mode.SRC_ATOP);
            getSupportActionBar().setHomeAsUpIndicator(upArrow);
        }

        // start of navigation drawer
        headerResult = new AccountHeaderBuilder()
                .withActivity(getActivity())
                .withCompactStyle(true)
                .withHeaderBackground(R.color.bakerloo)
                .withProfileImagesVisible(false)
                .withTextColor(Color.parseColor("#FFFFFF"))
                .withSelectionListEnabled(false)

                .addProfiles(
                        new ProfileDrawerItem().withName(getString(R.string.hdn)).withEmail(getString(R.string.hello_world))
                )
                .build();

        result = new DrawerBuilder()
                .withActivity(getActivity())
                .withAccountHeader(headerResult)
                .withTranslucentStatusBar(false)
                .withActionBarDrawerToggle(false)
                .addDrawerItems(
                        new PrimaryDrawerItem().withName(R.string.hello_world).withIdentifier(1).withCheckable(false)
                )
                .build();
        // end of navigation drawer
    }


    @Override
    public void onBackPressed() {
        if (result.isDrawerOpen()) {
            result.closeDrawer();
        } else {
            super.onBackPressed();
        }
        LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent("BACKPRESSED_TAG"));
    }
}

fragment class 片段类

public class FragmentBakerlooHDN extends android.support.v4.app.Fragment {

    public FragmentBakerlooHDN() {
        // Required empty constructor
    }

    BroadcastReceiver onNotice = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
             result.closeDrawer();
        }
    };

    private AccountHeader headerResult = null;
    private Drawer result = null;

    private boolean mTwoPane;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        LocalBroadcastManager.getInstance(getActivity()).registerReceiver(onNotice, new IntentFilter("BACKPRESSED_TAG"));

        super.onCreate(savedInstanceState);
    }

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_bakerloo_hdn, container, false);

        super.onCreate(savedInstanceState);
        return v;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        View v = getView();

        super.onActivityCreated(savedInstanceState);
    }
}

I would never have a fragment access the drawer directly. 我永远不会有碎片直接访问抽屉。 Instead I would call the Activity via a callback method from the Fragment and then access the drawer. 相反,我将通过Fragment中的回调方法调用Activity,然后访问抽屉。

After re-reading your question I suggest the following: 重新阅读您的问题后,我提出以下建议:

  • You Activity is already closing the drawer so no need to do it again in the fragment. 您的Activity已经关闭了抽屉,因此无需在片段中再次进行。
  • You should have 2 fragments, one for tablet and one for phone 您应该有2个片段,一个用于平板电脑,一个用于手机

If you still need to communicate with the Fragment do this: 如果您仍然需要与Fragment通信,请执行以下操作:

public void onBackPressed() {
    if (result.isDrawerOpen()) {
        result.closeDrawer();
        getSupportFragmentManager().findFragmentByTag("FRAGMENT_TAG").doSomething();
    } else {
        super.onBackPressed();
    }
}

In your Fragment add this: 在您的片段中添加以下内容:

public void doSomething() {
    // Do it here
}

My suggestion is basically to create a public method in the fragment. 我的建议基本上是在片段中创建一个公共方法。 And the activity calls the public method passing the drawer object. 活动调用传递抽屉对象的公共方法。 Simple really. 真的很简单。 This has the effect of passing the drawer by reference. 这具有通过引用传递抽屉的效果。

Code suggestion. 代码建议。 In BakerlooHDNActivity class: 在BakerlooHDNActivity类中:

AccountHeader headerResult;

if (savedInstanceState == null) {
   FragmentBakerlooHDN myFragment = new FragmentBakerlooHDN();
   myFragment.setDrawer(headerResult);
}

In FragmentBakerlooHDN class: 在FragmentBakerlooHDN类中:

private AccountHeader myDrawer;

public void setDrawer(final AccountHeader drawer) {
   this.myDrawer = drawer;
}

Notes: 笔记:

  • You may pass the object headerResult onto FragmentBakerlooHDN constructor but that is normally not done due to fragment lifecycle, I believe. 您可以将对象headerResult传递给FragmentBakerlooHDN构造函数,但是由于片段的生命周期,我通常不会这样做。
  • For now, you may call the public setDrawer immediately after creating new instance of the fragment. 现在,您可以在创建片段的新实例后立即调用public setDrawer。 But there may be issues with UI and fragment lifecycle. 但是,UI和片段生命周期可能存在问题。
  • If you modify contents of the drawer, either do it in activity or fragment, not both. 如果您修改抽屉的内容,请在活动中或在片段中进行,而不要同时进行。 Again, this solution is passing the drawer object by reference. 同样,此解决方案是通过引用传递抽屉对象。 So it is powerful enough to be dangerous. 因此它足够强大以至于危险。 Another method would be to use the technique of using callback/listener like what Sweder has said. 另一种方法是使用像Sweder所说的那样使用回调/侦听器的技术。
  • Object myDrawer is declared as AccountHeader instead of AccountHeaderBuilder. 对象myDrawer声明为AccountHeader而不是AccountHeaderBuilder。

My suggestion is use method onBackPressed in Activity. 我的建议是在Activity中使用onBackPressed方法。 I updated source code of my tutorial about NavigationDrawer ( https://github.com/AlexZhukovich/NavigationDrawerTutorial ). 我更新了有关NavigationDrawer的教程的源代码( https://github.com/AlexZhukovich/NavigationDrawerTutorial )。 I hope it's help you. 希望对您有帮助。 I used NavigationDrawer from com.android.support:design in this tutorial. 在本教程中,我使用了来自com.android.support:design的NavigationDrawer。

    @Override
    public void onBackPressed() {
        if (mDrawerLayout.isDrawerOpen(mNavigationView))
            mDrawerLayout.closeDrawers();
        else
            super.onBackPressed();
    }

For me it's work in tablet and phone. 对我来说,它适用于平板电脑和手机。 (Nexus devices). (Nexus设备)。

I created simple activity with fragment for you. 我为您创建了带有片段的简单活动。 This activity shows 2 fragment, but after click to back, delete second fragment. 此活动显示2个片段,但是单击返回后,删除第二个片段。

    public class TestActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test);

        getSupportFragmentManager().beginTransaction().add(R.id.container, new DummyFragment(), "TEST").commit();
        getSupportFragmentManager().beginTransaction().add(R.id.container2, new DummyFragment(), "TEST2").commit();
    }

    @Override
    public void onBackPressed() {
        if (getSupportFragmentManager().findFragmentByTag("TEST2") != null && getSupportFragmentManager().findFragmentByTag("TEST2").isVisible()) {
            getSupportFragmentManager().beginTransaction().remove(getSupportFragmentManager().findFragmentByTag("TEST2")).commit();
        } else {
            super.onBackPressed();
        }
    }

    private class DummyFragment extends Fragment {

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View view = inflater.inflate(R.layout.fragment_test, container, false);
            return view;
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM