如何居中水平android循环ListView



我在listview中水平添加项目,但如果我有单个项目,我希望它在水平中心

我尝试了许多解决方案,但仍然没有帮助。

  1. 我尝试使用相对布局(centerInParent, centerhorizontal)
  2. 重力,layout_重力属性等

请帮助。

  <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:weightSum="10"
    android:layout_height="match_parent">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/noUser_layout"
        android:orientation="vertical"
        android:layout_weight="10"
        android:visibility="gone"
        android:gravity="center">
        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/noMessageLogo"
            android:src="@mipmap/eapp_icon"/>
        <TextView android:text="@string/loading_Message" android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="15dp"
            android:layout_marginLeft="25dp"
            android:layout_marginRight="25dp"
            android:id="@+id/noMessage"
            android:gravity="center"
            android:fontFamily="sans-serif"
            android:textSize="16sp"
            android:textStyle="bold"
            android:textColor="@android:color/black" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:id="@+id/parentLayout"
        android:orientation="vertical"
        android:layout_weight="3.8"
        android:gravity="center|center_horizontal">
        <TextView android:text="Parent" android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"
            android:id="@+id/parentText"
            android:gravity="center"
            android:fontFamily="sans-serif"
            android:textSize="16sp"
            android:textStyle="bold"
            android:textColor="@android:color/holo_blue_dark" />
            <android.support.v7.widget.RecyclerView
                android:id="@+id/parentList"
                android:layout_width="wrap_content"
                android:layout_centerHorizontal="true"
                android:layout_height="wrap_content"
                />
    </LinearLayout>
    <LinearLayout
        android:layout_width="wrap_content" android:layout_height="0dp"
        android:layout_gravity="center"
        android:layout_weight="2.5"
        android:paddingTop="10dp"
        android:paddingBottom="10dp"
        android:id="@+id/contactLayout"
        android:layout_centerHorizontal="true"
        android:orientation="vertical">
        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="8dp"
            android:id="@+id/userImage"
            android:layout_gravity="center"
            android:src="@drawable/user_icon" />
        <TextView android:text="Contact Name" android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="5dp"
            android:layout_marginRight="5dp"
            android:id="@+id/name"
            android:fontFamily="sans-serif"
            android:textSize="15sp"
            android:textStyle="bold"
            android:layout_gravity="left"
            android:textColor="@android:color/black"/>
    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:id="@+id/childrenLayout"
        android:layout_centerHorizontal="true"
        android:layout_weight="3.8"
        android:orientation="vertical"
        android:gravity="center|center_horizontal">
        <TextView android:text="Child" android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/childText"
            android:gravity="center"
            android:layout_margin="10dp"
            android:fontFamily="sans-serif"
            android:textSize="16sp"
            android:textStyle="bold"
            android:textColor="@android:color/holo_blue_dark" />
        <android.support.v7.widget.RecyclerView
            android:id="@+id/childList"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center|center_horizontal" />
    </LinearLayout>
</LinearLayout>

RecyclerView上使用这个布局管理器

