【问题标题】:CoordinatorLayout replacing FragmentsCoordinatorLayout 替换 Fragments
【发布时间】:2015-07-11 12:06:36
【问题描述】:

我在替换 CoordinatorLayout 容器中的片段时遇到问题。

我有一个带有 CoordinatorLayout、AppBarLayout 和 CollapsingToolbarLayout 的类。

当 Activity 启动时,会添加第一个 Fragment 以使用 RecyclerView 显示一些类别。 如果选择了任何类别,则此 Fragment 将替换为 Product Fragment,它是产品列表,也使用 RecyclerView。

问题是当我选择一个类别时,第二个片段显示为空,列表未按应有的方式显示。

如果我使用 ListView 而不是 CoordinatorLayout 一切正常。

如果我在第二个 Fragment 中使用 add,两个列表会重叠。

对这个问题有帮助吗?

这是活动的 XML:

<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:id="@+id/container">


<android.support.design.widget.AppBarLayout
    android:id="@+id/appbarLayout"
    android:layout_height="192dp"
    android:layout_width="match_parent">
    <android.support.design.widget.CollapsingToolbarLayout
        android:id="@+id/ctlLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_scrollFlags="scroll|exitUntilCollapsed"
        app:contentScrim="?attr/colorPrimary"
        app:layout_collapseMode="parallax">
        <android.support.v7.widget.Toolbar
            android:id="@+id/appbar"
            android:layout_height="?attr/actionBarSize"
            android:layout_width="match_parent"
            app:layout_scrollFlags="scroll|enterAlways"
            app:layout_collapseMode="pin"/>
    </android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>

片段的 XML 文件,仅包含 RView:

<android.support.v7.widget.RecyclerView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/catalogueRV"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior" />

活动:

(....) 

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

    //App bar
    Toolbar toolbar = (Toolbar) findViewById(R.id.appbar);
    setSupportActionBar(toolbar);

    final ActionBar ab = getSupportActionBar();
    //CAMBIAR POR WHITE PARA QUE SEAN IGUALES...
    ab.setHomeAsUpIndicator(R.drawable.ic_arrow_back_black);
    ab.setDisplayHomeAsUpEnabled(true);

    //CollapsingToolbarLayout
    ctlLayout = (CollapsingToolbarLayout)findViewById(R.id.ctlLayout);
    ctlLayout.setTitle(getString(R.string.categories));


    //Rellena la Actividad con SubcategoriasFragment
    Fragment fragmentSubcategorias = new SubcategoriasFragment2();
    FragmentManager fragmentManagerMain = getSupportFragmentManager();
    fragmentManagerMain.beginTransaction()
            .add(R.id.container, fragmentSubcategorias).commit();
}

(...)

@Override
public void onSubcategorySelected(int idSubcategory) {
    //Argumentos para pasar al ProductosFragment
    final Bundle bundle = new Bundle();
    bundle.putInt("idSubcategoria", idSubcategory);

    Fragment fragmentProductos = ProductosFragment2.newInstance(bundle);
    FragmentManager fragmentManager = getSupportFragmentManager();
    fragmentManager.beginTransaction()
            .add(R.id.container,
                 fragmentProductos).addToBackStack(null).commit();
}

片段 1:

(....)
public static SubcategoriasFragment2 newInstance(Bundle arguments){
    SubcategoriasFragment2 f = new SubcategoriasFragment2();
    if(arguments != null){
        f.setArguments(arguments);
    }
    return f;
}

public SubcategoriasFragment2() {
    // Required empty public constructor
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    View view = inflater.inflate(R.layout.activity_coordinator2, container, false);

    int idCategoria=22;
    //INICIO EL DAO
    this.mSubcategoriasDAO = new SubcategoriasDAO(view.getContext());
    //Rellena la lista de Subcategorias
    mListaSubcategorias = mSubcategoriasDAO.getSubcategoriasDeCategoria(idCategoria);

    mRecycler = (RecyclerView) view.findViewById(R.id.catalogueRV);
    mRecycler.setHasFixedSize(true);
    // Usar un administrador para LinearLayout
    mLManager = new LinearLayoutManager(view.getContext());
    mRecycler.setLayoutManager(mLManager);

    //Inicio el Adapter de Subcategorias
    mAdapter = new SubcategoriasAdapter(mListaSubcategorias);
    mRecycler.setAdapter(mAdapter);

    //Maneja los eventos de click
    clickHandle();

    return view;
}

