(原创)关于viewpager嵌套listview居中显示的问题

今天折腾了半天自定义控件的问题,如下图所示,我们UI设计了一种可以左右滑动的列表,而列表中又包含了listview。而且要居中显示listview

我一看UI,心想简单,不就是根据datas的数目进行分页么,有几页就在viewpager里add几个listview,然后设置viewpager居中显示不就行了么?

这里先设置viewpager的width为wrap_content,listview的width也是wrap_content。然后根据数据分页,填充数据,设置页数指示点。

结果一运行发现问题所在,所有的条目都居左显示,而且viewpager一点也没有wrap_content,全都是占满了屏幕!

于是我就开始继承viewpager后自定义viewpager,让viewpager的宽度自动修改为子view中最大的宽度,结果发现不论怎么改,依然还是全屏!

后来才怀疑到是listview的问题,把listview弄出来设置wrap_content,结果一运行果然还是全屏!

于是乎又开始了自定义listview之旅,终于把这一切都自定义好了,然后一运行,果然第一页的内容宽度自适应了!,也居中显示了。

然而坑就坑在这里了,向左滑动下一页的宽度和这一页不一样,结果就又偏左了,再翻到第三页就居中了,也变窄了,结果划回来宽度就是后边的小宽度了。

如此坑爹啊!

后来终于想到一种办法就是,去掉viewpager的宽度自适应,让其match_parent,然后在listview的外城包裹一个LinearLayout,让LinearLayout实现match_parent,然后listview自适应宽度,并在LinearLayout中居中显示。

后边的代码如下:

item_list_address.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:orientation="horizontal">

    <TextView
        android:id="@+id/tv_address_number"
        style="@style/YunNormalText"
        android:layout_width="@dimen/x100"
        android:layout_height="@dimen/x100"
        android:layout_gravity="center_vertical"
        android:background="@drawable/shape_circle_blue"
        android:gravity="center"
        android:text="1"
        android:textColor="@color/YunCircleBlue"/>

    <LinearLayout
        android:id="@+id/ll_item_background"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="@dimen/x90"
        android:background="@drawable/ic_item_background"
        android:minWidth="@dimen/x800"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <TextView
                android:id="@+id/tv_address_title"
                style="@style/YunNormalText"
                android:text="回龙观(地铁站)"/>

            <TextView
                android:id="@+id/tv_address_distance"
                style="@style/YunNormalText"
                android:text="14.7公里"/>
        </LinearLayout>


        <TextView
            android:id="@+id/tv_address_des"
            style="@style/YunSmallText"
            android:text="13号线"/>
    </LinearLayout>
</LinearLayout>

layout_listview.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:gravity="center|top"
              android:orientation="horizontal">

    <com.honghe.library.view.WrapContentListView

        android:id="@+id/lv_address"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:listSelector="@android:color/transparent">

    </com.honghe.library.view.WrapContentListView>
</LinearLayout>

fragment_addresses.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent">

    <ImageView
        android:id="@+id/iv_back"
        android:layout_width="@dimen/x60"
        android:layout_height="@dimen/x60"
        android:layout_marginLeft="@dimen/x75"
        android:layout_marginTop="@dimen/y135"
        android:src="@drawable/ic_back"/>

    <com.honghe.library.view.VoiceRobotStatusView
        android:id="@+id/vrsv_3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="@dimen/x470"
        android:layout_marginTop="@dimen/y120"/>

    <TextView
        android:id="@+id/tv_voice_search_hint"
        style="@style/YunNormalText"
        android:layout_width="@dimen/x762"
        android:layout_marginLeft="@dimen/x690"
        android:layout_marginTop="@dimen/y100"
        android:text="金贸大厦"
        android:textAlignment="center"/>

    <ImageView
        android:layout_width="@dimen/x762"
        android:layout_height="@dimen/y3"
        android:layout_below="@+id/tv_voice_search_hint"
        android:layout_marginLeft="@dimen/x690"
        android:src="@drawable/ic_light_line"/>

    <TextView
        style="@style/YunSmallText"
        android:layout_below="@+id/tv_voice_search_hint"
        android:layout_marginLeft="@dimen/x690"
        android:text="找到9个结果,请说第几个/下一页/取消"
        android:textSize="@dimen/y40"/>

    <android.support.v4.view.ViewPager
        android:id="@+id/vp_address"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="@dimen/y300"
        android:visibility="visible">

    </android.support.v4.view.ViewPager>

    <LinearLayout
        android:id="@+id/ll_dots"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="@dimen/y100"
        android:orientation="horizontal">

    </LinearLayout>

</RelativeLayout>

WrapContentListView.java

package com.honghe.library.view;

import android.content.Context;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ListView;

/**
 * Created by wanghh on 2017/5/11.
 */

public class WrapContentListView extends ListView {
    public WrapContentListView(Context context) {
        super(context);
    }