public class WrapContentLinearLayoutManager extends LinearLayoutManager {
    public WrapContentLinearLayoutManager(Context context, int orientation, boolean reverseLayout)    {
        super(context, orientation, reverseLayout);
    }
    private int[] mMeasuredDimension = new int[2];
    @Override
    public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state,
                          int widthSpec, int heightSpec) {
        final int widthMode = View.MeasureSpec.getMode(widthSpec);
        final int heightMode = View.MeasureSpec.getMode(heightSpec);
        final int widthSize = View.MeasureSpec.getSize(widthSpec);
        final int heightSize = View.MeasureSpec.getSize(heightSpec);
        int width = 0;
        int height = 0;
        for (int i = 0; i < getItemCount(); i++) {
            measureScrapChild(recycler, i,
                    View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
                    View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
                    mMeasuredDimension);
            if (getOrientation() == HORIZONTAL) {
                width = width + mMeasuredDimension[0];
                if (i == 0) {
                    height = mMeasuredDimension[1];
                }
            } else {
                height = height + mMeasuredDimension[1];
                if (i == 0) {
                    width = mMeasuredDimension[0];
                }
            }
        }
        switch (widthMode) {
            case View.MeasureSpec.EXACTLY:
                width = widthSize;
            case View.MeasureSpec.AT_MOST:
            case View.MeasureSpec.UNSPECIFIED:
        }
        switch (heightMode) {
            case View.MeasureSpec.EXACTLY:
                height = heightSize;
            case View.MeasureSpec.AT_MOST:
            case View.MeasureSpec.UNSPECIFIED:
        }
        setMeasuredDimension(width, height);
    }
    private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,
                                   int heightSpec, int[] measuredDimension) {
        View view = recycler.getViewForPosition(position);
        if (view != null) {
            RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();
            int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec,
                    getPaddingLeft() + getPaddingRight(), p.width);
            int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec,
                    getPaddingTop() + getPaddingBottom(), p.height);
            view.measure(childWidthSpec, childHeightSpec);
            measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin;
            measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin;
            recycler.recycleView(view);
        }
    }
}

我使用窗口管理器来获取屏幕的总宽度,并用于设置回收视图

下面的布局管理器用于水平循环视图,即LinearLayoutManager

public class WrapHeightLinearLayoutManager extends LinearLayoutManager {
    Context mContext;
    public WrapHeightLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
        super(context, orientation, reverseLayout);
        mContext = context;
    }
    private int[] mMeasuredDimension = new int[2];
    @Override
    public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state,
                          int widthSpec, int heightSpec) {
        final int widthMode = View.MeasureSpec.getMode(widthSpec);
        final int heightMode = View.MeasureSpec.getMode(heightSpec);
        final int widthSize = View.MeasureSpec.getSize(widthSpec);
        final int heightSize = View.MeasureSpec.getSize(heightSpec);
        int width = 0;
        int height = 0;
        for (int i = 0; i < getItemCount(); i++) {
            measureScrapChild(recycler, i,
                    View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
                    View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
                    mMeasuredDimension);
            if (getOrientation() == HORIZONTAL) {
                //width = width + mMeasuredDimension[0];
                if (i == 0) {
                    WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
                    Display display = wm.getDefaultDisplay();
                    Point size = new Point();
                    display.getSize(size);
                    int widthWin = size.x;
                    int heightWin = size.y;
                    width = widthWin;
                    height = mMeasuredDimension[1];
                }
            } else {
                height = height + mMeasuredDimension[1];
                if (i == 0) {
                    width = mMeasuredDimension[0];
                }
            }
        }
        switch (widthMode) {
            case View.MeasureSpec.EXACTLY:
                width = widthSize;
            case View.MeasureSpec.AT_MOST:
            case View.MeasureSpec.UNSPECIFIED:
        }
        switch (heightMode) {
            case View.MeasureSpec.EXACTLY:
                height = heightSize;
            case View.MeasureSpec.AT_MOST:
            case View.MeasureSpec.UNSPECIFIED:
        }
        Logger.getInstanceLogger().printVerbose("WrapHeightLinearLayoutManager","width ==>"+width+" height==>"+height);
        setMeasuredDimension(width, height);
    }
    private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,
                                   int heightSpec, int[] measuredDimension) {
        View view = recycler.getViewForPosition(position);
        if (view != null) {
            RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();
            int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec,
                    getPaddingLeft() + getPaddingRight(), p.width);
            int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec,
                    getPaddingTop() + getPaddingBottom(), p.height);
            view.measure(childWidthSpec, childHeightSpec);
            measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin;
            measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin;
            recycler.recycleView(view);
        }
    }
}

这个简单的例子解决了我的问题:)

代码总结如下:

