云炬Android开发笔记 15评价晒单功能实现(自定义评分控件和仿微信自动多图选择控件)
閱讀目錄
1. 曬單評(píng)價(jià)
1.1 點(diǎn)擊頁(yè)面跳轉(zhuǎn)的實(shí)現(xiàn)
1.2 自定義評(píng)價(jià)訂單的布局實(shí)現(xiàn)
1.3 星星布局的實(shí)現(xiàn)
2. 仿微信自動(dòng)多圖及刪除控件
2.1 屬性值及控件的定義
2.2 圖片初始化方法onMearsure()方法
2.3 【設(shè)置避免重復(fù)測(cè)量的onMeasure()】
2.4??onLayout()方法的書寫
3. 對(duì)加號(hào)增加圖片事件的響應(yīng)
3.1 增加圖片
?3.2 增加對(duì)圖片的刪除功能
?
?
?
- ?
回到頂部
1. 曬單評(píng)價(jià)
回到頂部
1.1 點(diǎn)擊頁(yè)面跳轉(zhuǎn)的實(shí)現(xiàn)
【說(shuō)明】布局會(huì)使用自定義控件;
?
【點(diǎn)擊事件的處理】
?
【效果】
?
回到頂部
1.2 自定義評(píng)價(jià)訂單的布局實(shí)現(xiàn)
1 <?xml version="1.0" encoding="utf-8"?>2 <LinearLayout 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 android:orientation="vertical">7 8 <android.support.v7.widget.Toolbar9 android:id="@+id/tb_shop_cart" 10 android:layout_width="match_parent" 11 android:layout_height="75dp" 12 android:background="@android:color/holo_orange_dark" 13 android:gravity="center"> 14 15 <android.support.v7.widget.AppCompatTextView 16 android:layout_width="wrap_content" 17 android:layout_height="wrap_content" 18 android:layout_gravity="center" 19 android:text="評(píng)價(jià)曬單" 20 android:textColor="@android:color/white" 21 android:textSize="20sp" /> 22 23 <android.support.v7.widget.AppCompatTextView 24 android:id="@+id/top_tv_comment_commit" 25 android:layout_width="wrap_content" 26 android:layout_height="wrap_content" 27 android:layout_gravity="right" 28 android:layout_marginRight="20dp" 29 android:text="提交" 30 android:textColor="@android:color/white" 31 android:textSize="20sp" /> 32 </android.support.v7.widget.Toolbar> 33 34 <RelativeLayout 35 android:layout_width="match_parent" 36 android:layout_height="100dp"> 37 38 <android.support.v7.widget.AppCompatImageView 39 android:id="@+id/img_order_comment" 40 android:layout_width="80dp" 41 android:layout_height="80dp" 42 android:layout_centerVertical="true" 43 android:layout_marginLeft="10dp" /> 44 45 <TextView 46 android:id="@+id/tv_comment_title" 47 android:layout_width="wrap_content" 48 android:layout_height="wrap_content" 49 android:layout_marginLeft="20dp" 50 android:layout_marginTop="10dp" 51 android:layout_toRightOf="@id/img_order_comment" 52 android:text="評(píng)分" 53 android:textColor="#323232" /> 54 55 <com.flj.latte.ui.widget.StarLayout 56 android:id="@+id/custom_star_layout" 57 android:layout_width="match_parent" 58 android:layout_height="match_parent" 59 android:layout_below="@+id/tv_comment_title" 60 android:layout_toRightOf="@id/img_order_comment" /> 61 62 </RelativeLayout> 63 64 <android.support.v7.widget.AppCompatEditText 65 android:id="@+id/et_order_comment" 66 android:layout_width="match_parent" 67 android:layout_height="120dp" 68 android:background="@android:color/white" 69 android:gravity="top|left" 70 android:hint="寫下評(píng)論" 71 android:padding="10dp" /> 72 73 <com.flj.latte.ui.widget.AutoPhotoLayout 74 android:id="@+id/custom_auto_photo_layout" 75 android:layout_width="wrap_content" 76 android:layout_height="wrap_content" 77 app:icon_size="10sp" 78 app:item_margin="3" 79 app:line_count="5" 80 app:max_count="5" /> 81 82 </LinearLayout>?回到頂部
1.3 星星布局的實(shí)現(xiàn)
?
1 package com.flj.latte.ui.widget;2 3 import android.content.Context;4 import android.graphics.Color;5 import android.support.v7.widget.LinearLayoutCompat;6 import android.util.AttributeSet;7 import android.view.Gravity;8 import android.view.View;9 import android.view.ViewGroup;10 11 import com.flj.latte.ui.R;12 import com.joanzapata.iconify.widget.IconTextView;13 14 import java.util.ArrayList;15 16 17 public class StarLayout extends LinearLayoutCompat implements View.OnClickListener {18 19 private static final CharSequence ICON_UN_SELECT = "{fa-star-o}"; //空心圖標(biāo)20 private static final CharSequence ICON_SELECTED = "{fa-star}"; //實(shí)心圖標(biāo)21 private static final int STAR_TOTAL_COUNT = 5; //星星的數(shù)量22 private static final ArrayList<IconTextView> STARS = new ArrayList<>();23 24 public StarLayout(Context context) {25 this(context, null);26 }27 28 public StarLayout(Context context, AttributeSet attrs) {29 this(context, attrs, 0);30 }31 32 public StarLayout(Context context, AttributeSet attrs, int defStyleAttr) {33 super(context, attrs, defStyleAttr);34 initStarIcon();35 }36 //初始化星星37 private void initStarIcon() {38 for (int i = 0; i < STAR_TOTAL_COUNT; i++) {39 final IconTextView star = new IconTextView(getContext());40 star.setGravity(Gravity.CENTER);41 final LayoutParams lp =42 new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,43 ViewGroup.LayoutParams.MATCH_PARENT);44 lp.weight = 1;45 star.setLayoutParams(lp);46 star.setText(ICON_UN_SELECT);47 star.setTag(R.id.star_count, i);48 star.setTag(R.id.star_is_select, false); //默認(rèn)沒有選中49 star.setOnClickListener(this);50 STARS.add(star); //創(chuàng)建的星星放到布局中;51 this.addView(star); //加到布局中;52 }53 }54 55 public int getStarCount() {56 int count = 0;57 for (int i = 0; i < STAR_TOTAL_COUNT; i++) {58 final IconTextView star = STARS.get(i);59 final boolean isSelect = (boolean) star.getTag(R.id.star_is_select);60 if (isSelect) {61 count++;62 }63 }64 return count;65 }66 67 private void selectStar(int count) {68 for (int i = 0; i <= count; i++) {69 if (i <= count) {70 final IconTextView star = STARS.get(i);71 star.setText(ICON_SELECTED);72 star.setTextColor(Color.RED);73 star.setTag(R.id.star_is_select, true);74 }75 }76 }77 78 private void unSelectStar(int count) {79 for (int i = 0; i < STAR_TOTAL_COUNT; i++) {80 if (i >= count) {81 final IconTextView star = STARS.get(i);82 star.setText(ICON_UN_SELECT);83 star.setTextColor(Color.GRAY);84 star.setTag(R.id.star_is_select, false);85 }86 }87 }88 89 @Override90 public void onClick(View v) {91 final IconTextView star = (IconTextView) v;92 //獲取第幾個(gè)星星93 final int count = (int) star.getTag(R.id.star_count);94 //獲取點(diǎn)擊狀態(tài)95 final boolean isSelect = (boolean) star.getTag(R.id.star_is_select);96 if (!isSelect) {97 selectStar(count);98 } else {99 unSelectStar(count); 100 } 101 } 102 }?
【效果】1-評(píng)價(jià)星星點(diǎn)擊選擇的效果.gif
?
回到頂部
2. 仿微信自動(dòng)多圖及刪除控件
回到頂部
2.1 屬性值及控件的定義
【屬性值的定義】
【使用屬性值】
?
【為加號(hào)增加包邊】
?
【加號(hào)按鈕的設(shè)置和布局】
?
回到頂部
2.2 圖片初始化方法onMearsure()方法
1 package com.flj.latte.ui.widget;2 3 import android.content.Context;4 import android.content.res.TypedArray;5 import android.graphics.Color;6 import android.graphics.drawable.ColorDrawable;7 import android.net.Uri;8 import android.support.v7.app.AlertDialog;9 import android.support.v7.widget.AppCompatImageView;10 import android.support.v7.widget.LinearLayoutCompat;11 import android.util.AttributeSet;12 import android.view.Gravity;13 import android.view.View;14 import android.view.Window;15 import android.view.WindowManager;16 import android.view.animation.AlphaAnimation;17 18 import com.bumptech.glide.Glide;19 import com.bumptech.glide.load.engine.DiskCacheStrategy;20 import com.bumptech.glide.request.RequestOptions;21 import com.flj.latte.delegates.LatteDelegate;22 import com.flj.latte.ui.R;23 import com.joanzapata.iconify.widget.IconTextView;24 25 import java.util.ArrayList;26 27 public final class AutoPhotoLayout extends LinearLayoutCompat {28 29 private int mCurrentNum = 0; //首先判斷是第幾張圖片30 private final int mMaxNum; //最大容許多少?gòu)垐D片;31 private final int mMaxLineNum; //一行圖片的數(shù)量;32 private IconTextView mIconAdd = null; //增加圖片的按鈕,是一張圖片;33 private LayoutParams mParams = null; //公共的一些屬性值;34 35 /**36 * 【效果】如果添加了圖片,要?jiǎng)h除圖片,則會(huì)彈出dialog,刪除之后“加號(hào)按鈕”會(huì)自動(dòng)向前移動(dòng);37 */38 //要?jiǎng)h除的圖片ID39 private int mDeleteId = 0;40 private AppCompatImageView mTargetImageVew = null; //選中的圖片;41 private final int mImageMargin; //圖片的間距42 private LatteDelegate mDelegate = null; //對(duì)圖片的操作43 private ArrayList<View> mLineViews = null; //將每行增加的圖片存在arraylist中;44 private AlertDialog mTargetDialog = null; //刪除圖片的確認(rèn)框;45 private static final String ICON_TEXT = "{fa-plus}"; //加號(hào)圖標(biāo);46 private final float mIconSize; //加號(hào)圖標(biāo)的大小;47 //存儲(chǔ)所有的View;存儲(chǔ)方式是一行一行存儲(chǔ)的;如果有兩行就存儲(chǔ)兩行所有的View;48 private final ArrayList<ArrayList<View>> ALL_VIEWS = new ArrayList<>();49 private final ArrayList<Integer> LINE_HEIGHTS = new ArrayList<>(); //存儲(chǔ)每一個(gè)行的高度;50 51 52 53 //防止多次的測(cè)量和布局過(guò)程54 private boolean mIsOnceInitOnMeasure = false;55 private boolean mHasInitOnLayout = false;56 57 private static final RequestOptions OPTIONS = new RequestOptions()58 .centerCrop()59 .diskCacheStrategy(DiskCacheStrategy.NONE);60 61 public AutoPhotoLayout(Context context) {62 this(context, null);63 }64 65 public AutoPhotoLayout(Context context, AttributeSet attrs) {66 this(context, attrs, 0);67 }68 69 public AutoPhotoLayout(Context context, AttributeSet attrs, int defStyleAttr) {70 super(context, attrs, defStyleAttr);71 //從定義的attr.xml中將值取出;72 final TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.camera_flow_layout);73 mMaxNum = typedArray.getInt(R.styleable.camera_flow_layout_max_count, 1);74 mMaxLineNum = typedArray.getInt(R.styleable.camera_flow_layout_line_count, 3); //一行中什么都沒有傳遞,則默認(rèn)值是3個(gè)“加號(hào)”75 mImageMargin = typedArray.getInt(R.styleable.camera_flow_layout_item_margin, 0); //無(wú)圖片上傳,則默認(rèn)沒有間隙;76 mIconSize = typedArray.getDimension(R.styleable.camera_flow_layout_icon_size, 20); //無(wú)圖片,則默認(rèn)是20的大小;77 typedArray.recycle(); //回收typedArray,防止內(nèi)存泄露;78 }79 80 public final void setDelegate(LatteDelegate delegate) {81 this.mDelegate = delegate;82 }83 84 public final void onCropTarget(Uri uri) {85 createNewImageView();86 Glide.with(mDelegate)87 .load(uri)88 .apply(OPTIONS)89 .into(mTargetImageVew);90 }162 163 @Override 164 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 165 final int sizeWith = MeasureSpec.getSize(widthMeasureSpec); 166 final int modeWith = MeasureSpec.getMode(widthMeasureSpec); 167 final int sizeHeight = MeasureSpec.getSize(heightMeasureSpec); 168 final int modeHeight = MeasureSpec.getMode(heightMeasureSpec); 169 //wrap_content 170 int width = 0; 171 int height = 0; 172 //記錄每一行的寬度與高度 173 int lineWith = 0; 174 int lineHeight = 0; 175 //得到內(nèi)部元素個(gè)數(shù) 176 int cCount = getChildCount(); 177 for (int i = 0; i < cCount; i++) { 178 final View child = getChildAt(i); 179 //測(cè)量子View的寬和高 180 measureChild(child, widthMeasureSpec, heightMeasureSpec); 181 //的搭配LayoutParams 182 final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams(); 183 //子View占據(jù)的寬度 184 final int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin; 185 //子View占據(jù)的高度 186 final int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin; 187 //開始換行 188 if (lineWith + childWidth > sizeWith - getPaddingLeft() - getPaddingRight()) { 189 //對(duì)比得到最大寬度 190 width = Math.max(width, lineWith); 191 //重置lineWidth 192 lineWith = childWidth; 193 height += lineHeight; 194 lineHeight = childHeight; 195 } else { 196 //未換行 197 //疊加行寬 198 lineWith += childWidth; 199 //得到當(dāng)前最大的高度 200 lineHeight = Math.max(lineHeight, childHeight); 201 } 202 //最后一個(gè)子控件 203 if (i == cCount - 1) { 204 width = Math.max(lineWith, width); 205 //判斷是否超過(guò)最大拍照限制 206 height += lineHeight; 207 } 208 } 209 setMeasuredDimension( 210 modeWith == MeasureSpec.EXACTLY ? sizeWith : width + getPaddingLeft() + getPaddingRight(), 211 modeHeight == MeasureSpec.EXACTLY ? sizeHeight : height + getPaddingTop() + getPaddingBottom() 212 ); 213 //設(shè)置一行所有圖片的寬高 214 final int imageSideLen = sizeWith / mMaxLineNum; 215 //只初始化一次 216 if (!mIsOnceInitOnMeasure) { 217 mParams = new LayoutParams(imageSideLen, imageSideLen); 218 mIsOnceInitOnMeasure = true; 219 } 220 } 221回到頂部
2.3 【設(shè)置避免重復(fù)測(cè)量的onMeasure()】
?
【設(shè)置boolean值】
回到頂部
2.4? onLayout()方法的書寫
?【需要防止多次布局】
1 @Override2 protected void onLayout(boolean changed, int l, int t, int r, int b) {3 ALL_VIEWS.clear(); //清楚掉所有的之前的尺寸和參數(shù);4 LINE_HEIGHTS.clear();5 // 當(dāng)前ViewGroup的寬度 聲明需要使用的變量6 final int width = getWidth();7 int lineWidth = 0;8 int lineHeight = 0;9 if (!mHasInitOnLayout) { 10 mLineViews = new ArrayList<>(); 11 mHasInitOnLayout = true; 12 } 13 final int cCount = getChildCount(); 14 for (int i = 0; i < cCount; i++) { 15 final View child = getChildAt(i); 16 final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams(); 17 final int childWith = child.getMeasuredWidth(); 18 final int childHeight = child.getMeasuredHeight(); 19 //如果需要換行 20 if (childWith + lineWidth + lp.leftMargin + lp.rightMargin > 21 width - getPaddingLeft() - getPaddingRight()) { 22 //記錄lineHeight 23 LINE_HEIGHTS.add(lineHeight); 24 //記錄當(dāng)前一行的Views 25 ALL_VIEWS.add(mLineViews); 26 //重置寬和高 27 lineWidth = 0; 28 lineHeight = childHeight + lp.topMargin + lp.bottomMargin; 29 //重置View集合 30 mLineViews.clear(); 31 } 32 lineWidth += childWith + lp.leftMargin + lp.rightMargin; 33 lineHeight = Math.max(lineHeight, lineHeight + lp.topMargin + lp.bottomMargin); 34 mLineViews.add(child); 35 } 36 //處理最后一行 37 LINE_HEIGHTS.add(lineHeight); 38 ALL_VIEWS.add(mLineViews); 39 //設(shè)置子View位置 40 int left = getPaddingLeft(); 41 int top = getPaddingTop(); 42 //行數(shù) 43 final int lineNum = ALL_VIEWS.size(); 44 for (int i = 0; i < lineNum; i++) { 45 //當(dāng)前行所有的View 46 mLineViews = ALL_VIEWS.get(i); 47 lineHeight = LINE_HEIGHTS.get(i); 48 final int size = mLineViews.size(); 49 for (int j = 0; j < size; j++) { 50 final View child = mLineViews.get(j); 51 //判斷child的狀態(tài) 52 if (child.getVisibility() == GONE) { 53 continue; 54 } 55 final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams(); 56 //設(shè)置子View的邊距 57 final int lc = left + lp.leftMargin; 58 final int tc = top + lp.topMargin; 59 final int rc = lc + child.getMeasuredWidth() - mImageMargin; 60 final int bc = tc + child.getMeasuredHeight(); 61 //為子View進(jìn)行布局 62 child.layout(lc, tc, rc, bc); 63 left += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin; 64 } 65 left = getPaddingLeft(); 66 top += lineHeight; 67 } 68 mIconAdd.setLayoutParams(mParams); 69 mHasInitOnLayout = false; 70 }回到頂部
3. 對(duì)加號(hào)增加圖片事件的響應(yīng)
回到頂部
3.1 增加圖片
【創(chuàng)建圖片和對(duì)圖片的剪裁】
?
?
【效果】可以增加兩種圖片,但是不能刪除;
回到頂部
?3.2 增加對(duì)圖片的刪除功能
?【刪除圖片的對(duì)話框的布局】
1 <?xml version="1.0" encoding="utf-8"?>2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"3 android:layout_width="match_parent"4 android:layout_height="wrap_content"5 android:layout_gravity="center"6 android:layout_marginLeft="10dp"7 android:layout_marginRight="10dp"8 android:background="@android:color/transparent"9 android:orientation="vertical" 10 android:paddingBottom="10dp"> 11 12 <Button 13 android:id="@+id/dialog_image_clicked_btn_delete" 14 android:layout_width="match_parent" 15 android:layout_height="50dp" 16 android:background="@drawable/btn_border_takephoto" 17 android:gravity="center" 18 android:text="刪除" 19 android:textColor="#323232" /> 20 21 <View 22 android:layout_width="match_parent" 23 android:layout_height="0.5dp" 24 android:layout_gravity="center" 25 android:background="@android:color/transparent" 26 android:gravity="center" /> 27 28 29 <Button 30 android:id="@+id/dialog_image_clicked_btn_undetermined" 31 android:layout_width="match_parent" 32 android:layout_height="50dp" 33 android:layout_gravity="center" 34 android:background="@drawable/btn_border_nativephoto" 35 android:text="待定" 36 android:textColor="#323232" /> 37 38 <View 39 android:layout_width="match_parent" 40 android:layout_height="10dp" 41 android:layout_gravity="center" 42 android:background="@android:color/transparent" 43 android:gravity="center" /> 44 45 <Button 46 android:id="@+id/dialog_image_clicked_btn_cancel" 47 android:layout_width="match_parent" 48 android:layout_height="50dp" 49 android:layout_gravity="center" 50 android:background="@drawable/btn_border" 51 android:text="取消" 52 android:textColor="#323232" /> 53 54 </LinearLayout>?
?
1 private void createNewImageView() {2 mTargetImageVew = new AppCompatImageView(getContext());3 mTargetImageVew.setId(mCurrentNum);4 mTargetImageVew.setLayoutParams(mParams);5 mTargetImageVew.setOnClickListener(new OnClickListener() {6 @Override7 public void onClick(View v) {8 //獲取要?jiǎng)h除的圖片ID9 mDeleteId = v.getId(); 10 mTargetDialog.show(); 11 final Window window = mTargetDialog.getWindow(); 12 if (window != null) { 13 window.setContentView(R.layout.dialog_image_click_panel); 14 window.setGravity(Gravity.BOTTOM); 15 window.setWindowAnimations(R.style.anim_panel_up_from_bottom); 16 window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); 17 final WindowManager.LayoutParams params = window.getAttributes(); 18 params.width = WindowManager.LayoutParams.MATCH_PARENT; 19 params.flags = WindowManager.LayoutParams.FLAG_DIM_BEHIND; 20 params.dimAmount = 0.5f; 21 window.setAttributes(params); 22 window.findViewById(R.id.dialog_image_clicked_btn_delete) //刪除按鈕的事件 23 .setOnClickListener(new OnClickListener() { 24 @Override 25 public void onClick(View v) { 26 //得到要?jiǎng)h除的圖片 27 final AppCompatImageView deleteImageViwe = 28 (AppCompatImageView) findViewById(mDeleteId); 29 //設(shè)置圖片逐漸消失的動(dòng)畫 30 final AlphaAnimation animation = new AlphaAnimation(1, 0); 31 animation.setDuration(500); 32 animation.setRepeatCount(0); 33 animation.setFillAfter(true); 34 animation.setStartOffset(0); 35 deleteImageViwe.setAnimation(animation); 36 animation.start(); 37 AutoPhotoLayout.this.removeView(deleteImageViwe); 38 mCurrentNum -= 1; 39 //當(dāng)數(shù)目達(dá)到上限時(shí)隱藏添加按鈕,不足時(shí)顯示 40 if (mCurrentNum < mMaxNum) { 41 mIconAdd.setVisibility(VISIBLE); 42 } 43 mTargetDialog.cancel(); 44 } 45 }); 46 window.findViewById(R.id.dialog_image_clicked_btn_undetermined) 47 .setOnClickListener(new OnClickListener() { 48 @Override 49 public void onClick(View v) { 50 mTargetDialog.cancel(); 51 } 52 }); 53 window.findViewById(R.id.dialog_image_clicked_btn_cancel) //取消按鈕的事件 54 .setOnClickListener(new OnClickListener() { 55 @Override 56 public void onClick(View v) { 57 mTargetDialog.cancel(); 58 } 59 }); 60 } 61 } 62 }); 63 //添加子View的時(shí)候傳入位置 64 this.addView(mTargetImageVew, mCurrentNum); 65 mCurrentNum++; 66 //當(dāng)添加數(shù)目大于mMaxNum時(shí),自動(dòng)隱藏添加按鈕 67 if (mCurrentNum >= mMaxNum) { 68 mIconAdd.setVisibility(View.GONE); 69 } 70 }?
?
總結(jié)
以上是生活随笔為你收集整理的云炬Android开发笔记 15评价晒单功能实现(自定义评分控件和仿微信自动多图选择控件)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 程序员每天少吃 能活120岁
- 下一篇: android sina oauth2.