Макет ограничения с макетами дочерних ограничений, не расширяющимися по горизонтали

Я пытаюсь построить прямоугольный вид (охватывающий всю ширину экрана), который разделен по горизонтали на три блока, и я делаю это с помощью макета ограничения. Левый и правый блоки имеют указанную ширину, но центральный блок должен расширяться, чтобы соответствовать оставшемуся пространству. Поскольку мне требуется, чтобы крайний левый блок имел цвет фона, отличный от родительского, я сгруппировал его дочерние элементы в другой макет ограничения. Я дал макет 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="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>

К сожалению, средний блок не расширяется, чтобы соответствовать оставшейся ширине экрана. Кто-нибудь знает, как этого добиться? Я делаю что-то в корне не так?


Редактировать:

Основываясь на ответе Бена П., может оказаться, что с приведенным выше XML-кодом все в порядке, но схемы, в которых содержится эта схема, ошибочны. Поэтому я предоставил их ниже.

Этот макет XML является родителем 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/parent_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.Parent">

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

Этот XML-макет является родителем XML-кода RecyclerView выше:

<?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>

Изменить 2:

По запросу я предоставил полную базу кода:

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:

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:

<?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:

<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>

Любая помощь очень ценится!

2 ответа

Решение

Я не знаю, почему это работает, но это работает.

В bar.xmlзамени свой внешний ConstraintLayoutвысота с wrap_content (вместо 104dp).

Также в bar.xmlзамени ImageViewвысота с 104dp (вместо 0dp).

Это приводит к тому, что дизайн вашего макета остается неизменным... ConstraintLayoutвысота определяется ImageViewВысота, а не наоборот.

Если бы мне пришлось угадывать, почему это имеет значение, я бы предположил, что на этом пути есть какая-то особенность LinearLayoutManager измеряет своих детей, и что, когда он видит фиксированную высоту, он игнорирует match_parent ширина. Но это дикие предположения.

Обновить

Вот квартира ConstraintLayout это делает то, что я считаю, что вы хотите:

<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="100dp">

    <ImageView
        android:id="@+id/image"
        android:layout_width="100dp"
        android:layout_height="0dp"
        android:background="#33000000"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"/>

    <TextView
        android:id="@+id/text1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:padding="4dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="@+id/image"
        app:layout_constraintRight_toRightOf="@+id/image"
        tools:text="line 1"/>

    <TextView
        android:id="@+id/text2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:padding="4dp"
        app:layout_constraintTop_toBottomOf="@+id/text1"
        app:layout_constraintLeft_toLeftOf="@+id/image"
        app:layout_constraintRight_toRightOf="@+id/image"
        tools:text="line 2"/>

    <TextView
        android:id="@+id/text3"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:padding="4dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toRightOf="@+id/image"
        app:layout_constraintRight_toLeftOf="@+id/button"
        tools:text="line 3"/>

    <TextView
        android:id="@+id/text4"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:padding="4dp"
        app:layout_constraintTop_toBottomOf="@+id/text3"
        app:layout_constraintLeft_toRightOf="@+id/image"
        app:layout_constraintRight_toLeftOf="@+id/button"
        tools:text="line 4"/>

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        tools:text="button"/>

</android.support.constraint.ConstraintLayout>

И как это выглядит:

введите описание изображения здесь


оригинал

Это не дает точного ответа на вопрос (поскольку, насколько я могу судить, с размещенным макетом проблем нет), но...

Я не вижу причин для реализации этого интерфейса с помощью ConstraintLayout, Преимущество ConstraintLayout является то, что это позволяет избежать вложения ViewGroupвнутри вашего верхнего уровня View, А как твой ConstraintLayout написано, вы все еще группируете TextViewвнутри среднего уровня View,

Если вы не пользуетесь ConstraintLayoutСпособность организовывать без вложений, я думаю, что лучше использовать более простое представление верхнего уровня. Вот ваш интерфейс переопределен с LinearLayouts:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="100dp"
    android:layout_marginTop="8dp"
    android:background="#10000000"
    android:orientation="horizontal">

    <LinearLayout
        android:id="@+id/abc"
        android:layout_width="100dp"
        android:layout_height="match_parent"
        android:padding="2dp"
        android:background="#50000000"
        android:orientation="vertical">

        <TextView
            android:id="@+id/def"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#ffffffff"
            android:textSize="18sp"
            tools:text="line 1"/>

        <TextView
            android:id="@+id/ghi"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#ffffffff"
            android:textSize="14sp"
            tools:text="line 2"/>

    </LinearLayout>

    <LinearLayout
        android:id="@+id/jkl"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:orientation="vertical">

        <TextView
            android:id="@+id/mno"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textColor="#a0000000"
            android:textSize="14sp"
            android:textStyle="bold"
            tools:text="line 1"/>

        <TextView
            android:id="@+id/pqr"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textColor="#a0000000"
            android:textSize="14sp"
            tools:text="line 2"/>

    </LinearLayout>

    <ImageButton
        android:id="@+id/stu"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:layout_marginRight="16dp"
        android:layout_marginEnd="16dp"
        android:src="@drawable/plus"/>

</LinearLayout>
Другие вопросы по тегам