今天折腾了半天自定义控件的问题,如下图所示,我们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); } }