当前位置: 首页 > news >正文

移动app设计网站建设/国际域名注册网站

移动app设计网站建设,国际域名注册网站,网站建设代码,珠海本地网站设计公司序言 做电商的都知道,作为商品的一种售卖方式,拼团是是提供商品售卖的一种及时有效的方式,而在拼团市场中,拼多多无疑是做的最好的一家。于是,研究拼多多的售卖方式之后,我们的产品也开始了这方面的开发。本…

序言

做电商的都知道,作为商品的一种售卖方式,拼团是是提供商品售卖的一种及时有效的方式,而在拼团市场中,拼多多无疑是做的最好的一家。于是,研究拼多多的售卖方式之后,我们的产品也开始了这方面的开发。本文将要给大家介绍的就是通过自定义的方式实现堆叠头像,这种效果在直播app中非常常见。下面是部分效果:
这里写图片描述

通过分析,上面是一个使用ViewPager实现的一个可以左右无线循环的Galllery,相关实现可以访问我之前的介绍:PageTransformer使用简介
下面是一个列表的方式,可以通过下拉来加载更多的Cell数据,也比较简单。对于组合头像的实现也是比较简单的,其实就是一个简单的流式布局,在本篇实现上,本文也参考了张鸿洋的FlowLayout,对于流式布局来说,只要按照某种线性规则依次排列即可。

我相信很多朋友之前一定遇到过这种需求:富文本自动换行,如下所示:
这里写图片描述
要实现这种富文本换行,最重要的就是对onMeasure方法,通常的做法是,测量出子View的宽度,当大于屏幕的宽度的时候就换行(当然,需要考虑文字本来就很长,一行显示不下的情况)。相关代码如下:

@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);//AT_MOSTint width = 0;int height = 0;int rawWidth = 0;//当前行总宽度int rawHeight = 0;// 当前行高int count = getChildCount();for (int i = 0; i < count; i++) {View child = getChildAt(i);if(child.getVisibility() == GONE){if(i == count - 1){//最后一个childheight += rawHeight;width = Math.max(width, rawWidth);}continue;}measureChild(child, widthMeasureSpec, heightMeasureSpec);MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();int childWidth = child.getMeasuredWidth()  + lp.leftMargin + lp.rightMargin;int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;Log.e("=====", "childWidth 1: " + childWidth);if(rawWidth + childWidth > widthSpecSize - getPaddingLeft() - getPaddingRight()){//换行width = Math.max(width, rawWidth);rawWidth = childWidth;height += rawHeight;rawHeight = childHeight;} else {rawWidth += childWidth;rawHeight = Math.max(rawHeight, childHeight);}if(i == count - 1){width = Math.max(rawWidth, width);height += rawHeight;}}setMeasuredDimension(widthSpecMode == MeasureSpec.EXACTLY ? widthSpecSize : width + getPaddingLeft() + getPaddingRight(),heightSpecMode == MeasureSpec.EXACTLY ? heightSpecSize : height + getPaddingTop() + getPaddingBottom());}

实现

说了这么多,那么具体怎么实现的呢?由于时间关系,这里我就直接贴代码了。首先自定义ViewGrop,实现后一个头像会覆盖一部分到前一个头像上,为了方便使用者控制堆叠头像的重叠大小,我们通过自定义属性来解决。

PileView.java

public class PileView extends ViewGroup {protected float vertivalSpace;//垂直间隙protected float pileWidth=0;//重叠宽度public PileView(Context context) {this(context, null, 0);}public PileView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public PileView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);initAttr(context, attrs);}private void initAttr(Context context, AttributeSet attrs) {TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.PileLayout);vertivalSpace = ta.getDimension(R.styleable.PileLayout_PileLayout_vertivalSpace, dp2px(4));pileWidth = ta.getDimension(R.styleable.PileLayout_PileLayout_pileWidth, dp2px(10));ta.recycle();}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);//AT_MOSTint width = 0;int height = 0;int rawWidth = 0;//当前行总宽度int rawHeight = 0;// 当前行高int rowIndex = 0;//当前行位置int count = getChildCount();for (int i = 0; i < count; i++) {View child = getChildAt(i);if(child.getVisibility() == GONE){if(i == count - 1){//最后一个childheight += rawHeight;width = Math.max(width, rawWidth);}continue;}//调用measureChildWithMargins 而不是measureChildmeasureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();int childWidth = child.getMeasuredWidth()  + lp.leftMargin + lp.rightMargin;int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;if(rawWidth + childWidth  - (rowIndex > 0 ? pileWidth : 0)> widthSpecSize - getPaddingLeft() - getPaddingRight()){//换行width = Math.max(width, rawWidth);rawWidth = childWidth;height += rawHeight + vertivalSpace;rawHeight = childHeight;rowIndex = 0;} else {rawWidth += childWidth;if(rowIndex > 0){rawWidth -= pileWidth;}rawHeight = Math.max(rawHeight, childHeight);}if(i == count - 1){width = Math.max(rawWidth, width);height += rawHeight;}rowIndex++;}setMeasuredDimension(widthSpecMode == MeasureSpec.EXACTLY ? widthSpecSize : width + getPaddingLeft() + getPaddingRight(),heightSpecMode == MeasureSpec.EXACTLY ? heightSpecSize : height + getPaddingTop() + getPaddingBottom());}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {int viewWidth = r - l;int leftOffset = getPaddingLeft();int topOffset = getPaddingTop();int rowMaxHeight = 0;int rowIndex = 0;//当前行位置View childView;for( int w = 0, count = getChildCount(); w < count; w++ ){childView = getChildAt(w);if(childView.getVisibility() == GONE) continue;MarginLayoutParams lp = (MarginLayoutParams) childView.getLayoutParams();// 如果加上当前子View的宽度后超过了ViewGroup的宽度,就换行int occupyWidth = lp.leftMargin + childView.getMeasuredWidth() + lp.rightMargin;if(leftOffset + occupyWidth + getPaddingRight() > viewWidth){leftOffset = getPaddingLeft();  // 回到最左边topOffset += rowMaxHeight + vertivalSpace;  // 换行rowMaxHeight = 0;rowIndex = 0;}int left = leftOffset + lp.leftMargin;int top = topOffset + lp.topMargin;int right = leftOffset+ lp.leftMargin + childView.getMeasuredWidth();int bottom =  topOffset + lp.topMargin + childView.getMeasuredHeight();childView.layout(left, top, right, bottom);// 横向偏移leftOffset += occupyWidth;// 试图更新本行最高View的高度int occupyHeight = lp.topMargin + childView.getMeasuredHeight() + lp.bottomMargin;if(rowIndex != count - 1){leftOffset -= pileWidth;}rowMaxHeight = Math.max(rowMaxHeight, occupyHeight);rowIndex++;}}@Overridepublic LayoutParams generateLayoutParams(AttributeSet attrs) {return new MarginLayoutParams(getContext(), attrs);}@Overrideprotected LayoutParams generateDefaultLayoutParams() {return new MarginLayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);}@Overrideprotected LayoutParams generateLayoutParams(LayoutParams p) {return new MarginLayoutParams(p);}public float dp2px(float dpValue) {return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpValue, getResources().getDisplayMetrics());}
}