public void clickHandle(){
    /**
     * Manejo de Clicks.
     * GestureDetector.
     * Devuelve true si hay un click sencillo.
     */
    final GestureDetector subcategoriasGestureDetector = new GestureDetector(getActivity(),
            new GestureDetector.SimpleOnGestureListener(){
                @Override
                public boolean onSingleTapUp(MotionEvent e) {
                    return true;
                }
            });

    /**
     * Define addOnItemTL del RV al que se le pasa el objeto OnItemTouchListener
     * Cuando se crea un objeto OnItemTocuhListener, se sobrescriben dos métodos:
     * onInterceptTouchEvent() le dice el tipo de Gesto que ha detectado
     */
    mRecycler.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
        /**
         * onInterceptTouchEvent() detecta el evento
         * @param recyclerView
         * @param motionEvent
         * @return
         */
        @Override
        public boolean onInterceptTouchEvent(RecyclerView recyclerView, MotionEvent motionEvent) {

            View child = recyclerView.findChildViewUnder(motionEvent.getX(),motionEvent.getY());

            if(child!=null && subcategoriasGestureDetector.onTouchEvent(motionEvent)){
                int position = mRecycler.getChildAdapterPosition(child);
                //Obtiene el id de la Subcategoría
                int idSubcategoria = mListaSubcategorias.get(position).getScId();

                mListener.onSubcategorySelected(idSubcategoria);

                //Actualiza nombre de la ventana
                getActivity().setTitle(mListaSubcategorias.get(position).getScNombre());

                return true;
            }
            return false;
        }
        @Override
        public void onTouchEvent(RecyclerView recyclerView, MotionEvent motionEvent) {
            /**
             * ON TOUCH EVENT
             */
        }

        @Override
        public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

        }
    });

}



@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    Log.e("Subcategorias2Fragment", "onAttach()");
    try {
        mListener = (OnSubcategorySelectedListener) activity;
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString() + " must implement OnSubcategorySelectedListener");
    }
}

片段 2:

 (...)
 public static ProductosFragment2 newInstance(Bundle arguments){
    ProductosFragment2 f = new ProductosFragment2();
    if(arguments != null){
        f.setArguments(arguments);
    }
    return f;
}

public ProductosFragment2() {
    // Required empty public constructor
}


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {


    //Obtiene los argumentos del Fragment
    Bundle args = getArguments();
    int idSubcategoriaArg=0;
    if (args  != null && args.containsKey("idSubcategoria")) {
        idSubcategoriaArg = args.getInt("idSubcategoria");
        Log.e("ARGS ProductosFragment", args.toString());
    }

    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.activity_coordinator2, container, false);

    //INICIO EL DAO
    this.mProductosDAO = new ProductosDAO(getActivity());
    //Rellena la lista de Producto
    mListaProductos= mProductosDAO.getProductosDeSubcategoria(idSubcategoriaArg);

    mRecycler = (RecyclerView) view.findViewById(R.id.catalogueRV);
    mRecycler.setHasFixedSize(true);
    // Usar un administrador para LinearLayout
    mLManager = new LinearLayoutManager(getActivity());
    mRecycler.setLayoutManager(mLManager);

    //Inicio el Adapter de Producto
    mAdapter = new ProductosAdapter(mListaProductos);
    mRecycler.setAdapter(mAdapter);


    Log.e("ProductosFragment", ""+mListaProductos.size());


    return view;
}


@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    Log.e("Productos2Fragment", "onAttach()");
    try {
        mListener = (OnSubcategorySelectedListener) activity;
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString() + " must implement OnSubcategorySelectedListener");
    }
}

【问题讨论】:

    标签: android android-fragments android-support-library android-coordinatorlayout


    【解决方案1】:

    我昨天遇到了同样的问题,我通过避免这个问题来解决它。

    这是我的解决方案:

    不要使用 CoordinatorLayout 作为你的片段容器,如你所说,使用 ListView 或 FrameLayout 等。

    <android.support.v4.widget.DrawerLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/drawer_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
    <!--The main content view-->
    <FrameLayout
            android:id="@+id/main_content_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    

    将您的 CoordinatorLayout 改为片段,并在您的 Activity onCreate 方法中,用此片段替换容器。

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        initView();
        setListener();
        setupMainFragment();
    }
    
    private void setupMainFragment() {
        MainFragment mainFragment = new MainFragment();
        getSupportFragmentManager().beginTransaction().replace(R.id.main_content_layout, mainFragment).commit();
    }
    

    至于 CoordinatorLayout 是否或为什么不能成为片段的容器,我也不知道。

    我希望这个答案可能会有所帮助。

    【讨论】:

    • 首先,感谢您的回复,但我不想在 Fragment 中调用 Fragments。我想从 Activity 中管理它们,正如它在 Android 文档中所说的那样。在您提供的解决方案中,我必须使用 CoordinatorLayout 创建一个 Fragment,然后从该 Fragment 加载其他 Fragment,我想避免这种方式。我不明白为什么 CoordinatorLayout 容器不能正常工作。问题是,我在 Activity 中加载的第一个 Fragment 显示得很完美,但是当我用第二个 Fragment 替换它时,问题就来了,什么都没有显示。
    • 这样,你确实在一个Activity内部调用了fragment,而不是Fragment。可能是我没说清楚。
    • 是的,第一个带有CoordinatorLayout的Fragment是从Activity管理的,这样就OK了。但是我想在 CollapsingToolbarLayout 上方显示一个列表,它是另一个片段,然后如果您单击列表的某个元素,则会启动另一个列表。我怎样才能用你的结构实现这一点?提前致谢。
    • 我终于做到了你的意思。我在 Activity 中使用 CoordinatorLayout 和 FrameLayout 作为两个片段的布局。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多