    public WrapContentListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public WrapContentListView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public WrapContentListView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = getMaxWidthOfChildren() + getPaddingLeft() + getPaddingRight();//计算listview的宽度
        super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), heightMeasureSpec);//设置listview的宽高
    }

    /**
     * 计算item的最大宽度
     *
     * @return
     */
    private int getMaxWidthOfChildren() {
        int maxWidth = 0;
        View view = null;
        int count = getAdapter().getCount();
        for (int i = 0; i < count; i++) {
            view = getAdapter().getView(i, view, this);
            view.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
            if (view.getMeasuredWidth() > maxWidth)
                maxWidth = view.getMeasuredWidth();
        }
        if (maxWidth > getContext().getResources().getDisplayMetrics().widthPixels) {
            maxWidth = getContext().getResources().getDisplayMetrics().widthPixels;
        }
        return maxWidth;
    }
}
AddressesFragment.java
package com.yunjia.hud.fragment;

import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;

import com.amap.api.services.core.LatLonPoint;
import com.amap.api.services.core.PoiItem;
import com.honghe.library.view.VoiceRobotStatusView;
import com.yunjia.hud.R;
import com.yunjia.hud.adapter.AddressAdapter;
import com.yunjia.hud.adapter.ViewPagerListAdapter;

import java.util.ArrayList;
import java.util.List;

import me.yokeyword.fragmentation.SupportFragment;

/**
 * Created by wanghh on 2017/5/11.
 */

public class AddressesFragment extends SupportFragment implements View.OnClickListener {
    private Context mContext;
    private static final String TAG = AddressesFragment.class.getName();
    private View rootView;
    private VoiceRobotStatusView vrsv_3;
    private ViewPager vp_address;
    private LinearLayout ll_dots;
    private List<ImageView> mDots;

    public static AddressesFragment newInstance() {
        return new AddressesFragment();
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        if (rootView == null) {
            rootView = inflater.inflate(R.layout.fragment_addresses, container, false);
        }
        initView();
        setData();
        setListener();
        return rootView;
    }

    private void initView() {
        vrsv_3 = (VoiceRobotStatusView) rootView.findViewById(R.id.vrsv_3);
        vp_address = (ViewPager) rootView.findViewById(R.id.vp_address);
        ll_dots = (LinearLayout) rootView.findViewById(R.id.ll_dots);
    }

    private void setData() {
//模拟数据
        List<PoiItem> poiItems = new ArrayList<>();
        for (int i = 0; i < 11; i++) {
            if (i < 3) {
                PoiItem poiItem = new PoiItem("哈哈" + i, new LatLonPoint(0.0, 0.0), "哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈" + i, "呵呵" + i);
                poiItems.add(poiItem);
            } else {
                PoiItem poiItem2 = new PoiItem("哈哈" + i, new LatLonPoint(0.0, 0.0), "哈哈" + i, "呵呵" + i);
                poiItems.add(poiItem2);
            }
        }
        setViewPagerData(poiItems);
    }

    private void setListener() {
        vrsv_3.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.vrsv_3:
                vrsv_3.switchView();
                break;
        }
    }

    private void setViewPagerData(List<PoiItem> datas) {
        List<View> views = new ArrayList<>();
        int split = 3;
        int totalNumber = datas.size();
        int pages = totalNumber % split == 0 ? totalNumber / split : totalNumber / split + 1;
        initPoints(pages);
        for (int i = 0; i < pages; i++) {
            View view = LayoutInflater.from(getActivity()).inflate(R.layout.layout_listview, null);
            ListView listView = (ListView) view.findViewById(R.id.lv_address);
            List<PoiItem> poiItems = new ArrayList<>();
            int numOfPoiItemsPerPage = (totalNumber - split * i) / split == 0 ? (totalNumber - split * i) % split : split;
            for (int j = 0; j < numOfPoiItemsPerPage; j++) {
                poiItems.add(datas.get(split * i + j));
            }
            AddressAdapter adapter = new AddressAdapter(getActivity());
            listView.setAdapter(adapter);
            adapter.setData(poiItems);
            views.add(view);
        }
        vp_address.setAdapter(new ViewPagerListAdapter(views));
        vp_address.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                updatePoints(position);
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });
    }

    private void initPoints(int pageSize) {
        ll_dots.removeAllViews();
        mDots = new ArrayList<>();
        ImageView imageView;
        for (int i = 0; i < pageSize; i++) {
            imageView = new ImageView(getActivity());
            imageView.setBackgroundResource(R.drawable.ic_dot_unselected);
            LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
                    new ViewGroup.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
                            LinearLayout.LayoutParams.WRAP_CONTENT));
            layoutParams.leftMargin = 10;
            layoutParams.rightMargin = 10;
            ll_dots.addView(imageView, layoutParams);
            if (i == 0) {
                imageView.setBackgroundResource(R.drawable.ic_dot_selected);
            }
            mDots.add(imageView);
        }
    }

    private void updatePoints(int index) {
        for (int i = 0; i < mDots.size(); i++) {
            if (index == i) {
                mDots.get(i).setBackgroundResource(R.drawable.ic_dot_selected);
            } else {
                mDots.get(i).setBackgroundResource(R.drawable.ic_dot_unselected);
            }
        }
    }
}