public class SpinnerWheelActivity extends Activity {
private static final int NUM_ITEMS = 3;
private static final String BUNDLE_LIST_PIXELS = "allPixels";
private float itemWidth;
private float padding;
private float firstItemWidth;
private float allPixels;
private int mLastPosition;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_spinner_wheel);
    Display display = getWindowManager().getDefaultDisplay();
    Point size = new Point();
    display.getSize(size);
    itemWidth = getResources().getDimension(R.dimen.item_width);
    padding = (size.x - itemWidth) / 2;
    firstItemWidth = getResources().getDimension(R.dimen.padding_item_width);
    allPixels = 0;
    final RecyclerView items = (RecyclerView) findViewById(R.id.item_list);
    LinearLayoutManager shopItemslayoutManager = new LinearLayoutManager(getApplicationContext());
    shopItemslayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
    items.setLayoutManager(shopItemslayoutManager);
    // to center item
    items.setOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
            synchronized (this) {
                if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                    calculatePositionAndScroll(recyclerView);
                }
            }
        }
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            allPixels += dx;
        }
    });
    ExtraItemsAdapter adapter = new ExtraItemsAdapter(NUM_ITEMS);
    items.setAdapter(adapter);
    if (NUM_ITEMS > 0) // init position
        scrollListToPosition(items, 0);
}
@Override
protected void onResume() {
    super.onResume();
    //final RecyclerView items = (RecyclerView) findViewById(R.id.item_list);
    //ViewTreeObserver vto = items.getViewTreeObserver();
    //vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    //    @Override
    //    public void onGlobalLayout() {
    //        items.getViewTreeObserver().removeOnGlobalLayoutListener(this);
    //        calculatePositionAndScroll(items);
    //    }
    //});
}
private void calculatePositionAndScroll(RecyclerView recyclerView) {
    int expectedPosition = Math.round((allPixels + padding - firstItemWidth) / itemWidth);
    // Special cases for the padding items
    if (expectedPosition == -1) {
        expectedPosition = 0;
    } else if (expectedPosition >= recyclerView.getAdapter().getItemCount() - 2) {
        expectedPosition--;
    }
    scrollListToPosition(recyclerView, expectedPosition);
}
private void scrollListToPosition(RecyclerView recyclerView, int expectedPosition) {
    float targetScrollPos = expectedPosition * itemWidth + firstItemWidth - padding;
    float missingPx = targetScrollPos - allPixels;
    if (missingPx != 0) {
        recyclerView.smoothScrollBy((int) missingPx, 0);
    }
}
@Override
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    allPixels = savedInstanceState.getFloat(BUNDLE_LIST_PIXELS);
}
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putFloat(BUNDLE_LIST_PIXELS, allPixels);
}
/*----------  Adapters ----------*/
public class ExtraItemsAdapter extends RecyclerView.Adapter<ViewHolder> {
    private static final int VIEW_TYPE_PADDING = 1;
    private static final int VIEW_TYPE_ITEM = 2;
    private final int mNumItems;
    public ExtraItemsAdapter(int numItems) {
        mNumItems = numItems;
    }
    @Override
    public int getItemCount() {
        return mNumItems + 2; // We have to add 2 paddings
    }
    @Override
    public int getItemViewType(int position) {
        if (position == 0 || position == getItemCount() - 1) {
            return VIEW_TYPE_PADDING;
        }
        return VIEW_TYPE_ITEM;
    }
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        // create a new view
        if (viewType == VIEW_TYPE_ITEM) {
            View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);
            return new ViewHolder(v);
        } else {
            View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_padding, parent, false);
            return new ViewHolder(v);
        }
    }
    @Override
    public void onBindViewHolder(ViewHolder holder, final int position) {
        if (getItemViewType(position) == VIEW_TYPE_ITEM) {
            // We bind the item to the view
            holder.text.setText(String.valueOf(position));
        }
    }
}
/*----------  ViewHolders ----------*/
public class ViewHolder extends RecyclerView.ViewHolder {
    TextView text;
    public ViewHolder(View itemView) {
        super(itemView);
        text = (TextView) itemView.findViewById(R.id.item_text);
    }
}
}

最新更新