自定义的属性如下:

<declare-styleable name="PileLayout"><attr name="PileLayout_vertivalSpace" format="dimension"/><attr name="PileLayout_pileWidth" format="dimension"/></declare-styleable>

为了方便用户使用,我们在PileView的基础上再封装一下,封装完成后,只需要用户提供数据源即可实现头像堆叠。例如,下面的代码给控件设置数据源即可:

List<String> urls=new ArrayList<>();urls.clear();urls.add("http://ohe65w0xx.bkt.clouddn.com/u=2263418180,3668836868&fm=206&gp=0.jpg");urls.add("http://ohe65w0xx.bkt.clouddn.com/u=3637404049,2821183587&fm=214&gp=0.jpg");urls.add("http://ohe65w0xx.bkt.clouddn.com/avert.png");
//设置数据源
itemAvertView.setAvertImages(urls);

要完成上面的封装,主要会涉及如下的代码:
PileAvertView.java

public class PileAvertView extends LinearLayout {@BindView(R.id.pile_view)PileView pileView;private Context context = null;public static final int VISIBLE_COUNT = 3;//默认显示个数public PileAvertView(Context context) {this(context, null);this.context = context;}public PileAvertView(Context context, AttributeSet attrs) {super(context, attrs);this.context = context;initView();}private void initView() {View view = LayoutInflater.from(context).inflate(R.layout.layout_group_pile_avert, this);ButterKnife.bind(view);}public void setAvertImages(List<String> imageList) {setAvertImages(imageList,VISIBLE_COUNT);}//如果imageList>visiableCount,显示List最上面的几个public void setAvertImages(List<String> imageList, int visibleCount) {List<String> visibleList = null;if (imageList.size() > visibleCount) {visibleList = imageList.subList(imageList.size() - 1 - visibleCount, imageList.size() - 1);}pileView.removeAllViews();for (int i = 0; i < imageList.size(); i++) {CircleImageView image= (CircleImageView) LayoutInflater.from(context).inflate(R.layout.item_group_round_avert, pileView, false);CommonImageUtil.loadImage(imageList.get(i), image);pileView.addView(image);}}}

相关的布局:
layout_group_pile_avert.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="match_parent"android:gravity="center_horizontal"><com.lanshan.shihuicommunity.grouppurchase.view.PileViewandroid:id="@+id/pile_view"android:layout_width="wrap_content"android:layout_height="wrap_content"app:PileLayout_pileWidth="10dp"/>
</LinearLayout>

item_group_round_avert.xml

<?xml version="1.0" encoding="utf-8"?>
<com.makeramen.rounded.CircleImageView xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:id="@+id/circle_iamge"android:layout_width="30dp"android:layout_height="30dp"android:orientation="vertical"app:round_borderColor="#ffffff"app:round_borderWidth="1dp" />

相关文章:

  • 威远移动网站建设/seo排名优化软件有用
  • java网站做微信分享/陕西网站建设网络公司
  • 东莞常平医院网站建设/深圳营销策划公司十强
  • 自己如何做网站建设/seo外链购买
  • 郑州网站建设网站开发/网络营销ppt案例
  • 邯郸网站建设浩森宇特/经典软文案例分析
  • 福州网站建设联系时事在/苏州百度快照优化排名
  • 舟山企业网站建设/网址大全下载
  • 六盘水网站建设/搜索引擎入口yandex
  • 网站建设多少钱一年/站长工具无内鬼放心开车禁止收费
  • 温州网站建设大全/网站关键词查询网址
  • 思帽西宁网站建设/排名轻松seo 网站推广