AddressAdapter.java

package com.yunjia.hud.adapter;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.amap.api.maps.AMapUtils;
import com.amap.api.maps.model.LatLng;
import com.amap.api.services.core.PoiItem;
import com.honghe.library.util.AMapUtil;
import com.honghe.library.util.ConstUtil;
import com.yunjia.hud.R;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by wanghh on 2017/5/11.
 */

public class AddressAdapter extends BaseAdapter {
    private Context mContext;
    private List<PoiItem> mDatas = new ArrayList<>();
    private int position;

    public AddressAdapter(Context context) {
        this.mContext = context;
    }

    public void setData(List<PoiItem> datas) {
        if (null != datas && datas.size() > 0) {
            this.mDatas.clear();
            this.mDatas.addAll(datas);
        }
        notifyDataSetChanged();
    }

    @Override
    public int getCount() {
        if (null != mDatas) {
            return mDatas.size();
        }
        return 0;
    }

    @Override
    public Object getItem(int position) {
        return mDatas.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    public void selectItem(int position) {
        this.position = position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder viewHolder;
        if (convertView == null) {
            convertView = LayoutInflater.from(mContext).inflate(R.layout.item_list_address, null);
            viewHolder = new ViewHolder();
            viewHolder.ll_item_background = (LinearLayout) convertView.findViewById(R.id.ll_item_background);
            viewHolder.tv_address_number = (TextView) convertView.findViewById(R.id.tv_address_number);
            viewHolder.tv_address_title = (TextView) convertView.findViewById(R.id.tv_address_title);
            viewHolder.tv_address_distance = (TextView) convertView.findViewById(R.id.tv_address_distance);
            viewHolder.tv_address_des = (TextView) convertView.findViewById(R.id.tv_address_des);
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }
        switch (position % 3) {
            case 0:
                viewHolder.tv_address_number.setTextColor(mContext.getResources().getColor(R.color.YunCircleBlue));
                viewHolder.tv_address_number.setBackgroundResource(R.drawable.shape_circle_blue);
                break;
            case 1:
                viewHolder.tv_address_number.setTextColor(mContext.getResources().getColor(R.color.YunCircleGreen));
                viewHolder.tv_address_number.setBackgroundResource(R.drawable.shape_circle_green);
                break;
            case 2:
                viewHolder.tv_address_number.setTextColor(mContext.getResources().getColor(R.color.YunCircleYellow));
                viewHolder.tv_address_number.setBackgroundResource(R.drawable.shape_circle_yellow);
                break;
        }
        if (position == this.position) {
            viewHolder.ll_item_background.setSelected(true);
        } else {
            viewHolder.ll_item_background.setSelected(false);
        }
        viewHolder.tv_address_number.setText("" + (position + 1));
        viewHolder.tv_address_title.setText(mDatas.get(position).getTitle());
        viewHolder.tv_address_distance.setText(AMapUtil.getLengthString((int) AMapUtils.calculateLineDistance(new LatLng(ConstUtil.currentLatitude, ConstUtil.currentLongitude), new LatLng(mDatas.get(position).getLatLonPoint().getLatitude(), mDatas.get(position).getLatLonPoint().getLongitude()))));
        viewHolder.tv_address_des.setText(mDatas.get(position).getSnippet());
        return convertView;
    }

    private class ViewHolder {
        LinearLayout ll_item_background;
        TextView tv_address_number;
        TextView tv_address_title;
        TextView tv_address_distance;
        TextView tv_address_des;
    }
}

ViewPagerListAdapter.java

package com.yunjia.hud.adapter;

import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.view.ViewGroup;

import java.util.List;

/**
 * Created by wanghh on 2017/5/11.
 */

public class ViewPagerListAdapter extends PagerAdapter {
    private List<View> pageViews;

    public ViewPagerListAdapter(List<View> pageViews) {
        super();
        this.pageViews = pageViews;
    }

    @Override
    public int getCount() {
        if (null != pageViews) {
            return pageViews.size();
        }
        return 0;
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == object;
    }

    @Override
    public int getItemPosition(Object object) {
        return super.getItemPosition(object);
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        ((ViewPager) container).removeView(pageViews.get(position));
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        ((ViewPager) container).addView(pageViews.get(position));
        return pageViews.get(position);
    }
}
原文地址:https://www.cnblogs.com/dongweiq/p/6842575.html