具有子约束布局但不水平扩展的约束布局

时间:2017-07-17 22:08:31

标签: android android-constraintlayout

我试图建立一个矩形视图(跨越屏幕的宽度),它被水平分割成三个块,我正在使用约束布局。左侧和右侧块具有指定的宽度,但中心块应扩展以适合剩余空间。因为我要求最左边的块具有与父节点不同的背景颜色,所以我将其子节点分组为另一个约束布局。我在下面给出了布局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>

不幸的是,中间块不会扩展以适应屏幕的剩余宽度。有谁知道如何实现这一目标?我在这里做了什么根本性的错误吗?

修改

基于Ben P.的回复,可能是上面的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是上面的RecyclerView 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"
        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 个答案:

答案 0 :(得分:2)

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

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

同样在bar.xml中,将ImageView的高度替换为104dp(而不是0dp)。

这样可以保持您的布局设计一致......它只有ConstraintLayout的高度定义的ImageView高度高度,而不是相反。

如果我不得不猜测为什么这会产生影响,我会假设LinearLayoutManager测量其孩子的方式存在一些怪癖,当它看到一个固定的高度时忽略match_parent宽度。但这是一种疯狂的猜测。

答案 1 :(得分:0)

更新

这是一个符合我想要的平面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>

它看起来像什么:

enter image description here

原始

这并没有严格回答这个问题(因为据我所知,发布的布局没有问题),但......

我认为没有理由使用ConstraintLayout来实现此UI。 ConstraintLayout的好处是,它可以避免将ViewGroup嵌套在顶级View中。但是,当您编写ConstraintLayout时,您仍然会将TextView内部View内的ConstraintLayout分组。

如果你没有利用LinearLayout没有嵌套的组织能力,我认为使用更简单的顶级视图更好。以下是使用<?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> s重新实现的用户界面:

 from bs4 import BeautifulSoup
import requests
import time
import re

# Get search inputs from user
search_term = raw_input('Search Term:')

# Build URL to imdb.com
aliURL = 'https://www.aliexpress.com/wholesale?SearchText=%(q)s'
payload = {'q': search_term, }

# Get resulting webpage
r = requests.get(aliURL % payload)

# Build 'soup' from webpage and filter down to the results of search
soup = BeautifulSoup(r.text, "html5lib")
titles = soup.findAll('a', attrs = {'class': 'product'})


itemURL = titles[0]["href"]
seperatemarker = '?'
seperatedURL = itemURL.split(seperatemarker, 1)[0]

seperatedURL = "http:" + seperatedURL

print seperatedURL

IR = requests.get(seperatedURL)
Isoup = BeautifulSoup(IR.text, "html5lib")

productname = Isoup.findAll('h1')

print productname