阅读目录
1.商品详情ui框架设计
1.1 自定义圆形控件
1.2 底部栏的布局
1.3 整体布局
2.商品详情UI-MD风格伸缩渐变效果实现
2.1 ui的绑定
2.2 服务器中商品详情页的数据的取出
3.商品详情页的中间信息的完善
4. 商品详情页下部滑动Tab页面的实现
4.2 填充的ImageDelegate和布局
4.4 商品详情页的ViewPager的适配器的设置
5.商品飞入购物车和逻辑梳理
5.1 动画的依赖
1.商品详情ui框架设计
【说明】点击商品之后跳转到商品的详情页面
1.1 自定义圆形控件
【源码】自定义圆形textView控件:com.flj.latte.ui.widget.CircleTextView1 package com.flj.latte.ui.widget; 2 3 import android.content.Context; 4 import android.graphics.Canvas; 5 import android.graphics.Color; 6 import android.graphics.Paint; 7 import android.graphics.PaintFlagsDrawFilter; 8 import android.support.annotation.ColorInt; 9 import android.support.v7.widget.AppCompatTextView; 10 import android.util.AttributeSet; 11 12 13 public class CircleTextView extends AppCompatTextView { 14 15 private final Paint PAINT; 16 private final PaintFlagsDrawFilter FILTER; 17 18 public CircleTextView(Context context) { 19 this(context, null); 20 } 21 22 public CircleTextView(Context context, AttributeSet attrs) { 23 super(context, attrs); 24 PAINT = new Paint(); 25 FILTER = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); 26 PAINT.setColor(Color.WHITE); 27 PAINT.setAntiAlias(true); 28 } 29 30 public final void setCircleBackground(@ColorInt int color) { 31 PAINT.setColor(color); 32 } 33 34 @Override 35 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 36 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 37 final int width = getMeasuredWidth(); 38 final int height = getMaxHeight(); 39 final int max = Math.max(width, height); 40 setMeasuredDimension(max, max); 41 } 42 43 @Override 44 public void draw(Canvas canvas) { 45 canvas.setDrawFilter(FILTER); 46 canvas.drawCircle(getWidth() / 2, getHeight() / 2, 47 Math.max(getWidth(), getHeight()) / 2, PAINT); 48 super.draw(canvas); 49 } 50 }
回到顶部
1.2 底部栏的布局
【源码】\d1nj4n\latte-ec\src\main\res\layout\layout_goods_detail_bottom.xml
1 <?xml version="1.0" encoding="utf-8"?> 2 <android.support.v7.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:tools="http://schemas.android.com/tools" 4 android:id="@+id/ll_bottom" 5 android:layout_width="match_parent" 6 android:layout_height="50dp" 7 android:layout_alignParentBottom="true" 8 android:baselineAligned="true" 9 android:orientation="horizontal"> 10 11 <RelativeLayout 12 android:id="@+id/rl_favor" 13 android:layout_width="0dp" 14 android:layout_height="match_parent" 15 android:layout_weight="1" 16 android:background="@android:color/white" 17 android:paddingBottom="5dp"> 18 19 <com.joanzapata.iconify.widget.IconTextView 20 android:id="@+id/icon_favor" 21 android:layout_width="match_parent" 22 android:layout_height="wrap_content" 23 android:layout_centerHorizontal="true" 24 android:layout_marginTop="10dp" 25 android:gravity="center" 26 android:text="{fa-heart-o}" 27 android:textSize="20sp" /> 28 29 <android.support.v7.widget.AppCompatTextView 30 android:layout_width="match_parent" 31 android:layout_height="wrap_content" 32 android:layout_alignParentBottom="true" 33 android:layout_centerHorizontal="true" 34 android:gravity="center" 35 android:text="喜欢" 36 android:textSize="12sp" /> 37 38 </RelativeLayout> 39 40 <RelativeLayout 41 android:id="@+id/rl_shop_cart" 42 android:layout_width="0dp" 43 android:layout_height="match_parent" 44 android:layout_weight="1" 45 android:background="@android:color/white" 46 android:paddingBottom="5dp"> 47 48 <com.joanzapata.iconify.widget.IconTextView 49 android:id="@+id/icon_shop_cart" 50 android:layout_width="match_parent" 51 android:layout_height="wrap_content" 52 android:layout_centerHorizontal="true" 53 android:layout_marginTop="10dp" 54 android:gravity="center" 55 android:text="{fa-shopping-cart}" 56 android:textSize="20sp" /> 57 58 <android.support.v7.widget.AppCompatTextView 59 android:layout_width="match_parent" 60 android:layout_height="wrap_content" 61 android:layout_alignParentBottom="true" 62 android:layout_centerHorizontal="true" 63 android:gravity="center" 64 android:text="购物车" 65 android:textSize="12sp" /> 66 67 <com.flj.latte.ui.widget.CircleTextView 68 android:id="@+id/tv_shopping_cart_amount" 69 android:layout_width="20dp" 70 android:layout_height="20dp" 71 android:layout_alignEnd="@+id/icon_shop_cart" 72 android:layout_alignParentTop="true" 73 android:layout_alignRight="@+id/icon_shop_cart" 74 android:layout_marginRight="20dp" 75 android:layout_marginTop="2dp" 76 android:gravity="center" 77 android:textColor="@android:color/white" 78 android:textSize="12sp" 79 tools:ignore="RtlHardcoded" /> 80 81 </RelativeLayout> 82 83 <RelativeLayout 84 android:id="@+id/rl_add_shop_cart" 85 android:layout_width="0dp" 86 android:layout_height="match_parent" 87 android:layout_weight="2" 88 android:background="@android:color/holo_orange_dark" 89 android:gravity="center_horizontal"> 90 91 <android.support.v7.widget.AppCompatTextView 92 android:layout_width="match_parent" 93 android:layout_height="match_parent" 94 android:layout_centerInParent="true" 95 android:gravity="center" 96 android:text="加入购物车" 97 android:textColor="@android:color/white" /> 98 99 </RelativeLayout> 100 </android.support.v7.widget.LinearLayoutCompat>
回到顶部
1.3 整体布局
【源码】d1nj4n\latte-ec\src\main\res\layout\delegate_goods_detail.xml
1 <?xml version="1.0" encoding="utf-8"?> 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:app="http://schemas.android.com/apk/res-auto" 4 android:layout_width="match_parent" 5 android:layout_height="match_parent"> 6 7 <android.support.design.widget.CoordinatorLayout //内容部分整体使用该布局抱起来 8 android:layout_width="match_parent" 9 android:layout_height="match_parent"> 10 11 <android.support.design.widget.AppBarLayout //商品详情:会随着整体滑动而滑动 12 android:id="@+id/app_bar_detail" 13 android:layout_width="match_parent" 14 android:layout_height="wrap_content"> 15 16 <android.support.design.widget.CollapsingToolbarLayout //可伸缩的toolbar,需要配合84行的behavior;必须套在appBarLayout中; 17 android:id="@+id/collapsing_toolbar_detail" 18 android:layout_width="match_parent" 19 android:layout_height="wrap_content" 20 app:layout_scrollFlags="scroll|exitUntilCollapsed" 21 app:statusBarScrim="@android:color/transparent"> 22 23 <RelativeLayout 24 android:layout_width="match_parent" 25 android:layout_height="wrap_content"> 26 27 <com.bigkoo.convenientbanner.ConvenientBanner 28 android:id="@+id/detail_banner" 29 android:layout_width="match_parent" 30 android:layout_height="260dp" /> 31 32 <android.support.v7.widget.ContentFrameLayout 33 android:id="@+id/frame_goods_info" 34 android:layout_width="match_parent" 35 android:layout_height="match_parent" 36 android:layout_below="@+id/detail_banner" /> 37 </RelativeLayout> 38 39 <!--要放在下面 否则CollapsingToolbarLayout 和 CoordinatorLayout不能正确的处理上下滑动的事件 --> 40 <android.support.v7.widget.Toolbar 41 android:id="@+id/goods_detail_toolbar" 42 android:layout_width="match_parent" 43 android:layout_height="?android:attr/actionBarSize" 44 app:layout_collapseMode="pin"> //此处的模式必须选择为:pin模式,否则无法上下折叠滑动 45 46 <RelativeLayout 47 android:layout_width="match_parent" 48 android:layout_height="match_parent"> 49 50 <com.joanzapata.iconify.widget.IconTextView 51 android:id="@+id/icon_goods_back" 52 android:layout_width="wrap_content" 53 android:layout_height="match_parent" 54 android:layout_marginLeft="12dp" 55 android:gravity="center" 56 android:text="{fa-chevron-left}" 57 android:textColor="@android:color/black" 58 android:textSize="26sp" /> 59 60 <android.support.v7.widget.AppCompatTextView 61 android:id="@+id/tv_detail_title_text" 62 android:layout_width="wrap_content" 63 android:layout_height="wrap_content" 64 android:layout_centerInParent="true" 65 android:text="商品详情" 66 android:textColor="@android:color/black" 67 android:textSize="20sp" /> 68 </RelativeLayout> 69 </android.support.v7.widget.Toolbar> 70 <!--如果将TabLayout写在这里,将透明--> 71 72 </android.support.design.widget.CollapsingToolbarLayout> 73 74 <android.support.design.widget.TabLayout 75 android:id="@+id/tab_layout" 76 android:layout_width="match_parent" 77 android:layout_height="?attr/actionBarSize" /> 78 </android.support.design.widget.AppBarLayout> 79 80 <android.support.v4.view.ViewPager 81 android:id="@+id/view_pager" 82 android:layout_width="match_parent" 83 android:layout_height="match_parent" 84 app:layout_behavior="@string/appbar_scrolling_view_behavior" /> 85 86 87 </android.support.design.widget.CoordinatorLayout> 88 89 <include layout="@layout/layout_goods_detail_bottom" /> 90 91 </RelativeLayout>
回到顶部
2.商品详情UI-MD风格伸缩渐变效果实现
回到顶部
2.1 ui的绑定
【说明】首先取出控件;
【商品详情页面的设置和布局】
【点击响应】【点击index页面的商品的按钮图标的点击响应】商品的id进行了传递,此处id就是json字符串中的id值;
【详情页面的数据】
【完善商品详情页】绑定ui;
回到顶部
2.2 服务器中商品详情页的数据的取出
【数据的返回】初始化数据;此处具有goods_id的参数;
【banner数据的取出】
回到顶部
3.商品详情页的中间信息的完善
【说明】布局使用的是frameLayout,内部会塞一个fragment,即delegate;
【好处】可以降低耦合度,可以改变其中的内容;
【新建fragment】
【布局】
1 <?xml version="1.0" encoding="utf-8"?> 2 <android.support.v7.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:background="@android:color/white" 6 android:orientation="vertical"> 7 8 <android.support.v7.widget.AppCompatTextView 9 android:id="@+id/tv_goods_info_title" 10 android:layout_width="match_parent" 11 android:layout_height="wrap_content" 12 android:layout_marginLeft="20dp" 13 android:layout_marginRight="20dp" 14 android:layout_marginTop="20dp" 15 android:textColor="@android:color/black" 16 android:textSize="18sp" /> 17 18 <android.support.v7.widget.AppCompatTextView 19 android:id="@+id/tv_goods_info_desc" 20 android:layout_width="match_parent" 21 android:layout_height="wrap_content" 22 android:layout_marginLeft="20dp" 23 android:layout_marginRight="20dp" 24 android:layout_marginTop="5dp" 25 android:textSize="16sp" /> 26 27 <android.support.v7.widget.LinearLayoutCompat 28 android:layout_width="match_parent" 29 android:layout_height="wrap_content" 30 android:orientation="horizontal"> 31 32 <android.support.v7.widget.AppCompatTextView 33 android:layout_width="wrap_content" 34 android:layout_height="wrap_content" 35 android:layout_marginLeft="20dp" 36 android:layout_marginTop="10dp" 37 android:text="¥" 38 android:textColor="@color/app_main" 39 android:textSize="20sp" /> 40 41 <android.support.v7.widget.AppCompatTextView 42 android:id="@+id/tv_goods_info_price" 43 android:layout_width="wrap_content" 44 android:layout_height="wrap_content" 45 android:layout_marginTop="10dp" 46 android:text="1299" 47 android:textColor="@color/app_main" 48 android:textSize="20sp" /> 49 </android.support.v7.widget.LinearLayoutCompat> 50 51 </android.support.v7.widget.LinearLayoutCompat>
【传递服务器中的data数据】
【取出数据值】
【设置数据值】
回到顶部
4. 商品详情页下部滑动Tab页面的实现
【需要将viewPager和TabLayout相应的adapter中将数据进行转化】达到映射数据和滑动变换的效果;
【传递数据】
【数据适配器--数据的取出】
回到顶部
4.2 填充的ImageDelegate和布局
【数据为空】当数据为空的时候,在页面中使用fragment进行填充,有利于解耦;
【使用recycleView布局处理下半部的数据】
【完善】
【正确的写法】上面的写法不正确;
【初始化images】fragment天生支持StringarrayList;此处没有进行转化,处理简单;
【recycleView中的item的布局】
【recycleView的数据适配器】
【使用ImageDelegate】
回到顶部
4.4 商品详情页的ViewPager的适配器的设置
回到顶部
5.商品飞入购物车和逻辑梳理
回到顶部
5.1 动画的依赖
【贝塞尔动画】使用别人的贝塞尔的动画库,经过了修改;
【源码】d1nj4n\latte-ui\src\main\java\com\flj\latte\ui\animation\BezierAnimation.java
1 package com.flj.latte.ui.animation; 2 3 import android.app.Activity; 4 import android.content.Context; 5 import android.graphics.drawable.Drawable; 6 import android.view.View; 7 import android.view.ViewGroup; 8 import android.view.animation.AccelerateInterpolator; 9 import android.view.animation.Animation; 10 import android.view.animation.AnimationSet; 11 import android.view.animation.DecelerateInterpolator; 12 import android.view.animation.TranslateAnimation; 13 import android.widget.ImageView; 14 import android.widget.LinearLayout; 15 16 import com.flj.latte.ui.R; 17 18 19 public final class BezierUtil { 20 21 static void startAnimationForJd(final View v, int fromXDelta, 22 int fromYDelta, int fx, int fy, int mx, int my, int tx, 23 int ty, final AnimationListener listener) { 24 final AnimationSet set = new AnimationSet(false); 25 final TranslateAnimation translateAnimation1 = new TranslateAnimation(fromXDelta, mx - fx, fromYDelta, my - fy); 26 translateAnimation1.setInterpolator(new DecelerateInterpolator()); 27 translateAnimation1.setRepeatCount(0); 28 translateAnimation1.setFillAfter(false); 29 set.addAnimation(translateAnimation1); 30 31 final TranslateAnimation translateAnimation2 = new TranslateAnimation(fromXDelta, tx - mx, fromYDelta, ty - my); 32 translateAnimation2.setInterpolator(new AccelerateInterpolator()); 33 translateAnimation2.setRepeatCount(0); 34 translateAnimation2.setFillAfter(false); 35 set.addAnimation(translateAnimation2); 36 set.setDuration(700); 37 set.setFillAfter(false); 38 set.setAnimationListener(new Animation.AnimationListener() { 39 @Override 40 public void onAnimationStart(Animation animation) { 41 v.setVisibility(View.VISIBLE); 42 } 43 44 @Override 45 public void onAnimationEnd(Animation animation) { 46 v.setVisibility(View.GONE); 47 if (listener != null) { 48 listener.onAnimationEnd(); 49 } 50 } 51 52 @Override 53 public void onAnimationRepeat(Animation animation) { 54 55 } 56 }); 57 58 v.startAnimation(set); 59 } 60 61 static ViewGroup createAnimLayout(Activity activity) { 62 final ViewGroup rootView = (ViewGroup) activity.getWindow().getDecorView(); 63 final LinearLayout animLayout = new LinearLayout(activity); 64 final LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams( 65 ViewGroup.LayoutParams.MATCH_PARENT, 66 ViewGroup.LayoutParams.MATCH_PARENT); 67 animLayout.setLayoutParams(lp); 68 animLayout.setId(Integer.MAX_VALUE - 1); 69 animLayout.setBackgroundResource(android.R.color.transparent); 70 rootView.addView(animLayout); 71 return animLayout; 72 } 73 74 static View addViewToAnimLayout(Context mContext, View view, int[] location, boolean wrap_content) { 75 if (view == null) return null; 76 int x = location[0]; 77 int y = location[1]; 78 final LinearLayout.LayoutParams params; 79 if (wrap_content) { 80 Drawable drawable = null; 81 if (view instanceof ImageView) { 82 drawable = ((ImageView) view).getDrawable(); 83 } 84 if (drawable == null) { 85 params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); 86 } else { 87 params = new LinearLayout.LayoutParams(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); 88 } 89 } else { 90 final int wh = mContext.getResources().getDimensionPixelSize(R.dimen.db_goods_wh); 91 params = new LinearLayout.LayoutParams(wh, wh); 92 } 93 params.leftMargin = x; 94 params.topMargin = y; 95 view.setLayoutParams(params); 96 return view; 97 } 98 99 public interface AnimationListener { 100 /** 101 * 处理动画结束后的逻辑,不要涉及动画相关的View 102 */ 103 void onAnimationEnd(); 104 } 105 }
【添加购物车的点击事件】
【】图片的url需要创建出来,获取值;同样 ,count值也需要处理;
【添加动画】
【BUG】添加购物车之后没有效果
【增加服务器返回数据的判断】在真实的环境中返回的数据是很多的,不是简单的true;
【效果】在加入购物车之后返回了服务器设置的值;