我有带导航抽屉的android应用程序,其中包含视频,图形,共享等菜单。每个菜单链接到片段。在Graphs中我想显示制表符布局但是在为每个制表符实现带有片段的ViewPager时它会引发异常MainActivity必须实现OnFragmentInteractionListener。 这是logcat错误
10-27 00:12:43.560 31450-31450 / com.example.dp.facialemotionalyzer I / AppCompatViewInflater:app:主题现已弃用。请转到 使用android:theme代替。 10-27 00:12:43.626 31450-31450 / com.example.dp.facialemotionalyzer D / AndroidRuntime: 关闭VM
java.lang.RuntimeException:com.example.dp.facialemotionalyzer.activity.MainActivity@a8ce577必须 实现OnFragmentInteractionListener 在 com.example.dp.facialemotionalyzer.fragment.HappinessFragment.onAttach(HappinessFragment.java:77) 在 android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1043) 在 android.support.v4.app.BackStackRecord.setLastIn(BackStackRecord.java:838) 在 android.support.v4.app.BackStackRecord.calculateFragments(BackStackRecord.java:861) 在 android.support.v4.app.BackStackRecord.run(BackStackRecord.java:719) 在 android.support.v4.app.FragmentManagerImpl.execSingleAction(FragmentManager.java:1638) 在 android.support.v4.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:679) 在 android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:143) 在android.support.v4.view.ViewPager.populate(ViewPager.java:1240) 在android.support.v4.view.ViewPager.populate(ViewPager.java:1088) 在android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1614) 在android.view.View.measure(View.java:18809) 在android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5954) 在 android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1465) 在android.widget.LinearLayout.measureVertical(LinearLayout.java:748) 在android.widget.LinearLayout.onMeasure(LinearLayout.java:630) 在 android.support.design.widget.AppBarLayout.onMeasure(AppBarLayout.java:218) 在android.view.View.measure(View.java:18809) 在android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5954) 在android.widget.FrameLayout.onMeasure(FrameLayout.java:194) 在android.view.View.measure(View.java:18809) 在android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5954) 在 android.support.design.widget.CoordinatorLayout.onMeasureChild(CoordinatorLayout.java:700) 在 android.support.design.widget.HeaderScrollingViewBehavior.onMeasureChild(HeaderScrollingViewBehavior.java:90) 在 android.support.design.widget.AppBarLayout $ ScrollingViewBehavior.onMeasureChild(AppBarLayout.java:1364) 在 android.support.design.widget.CoordinatorLayout.onMeasure(CoordinatorLayout.java:765) 在android.view.View.measure(View.java:18809) 在 android.support.v4.widget.DrawerLayout.onMeasure(DrawerLayout.java:1085) 在android.view.View.measure(View.java:18809) 在android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5954) 在android.widget.FrameLayout.onMeasure(FrameLayout.java:194) 在 android.support.v7.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:135) 在android.view.View.measure(View.java:18809) 在android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5954) 在 android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1465) 在android.widget.LinearLayout.measureVertical(LinearLayout.java:748) 在android.widget.LinearLayout.onMeasure(LinearLayout.java:630) 在android.view.View.measure(View.java:18809) 在android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5954) 在android.widget.FrameLayout.onMeasure(FrameLayout.java:194) 在android.view.View.measure(View.java:18809) 在android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5954) 在 android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1465) 在android.widget.LinearLayout.measureVertical(LinearLayout.java:748) 在android.widget.LinearLayout.onMeasure(LinearLayout.java:630) 在android.view.View.measure(View.java:18809) 在android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5954) 在android.widget.FrameLayout.onMeasure(FrameLayout.java:194) 在 com.android.internal.policy.PhoneWindow $ DecorView.onMeasure(PhoneWindow.java:2643) 在android.view.View.measure(View.java:18809) 在android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2112) 在android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1228) 在android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1464) 在android.view.ViewRootImpl.d
这是GraphFragment.java
package com.example.dp.facialemotionalyzer.fragment;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.example.dp.facialemotionalyzer.R;
import com.example.dp.facialemotionalyzer.other.TabsPagerAdapter;
/**
* A simple {@link Fragment} subclass.
* Activities that contain this fragment must implement the
* {@link GraphFragment.OnFragmentInteractionListener} interface
* to handle interaction events.
* Use the {@link GraphFragment newInstance} factory method to
* create an instance of this fragment.
*/
public class GraphFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
private OnFragmentInteractionListener mListener;
private TabsPagerAdapter mAdapter;
private String[] tabs = {"Happiness", "Anger", "Surprice",
"Neutral", "Sadness"};
public GraphFragment() {
// Required empty public constructor
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View inflatedView = inflater.inflate(R.layout.fragment_graph, container, false);
TabLayout tabLayout = (TabLayout) inflatedView.findViewById(R.id.tabs);
final ViewPager viewPager = (ViewPager) inflatedView.findViewById(R.id.viewpager);
mAdapter = new TabsPagerAdapter(getChildFragmentManager());
viewPager.setAdapter(mAdapter);
for (String tab_name : tabs) {
tabLayout.addTab(tabLayout.newTab().setText(tab_name));
}
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
return inflatedView;
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
}
这是TabsPagerAdapter.java
package com.example.dp.facialemotionalyzer.other;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import com.example.dp.facialemotionalyzer.fragment.AngerFragment;
import com.example.dp.facialemotionalyzer.fragment.HappinessFragment;
public class TabsPagerAdapter extends FragmentPagerAdapter {
public TabsPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int index) {
switch (index) {
case 0:
// Top Rated fragment activity
return new HappinessFragment();
case 1:
// Games fragment activity
return new AngerFragment();
case 2:
// Movies fragment activity
return new HappinessFragment();
case 3:
// Movies fragment activity
return new AngerFragment();
case 4:
// Movies fragment activity
return new HappinessFragment();
case 5:
// Movies fragment activity
return new AngerFragment();
}
return null;
}
@Override
public int getCount() {
// get item count - equal to number of tabs
return 6;
}
}
这是MainActivity.java
package com.example.dp.facialemotionalyzer.activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Handler;
import android.support.design.widget.NavigationView;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v4.view.GravityCompat;
import android.os.Bundle;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import android.support.v7.widget.Toolbar;
import com.example.dp.facialemotionalyzer.R;
import com.example.dp.facialemotionalyzer.fragment.GraphFragment;
import com.example.dp.facialemotionalyzer.fragment.HomeFragment;
import com.example.dp.facialemotionalyzer.fragment.VideoFragment;
public class MainActivity extends AppCompatActivity implements
GraphFragment.OnFragmentInteractionListener{
private NavigationView navigationView;
private DrawerLayout drawer;
private View navHeader;
private ImageView imgNavHeaderBg, imgProfile;
private TextView txtName, txtWebsite;
private Toolbar toolbar;
private FloatingActionButton fab;
private static final String TAG_HOME = "home";
private static final String TAG_VIDEO = "video";
private static final String TAG_GRAPH = "graph";
private static String CURRENT_TAG = TAG_HOME;
private String[] activityTitles;
private boolean shouldLoadHomeFragOnBackPress = true;
private Handler mHandler;
private int navItemIndex = 0;
static final int REQUEST_VIDEO_CAPTURE = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
mHandler = new Handler();
drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
navigationView = (NavigationView) findViewById(R.id.nav_view);
activityTitles = getResources().getStringArray(R.array.nav_item_activity_titles);
fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
}
});
setUpNavigationView();
if (savedInstanceState == null && checkCameraHardware(getApplicationContext())) {
navItemIndex = 0;
CURRENT_TAG = TAG_HOME;
loadHomeFragment();
}
}
private void loadHomeFragment(){
selectNavMenu();
setToolbarTitle();
if(getSupportFragmentManager().findFragmentByTag(CURRENT_TAG) != null){
drawer.closeDrawers();
toggleFab();
return;
}
Runnable mPendingRunnable = new Runnable() {
@Override
public void run() {
Fragment fragment = getHomeFragment();
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.setCustomAnimations(android.R.anim.fade_in,
android.R.anim.fade_out);
fragmentTransaction.replace(R.id.frame, fragment, CURRENT_TAG);
fragmentTransaction.commitAllowingStateLoss();
}
};
if(mPendingRunnable != null){
mHandler.post(mPendingRunnable);
}
toggleFab();
drawer.closeDrawers();
invalidateOptionsMenu();
}
private Fragment getHomeFragment(){
switch (navItemIndex){
case 0:
HomeFragment homeFragment = new HomeFragment();
return homeFragment;
case 1:
VideoFragment videoFragment = new VideoFragment();
return videoFragment;
case 2:
GraphFragment graphFragment = new GraphFragment();
return graphFragment;
default:
return new HomeFragment();
}
}
private void setToolbarTitle(){
getSupportActionBar().setTitle(activityTitles[navItemIndex]);
}
private void selectNavMenu(){
navigationView.getMenu().getItem(navItemIndex).setChecked(true);
}
private void setUpNavigationView() {
//Setting Navigation View Item Selected Listener to handle the item click of the navigation menu
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
// This method will trigger on item Click of navigation menu
@Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
//Check to see which item was being clicked and perform appropriate action
switch (menuItem.getItemId()) {
//Replacing the main content with ContentFragment Which is our Inbox View;
case R.id.nav_home:
navItemIndex = 0;
CURRENT_TAG = TAG_HOME;
break;
case R.id.nav_video:
navItemIndex = 1;
CURRENT_TAG = TAG_VIDEO;
break;
case R.id.nav_graph:
navItemIndex = 2;
CURRENT_TAG = TAG_GRAPH;
break;
default:
navItemIndex = 0;
}
//Checking if the item is in checked state or not, if not make it in checked state
if (menuItem.isChecked()) {
menuItem.setChecked(false);
} else {
menuItem.setChecked(true);
}
menuItem.setChecked(true);
loadHomeFragment();
return true;
}
});
ActionBarDrawerToggle actionBarDrawerToggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.openDrawer, R.string.closeDrawer) {
@Override
public void onDrawerClosed(View drawerView) {
// Code here will be triggered once the drawer closes as we dont want anything to happen so we leave this blank
super.onDrawerClosed(drawerView);
}
@Override
public void onDrawerOpened(View drawerView) {
// Code here will be triggered once the drawer open as we dont want anything to happen so we leave this blank
super.onDrawerOpened(drawerView);
}
};
//Setting the actionbarToggle to drawer layout
drawer.setDrawerListener(actionBarDrawerToggle);
//calling sync state is necessary or else your hamburger icon wont show up
actionBarDrawerToggle.syncState();
}
@Override
public void onBackPressed() {
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawers();
return;
}
// This code loads home fragment when back key is pressed
// when user is in other fragment than home
if (shouldLoadHomeFragOnBackPress) {
// checking if user is on other navigation menu
// rather than home
if (navItemIndex != 0) {
navItemIndex = 0;
CURRENT_TAG = TAG_HOME;
loadHomeFragment();
return;
}
}
super.onBackPressed();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
// show menu only when home fragment is selected
if (navItemIndex == 0) {
getMenuInflater().inflate(R.menu.main, menu);
}
// when fragment is notifications, load the menu created for notifications
if (navItemIndex == 3) {
getMenuInflater().inflate(R.menu.notifications, menu);
}
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_logout) {
Toast.makeText(getApplicationContext(), "Logout user!", Toast.LENGTH_LONG).show();
return true;
}
// user is in notifications fragment
// and selected 'Mark all as Read'
if (id == R.id.action_mark_all_read) {
Toast.makeText(getApplicationContext(), "All notifications marked as read!", Toast.LENGTH_LONG).show();
}
// user is in notifications fragment
// and selected 'Clear All'
if (id == R.id.action_clear_notifications) {
Toast.makeText(getApplicationContext(), "Clear all notifications!", Toast.LENGTH_LONG).show();
}
return super.onOptionsItemSelected(item);
}
// show or hide the fab
private void toggleFab() {
if (navItemIndex == 0)
fab.show();
else
fab.hide();
}
private boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
// this device has a camera
return true;
} else {
// no camera on this device
return false;
}
}
public void onFragmentInteraction(Uri uri) {
}
}