带有子约束布局的约束布局未水平扩展 [英] Constraint layout with child constraint layouts not expanding horizontally

查看:77
本文介绍了带有子约束布局的约束布局未水平扩展的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试构建一个矩形视图(跨越屏幕的宽度),该视图被水平分为三个块,并且使用约束布局来实现.左侧和右侧块具有指定的宽度,但中央块应扩展以适合剩余空间.因为我要求最左边的块与父块具有不同的背景色,所以我将其子块分组为另一个约束布局.我在下面给出了布局XML:

I'm trying to build a rectangular view (spanning the width of the screen) which is split horizontally into three blocks, and I am doing so using a constraint layout. The left and right blocks have a specified width, but the centre block should expand to fit the remaining space. Because I require that the left-most block have a different background colour to the parent, I have grouped its children into another constraint layout. I have given the layout XML below:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    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="100dp"
    android:layout_marginTop="8dp"
    android:background="#10000000"
    xmlns:tools="http://schemas.android.com/tools">

    <android.support.constraint.ConstraintLayout
        android:id="@+id/abc"
        android:layout_width="100dp"
        android:layout_height="match_parent"
        android:background="#50000000"
        android:layout_marginEnd="8dp"
        android:padding="2dp"
        app:layout_constraintHorizontal_chainStyle="spread_inside"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/jkl"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <TextView
            android:id="@+id/def"
            android:gravity="start"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#ffffffff"
            android:textSize="18sp"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/ghi"
            android:gravity="start"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#ffffffff"
            android:textSize="14sp"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/def" />

    </android.support.constraint.ConstraintLayout>

    <!-- This should expand to fit the remainder of the screen width -->
    <android.support.constraint.ConstraintLayout
        android:id="@+id/jkl"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        app:layout_constraintHorizontal_chainStyle="spread_inside"
        app:layout_constraintEnd_toStartOf="@+id/stu"
        app:layout_constraintStart_toEndOf="@+id/abc">

        <TextView
            android:id="@+id/mno"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="top|start"
            android:textColor="#a0000000"
            android:textSize="14sp"
            android:textStyle="bold"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/pqr"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="top|start"
            android:textColor="#a0000000"
            android:textSize="14sp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/mno" />

    </android.support.constraint.ConstraintLayout>

    <ImageButton
        android:id="@+id/stu"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="16dp"
        android:src="@drawable/x"
        app:layout_constraintHorizontal_chainStyle="spread_inside"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/jkl"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

不幸的是,中间块无法扩展为适合屏幕的剩余宽度.有谁知道如何实现这一目标?我在这里做任何根本上错误的事情吗?

Unfortunately, the middle block does not expand to fit the remaining width of the screen. Does anyone know how to achieve this? Am I doing anything fundamentally wrong here?

根据Ben P.的回答,可能是上面的XML很好,但是包含此布局的布局存在错误.因此,我在下面提供了它们.

Based on Ben P.'s response it may be that the XML above is fine, but the layouts in which this layout is contained are at fault. I have therefore provided them below.

此布局XML是上述XML的父级:

This layout XML is the parent of the XML above:

<android.support.v7.widget.RecyclerView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/parent_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.Parent">

</android.support.v7.widget.RecyclerView>

此布局XML是上述RecyclerView XML的父级:

This layout XML is the parent of the RecyclerView XML above:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    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="com.example.MainActivity">

    <FrameLayout
        android:id="@+id/fragment_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <include layout="@layout/bottom_navigation" />

</android.support.constraint.ConstraintLayout>


根据要求,我提供了完整的代码库:

As requested I've provided the complete code base:

MainActivity.java:

MainActivity.java:

public class MainActivity extends AppCompatActivity {

    private FragmentManager mFragmentManager;

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

        mFragmentManager = getFragmentManager();

        FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
        fragmentTransaction.replace(R.id.fragment_container, new Foo());
        fragmentTransaction.addToBackStack(null);
        fragmentTransaction.commit();
    }
}

Foo.java:

public class Foo extends Fragment {
    private String[] mDataset;

    private OnFragmentInteractionListener mListener;

    private RecyclerView mRecyclerView;
    private RecyclerView.Adapter mAdapter;
    private RecyclerView.LayoutManager mLayoutManager;

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

