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

问题描述:

有没有办法从我的片段访问我在我的活动中创建的导航抽屉?我也希望能够使用后退按下功能。我的活动在手机上启动,我的片段在平板电脑上启动。从片段访问和使用活动导航抽屉

活动类

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")); 
    } 
} 

片段类

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); 
    } 
} 
+0

你的片段是FragmentBakerlooHDN。电话在哪里?我期望从活动。 –

+0

为什么在Activity和Fragment中实例化类AccountHeaderBuilder?那是故意的设计吗? –

+0

@TheOriginalAndroid道歉,这不应该在那里 - 它已被删除。 – MacaronLover

我永远不会直接有一个片段访问抽屉。相反,我会通过Fragment中的回调方法调用Activity,然后访问抽屉。

重新阅读您的问题后,我建议如下:

  • 您的活动已经关闭抽屉所以没必要在片段做一遍。
  • 你应该有2个片段,一个是平板电脑和一个手机

如果您仍需要与该片沟通做到这一点:

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

在您的片段补充一点:

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

需要在片段代码中替换“//在此处执行”?我的活动和片段有自己的xml布局(如我发布的代码所示)'activity_bakerloo_hdn.xml'和'fragment_bakerloo_hdn.xml'。 – MacaronLover

+0

取决于你想要做的事情。你的原始代码说'//在按下活动时做某事' –

+0

我想要导航抽屉关闭 – MacaronLover

我的建议基本上是在片段中创建一个公共方法。活动调用传递抽屉对象的公共方法。真的很简单。这具有通过引用传递抽屉的效果。

代码建议。 在BakerlooHDNActivity类:

AccountHeader headerResult; 

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

在FragmentBakerlooHDN类:

private AccountHeader myDrawer; 

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

注:

  • 您可以传递对象headerResult到FragmentBakerlooHDN构造函数,但认为是由于片段通常不会做生命周期,我相信。
  • 现在,您可以在创建片段的新实例后立即调用公共setDrawer。但是UI和片段生命周期可能存在问题。
  • 如果修改抽屉的内容,请在活动或片段中进行,而不是在两者中进行。同样,这个解决方案是通过引用传递抽屉对象。所以它是足够强大的危险。另一种方法是使用像Sweder所说的使用回调/侦听器的技术。
  • 对象myDrawer被声明为AccountHeader而不是AccountHeaderBuilder。
+0

@MacaronLover,我在编辑部分添加了评论。你的问题是一个简单的编译错误。它只需要相同的类类型。我认为将headerResult声明为AccountHeader是不正确的,它可能不是有意的。你的代码是“headerResult = new AccountHeaderBuilder ...”所以我认为我的代码建议是正确的。 –

+0

@MacaronLover,这里的教训是,你要么改变Activity中的headerResult的声明,要么改变setDrawer的声明(最终的AccountHeaderBuilder抽屉)。您可以更改抽屉的参数类型和类对象myDrawer。 –

+0

使用该代码后无法使用,请查看以下最新屏幕截图:[截图1](http://picpaste.com/Screen_Shot_2015-08-13_at_18.09.34-UPhC2xKV.png)和[截图2](http:/ /picpaste.com/Screen_Shot_2015-08-13_at_18.10.09-dR0hzChN.png) – MacaronLover

我的建议是使用方法onBackPressed在Activity中。我更新了关于NavigationDrawer的教程的源代码(https://github.com/AlexZhukovich/NavigationDrawerTutorial)。我希望这对你有所帮助。我在本教程中使用了com.android.support:design中的NavigationDrawer。

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

对我来说,它是在平板电脑和手机上工作。 (Nexus设备)。

我为你创建了带有片段的简单活动。此活动显示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; 
     } 
    } 
} 
+0

这已经在我的活动中了。问题在于如何处理平板电脑,因为它会打开一个片段,而不是一个活动。 – MacaronLover

+0

尝试在添加/替换片段期间添加标签,因为它更好地使用 getTextField()。你可以搜索片段,并做你需要的 'if(getSupportFragmentManager()。findFragmentByTag(“FRAGMENT_TAG”)!= null){fragment.close(); }' –

+0

这需要去哪里? – MacaronLover