    /**
     * Use this factory method to create a new instance of
     * this fragment using the provided parameters.
     *
     * @param param1 Parameter 1.
     * @param param2 Parameter 2.
     * @return A new instance of fragment Foo.
     */
    // TODO: Rename and change types and number of parameters
    public static Foo newInstance(String param1, String param2) {
        Foo fragment = new Foo();
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
        initDataset();
    }

    private void initDataset() {
        mDataset = new String[1];
        mDataset[0] = "Hello World";
    }

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

        mRecyclerView = view.findViewById(R.id.foo_view);
        mRecyclerView.setHasFixedSize(true);

        mLayoutManager = new LinearLayoutManager(getActivity());
        mRecyclerView.setLayoutManager(mLayoutManager);

        mAdapter = new FooAdapter(mDataset);
        mRecyclerView.setAdapter(mAdapter);

        return view;
    }

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

FooAdapter.java:

FooAdapter.java:

public class FooAdapter extends RecyclerView.Adapter<FooAdapter.ViewHolder> {

    private String[] mDataset;

    public static class ViewHolder extends RecyclerView.ViewHolder {
        private TextView mFoofoo;
        private TextView mBarbar;

        public ViewHolder(View itemView) {
            super(itemView);

            mFoofoo = itemView.findViewById(R.id.foofoo);
            mBarbar = itemView.findViewById(R.id.barbar);
        }

        public TextView getFoofoo() {
            return mFoo;
        }

        public TextView getBarbar() {
            return mBar;
        }
    }

    public FooAdapter(String[] mDataset) {
        this.mDataset = mDataset;
    }

    @Override
    public FooAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.bar, parent, false);

        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(FooAdapter.ViewHolder holder, int position) {
        String text = mDataset[position];
        holder.getBarbar().setText(text);
        holder.getFoofoo().setText(text);
    }

    @Override
    public int getItemCount() {
        return mDataset.length;
    }
}

activity_main.xml:

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    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="com.example.MainActivity">

    <FrameLayout
        android:id="@+id/fragment_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#eaff73"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

fragment.xml:

fragment.xml:

<android.support.v7.widget.RecyclerView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/foo_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#8df78b"
    tools:context="com.example.Foo">

</android.support.v7.widget.RecyclerView>

bar.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    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="104dp"
    android:layout_marginTop="4dp"
    android:background="#10000000"
    xmlns:tools="http://schemas.android.com/tools">

    <ImageView
        android:id="@+id/backg"
        android:background="#50000000"
        android:layout_width="104dp"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/foofoo"
        android:gravity="start"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:textColor="#ffffffff"
        android:textSize="18sp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <ImageButton
        android:id="@+id/action"
        android:layout_height="wrap_content"
        android:layout_marginEnd="16dp"
        android:layout_width="wrap_content"
        android:src="@drawable/pic"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/barbar"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/barbar"
        android:autoSizeMaxTextSize="24sp"
        android:autoSizeMinTextSize="14dp"
        android:autoSizeStepGranularity="2dp"
        android:autoSizeTextType="uniform"
        android:background="#ef0505"
        android:gravity="top|start"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:paddingStart="8dp"
        android:textColor="#a0000000"
        android:textSize="24sp"
        android:textStyle="bold"
        app:layout_constraintEnd_toStartOf="@id/action"
        app:layout_constraintStart_toEndOf="@id/backg"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

任何帮助将不胜感激!

推荐答案

我不知道为什么会这样,但确实如此.

I do not know why this works, but it does.

bar.xml中,将外部ConstraintLayout的高度替换为wrap_content(而不是104dp).

In bar.xml, replace your outer ConstraintLayout's height with wrap_content (instead of 104dp).

也在bar.xml中,用104dp(而不是0dp)代替ImageView的高度.

Also in bar.xml, replace your ImageView's height with 104dp (instead of 0dp).

这具有保持布局设计相同的最终效果……它只是具有由ImageView的高度定义的ConstraintLayout的高度,而不是相反的方式.

This has the net effect of keeping your layout's design the same... it just has the ConstraintLayout's height defined by the ImageView's height, instead of the other way around.

如果我不得不猜测为什么会有所不同,我会假设LinearLayoutManager测量其子级的方式中存在一些古怪之处,并且当它看到固定高度时,它会忽略match_parent宽度.但这是一种疯狂的猜测.

If I had to guess at why this makes a difference, I'd assume that there's some quirk in the way LinearLayoutManager measures its children, and that when it sees a fixed height it ignores the match_parent width. But that's wild speculation.

这篇关于带有子约束布局的约束布局未水平扩展的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