写这个小Demo,也是因为刚好手里没什么事然后看到很多朋友还在好奇这个阻尼界面效果,还有自定义标签,其实这个标签因为现在Google已经有推出更好使用的东西可以替代,那就是“FlexboxLayout”,关于“FlexboxLayout”我之前的文章也介绍过。不清楚的可以回过去看下。关于titleBar的显示和隐藏,其实就是当我们在触摸滑动的时候,监听就可以了。这里贴出来,就是希望和大家共同学习,OK,先看效果吧。

布局文件activity_main:

 <?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"> <com.example.administrator.sbdemo.MyScrollView
android:id="@+id/scrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"> <RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"> <ImageView
android:id="@+id/img"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_gravity="center"
android:scaleType="centerCrop"
android:src="@mipmap/fj" /> <TextView
android:id="@+id/companyName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/img"
android:layout_centerInParent="true"
android:layout_marginTop="10dp"
android:text="@string/company"
android:textColor="@android:color/black"
android:textSize="18sp"
android:textStyle="bold" /> <LinearLayout
android:id="@+id/informationLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/companyName"
android:layout_centerInParent="true"
android:layout_marginTop="8dp"
android:orientation="horizontal"> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/companyNumber" /> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:drawableLeft="@mipmap/pos"
android:drawablePadding="3dp"
android:paddingBottom="7dp"
android:paddingTop="7dp"
android:text="@string/address" />
</LinearLayout> <LinearLayout
android:id="@+id/senLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/informationLayout"
android:layout_centerInParent="true"
android:orientation="horizontal"> <TextView
android:id="@+id/senP"
style="@style/tv_style"
android:layout_marginRight="8dp"
android:text="@string/senProject"
android:textColor="@android:color/white" /> <TextView
style="@style/tv_style"
android:layout_marginLeft="8dp"
android:text="@string/senInformation"
android:textColor="@android:color/white" />
</LinearLayout> <View
android:id="@+id/line"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_below="@+id/senLayout"
android:layout_marginTop="30dp"
android:background="@android:color/darker_gray" /> <TextView
android:id="@+id/he"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/line"
android:layout_marginLeft="10dp"
android:layout_marginTop="12dp"
android:text="@string/heProject"
android:textColor="@android:color/black"
android:textSize="17sp"
android:textStyle="bold" /> <LinearLayout
android:id="@+id/evaluateLayout" android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/he"
android:layout_marginLeft="10dp"
android:orientation="horizontal"> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginBottom="10dp"
android:layout_marginTop="10dp"
android:text="@string/evaluate"
android:textColor="@android:color/black"
android:textSize="17sp" /> <RatingBar
style="?android:attr/ratingBarStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="30dp"
android:isIndicator="false" />
</LinearLayout> <com.example.administrator.sbdemo.FLayout
android:id="@+id/fl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/evaluateLayout"
android:layout_marginTop="8dp"></com.example.administrator.sbdemo.FLayout> <View
android:id="@+id/line2"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_below="@+id/fl"
android:layout_marginTop="30dp"
android:background="@android:color/darker_gray" /> <com.example.administrator.sbdemo.MyListview
android:id="@+id/lv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/line2"
android:layout_marginTop="15dp"> </com.example.administrator.sbdemo.MyListview>
</RelativeLayout> </com.example.administrator.sbdemo.MyScrollView> <include layout="@layout/title_layout" /> </RelativeLayout>

布局item:

 <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"> <com.example.administrator.sbdemo.Circle_ImageView
android:id="@+id/id_icon"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginLeft="10dp"
android:layout_marginTop="15dp"
android:scaleType="centerCrop"
android:src="@mipmap/log"
app:civ_border_color="@android:color/black"
app:civ_border_width="2dp" /> <TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:layout_toRightOf="@+id/id_icon"
android:text="火龙裸先生"
android:textColor="@android:color/black"
android:textSize="17sp" /> <TextView
android:id="@+id/Code"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/name"
android:layout_marginLeft="10dp"
android:layout_marginTop="5dp"
android:layout_toRightOf="@+id/id_icon"
android:text="ABCDEFG"
android:textSize="17sp" /> <RatingBar
style="?android:attr/ratingBarStyleSmall"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_alignBaseline="@+id/name"
android:layout_alignParentRight="true"
android:layout_gravity="center"
android:layout_marginLeft="30dp"
android:layout_marginRight="10dp"
android:isIndicator="false"
android:paddingBottom="10dp"
android:paddingTop="10dp" /> <TextView
android:id="@+id/message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/id_icon"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:text="啊啊啊啊啊 坑爹啊"
android:textColor="@android:color/black"
android:textSize="15sp"
android:textStyle="bold" /> <TextView
android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/message"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:text="2020-8-9" /> <TextView
android:id="@+id/money"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/message"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:layout_toRightOf="@+id/time"
android:text="交易金额¥555" />
</RelativeLayout>

布局title_layout:

 <?xml version="1.0" encoding="utf-8"?>

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/titleBar"
android:layout_width="match_parent"
android:layout_height="48dp"> <ImageView
android:id="@+id/backImage"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_centerVertical="true"
android:scaleType="centerCrop"
android:src="@mipmap/balk" /> <TextView
android:id="@+id/textview"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginLeft="1dp"
android:layout_toRightOf="@+id/backImage"
android:background="#00000000"
android:gravity="center"
android:text="@string/back"
android:textColor="@android:color/white"
android:textSize="18sp" /> <TextView android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:layout_marginLeft="1dp"
android:layout_marginRight="15dp"
android:background="#00000000"
android:gravity="center"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:text="更多"
android:textColor="@android:color/white"
android:textSize="18sp" />
</RelativeLayout>

实体类Model.java:

 package com.example.administrator.sbdemo;

 /**
* 参数:Created by Administrator on 2017/3/13.
* 类作用:Created by Administrator on 2017/3/13.
*/
public class Model {
String name;
String money;
String code;
String time;
String message; public String getMoney() {
return money;
} public void setMoney(String money) {
this.money = money;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getCode() {
return code;
} public void setCode(String code) {
this.code = code;
} public String getTime() {
return time;
} public void setTime(String time) {
this.time = time;
} public String getMessage() {
return message;
} public void setMessage(String message) {
this.message = message;
}
}

自定义标签类Flayout.java:

 package com.example.administrator.sbdemo;

 import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup; import java.util.ArrayList;
import java.util.List; /**
* Created by taofangxin on 16/4/16.
*/
public class FLayout extends ViewGroup { private Context mContext;
private int usefulWidth; // the space of a line we can use(line's width minus the sum of left and right padding
private int lineSpacing = 0; // the spacing between lines in FLayout
List<View> childList = new ArrayList();
List<Integer> lineNumList = new ArrayList(); public FLayout(Context context) {
this(context, null);
} public FLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
} public FLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
/* TypedArray mTypedArray = context.obtainStyledAttributes(attrs,
R.styleable.FLayout);
lineSpacing = mTypedArray.getDimensionPixelSize(
R.styleable.FLayout_lineSpacing, 0);*/
//mTypedArray.recycle();
} @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int mPaddingLeft = getPaddingLeft();
int mPaddingRight = getPaddingRight();
int mPaddingTop = getPaddingTop();
int mPaddingBottom = getPaddingBottom(); int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int lineUsed = mPaddingLeft + mPaddingRight;
int lineY = mPaddingTop;
int lineHeight = 0;
for (int i = 0; i < this.getChildCount(); i++) {
View child = this.getChildAt(i);
if (child.getVisibility() == GONE) {
continue;
}
int spaceWidth = 0;
int spaceHeight = 0;
LayoutParams childLp = child.getLayoutParams();
if (childLp instanceof MarginLayoutParams) {
measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, lineY);
MarginLayoutParams mlp = (MarginLayoutParams) childLp;
spaceWidth = mlp.leftMargin + mlp.rightMargin;
spaceHeight = mlp.topMargin + mlp.bottomMargin;
} else {
measureChild(child, widthMeasureSpec, heightMeasureSpec);
} int childWidth = child.getMeasuredWidth();
int childHeight = child.getMeasuredHeight();
spaceWidth += childWidth;
spaceHeight += childHeight; if (lineUsed + spaceWidth > widthSize) {
//approach the limit of width and move to next line
lineY += lineHeight + lineSpacing;
lineUsed = mPaddingLeft + mPaddingRight;
lineHeight = 0;
}
if (spaceHeight > lineHeight) {
lineHeight = spaceHeight;
}
lineUsed += spaceWidth;
}
setMeasuredDimension(
widthSize,
heightMode == MeasureSpec.EXACTLY ? heightSize : lineY + lineHeight + mPaddingBottom
);
} @Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int mPaddingLeft = getPaddingLeft();
int mPaddingRight = getPaddingRight();
int mPaddingTop = getPaddingTop(); int lineX = mPaddingLeft;
int lineY = mPaddingTop;
int lineWidth = r - l;
usefulWidth = lineWidth - mPaddingLeft - mPaddingRight;
int lineUsed = mPaddingLeft + mPaddingRight;
int lineHeight = 0;
int lineNum = 0; lineNumList.clear();
for (int i = 0; i < this.getChildCount(); i++) {
View child = this.getChildAt(i);
if (child.getVisibility() == GONE) {
continue;
}
int spaceWidth = 0;
int spaceHeight = 0;
int left = 0;
int top = 0;
int right = 0;
int bottom = 0;
int childWidth = child.getMeasuredWidth();
int childHeight = child.getMeasuredHeight(); LayoutParams childLp = child.getLayoutParams();
if (childLp instanceof MarginLayoutParams) {
MarginLayoutParams mlp = (MarginLayoutParams) childLp;
spaceWidth = mlp.leftMargin + mlp.rightMargin;
spaceHeight = mlp.topMargin + mlp.bottomMargin;
left = lineX + mlp.leftMargin;
top = lineY + mlp.topMargin;
right = lineX + mlp.leftMargin + childWidth;
bottom = lineY + mlp.topMargin + childHeight;
} else {
left = lineX;
top = lineY;
right = lineX + childWidth;
bottom = lineY + childHeight;
}
spaceWidth += childWidth;
spaceHeight += childHeight; if (lineUsed + spaceWidth > lineWidth) {
//approach the limit of width and move to next line
lineNumList.add(lineNum);
lineY += lineHeight + lineSpacing;
lineUsed = mPaddingLeft + mPaddingRight;
lineX = mPaddingLeft;
lineHeight = 0;
lineNum = 0;
if (childLp instanceof MarginLayoutParams) {
MarginLayoutParams mlp = (MarginLayoutParams) childLp;
left = lineX + mlp.leftMargin;
top = lineY + mlp.topMargin;
right = lineX + mlp.leftMargin + childWidth;
bottom = lineY + mlp.topMargin + childHeight;
} else {
left = lineX;
top = lineY;
right = lineX + childWidth;
bottom = lineY + childHeight;
}
}
child.layout(left, top, right, bottom);
lineNum++;
if (spaceHeight > lineHeight) {
lineHeight = spaceHeight;
}
lineUsed += spaceWidth;
lineX += spaceWidth;
}
// add the num of last line
lineNumList.add(lineNum);
} /**
* resort child elements to use lines as few as possible
*/
public void relayoutToCompress() {
int childCount = this.getChildCount();
if (0 == childCount) {
//no need to sort if FLayout has no child view
return;
}
int count = 0;
for (int i = 0; i < childCount; i++) {
View v = getChildAt(i);
if (v instanceof BlankView) {
//BlankView is just to make childs look in alignment, we should ignore them when we relayout
continue;
}
count++;
}
View[] childs = new View[count];
int[] spaces = new int[count];
int n = 0;
for (int i = 0; i < childCount; i++) {
View v = getChildAt(i);
if (v instanceof BlankView) {
//BlankView is just to make childs look in alignment, we should ignore them when we relayout
continue;
}
childs[n] = v;
LayoutParams childLp = v.getLayoutParams();
int childWidth = v.getMeasuredWidth();
if (childLp instanceof MarginLayoutParams) {
MarginLayoutParams mlp = (MarginLayoutParams) childLp;
spaces[n] = mlp.leftMargin + childWidth + mlp.rightMargin;
} else {
spaces[n] = childWidth;
}
n++;
}
int[] compressSpaces = new int[count];
for (int i = 0; i < count; i++) {
compressSpaces[i] = spaces[i] > usefulWidth ? usefulWidth : spaces[i];
}
sortToCompress(childs, compressSpaces);
this.removeAllViews();
for (View v : childList) {
this.addView(v);
}
childList.clear();
} private void sortToCompress(View[] childs, int[] spaces) {
int childCount = childs.length;
int[][] table = new int[childCount + 1][usefulWidth + 1];
for (int i = 0; i < childCount + 1; i++) {
for (int j = 0; j < usefulWidth; j++) {
table[i][j] = 0;
}
}
boolean[] flag = new boolean[childCount];
for (int i = 0; i < childCount; i++) {
flag[i] = false;
}
for (int i = 1; i <= childCount; i++) {
for (int j = spaces[i - 1]; j <= usefulWidth; j++) {
table[i][j] = (table[i - 1][j] > table[i - 1][j - spaces[i - 1]] + spaces[i - 1]) ? table[i - 1][j] : table[i - 1][j - spaces[i - 1]] + spaces[i - 1];
}
}
int v = usefulWidth;
for (int i = childCount; i > 0 && v >= spaces[i - 1]; i--) {
if (table[i][v] == table[i - 1][v - spaces[i - 1]] + spaces[i - 1]) {
flag[i - 1] = true;
v = v - spaces[i - 1];
}
}
int rest = childCount;
View[] restArray;
int[] restSpaces;
for (int i = 0; i < flag.length; i++) {
if (flag[i] == true) {
childList.add(childs[i]);
rest--;
}
} if (0 == rest) {
return;
}
restArray = new View[rest];
restSpaces = new int[rest];
int index = 0;
for (int i = 0; i < flag.length; i++) {
if (flag[i] == false) {
restArray[index] = childs[i];
restSpaces[index] = spaces[i];
index++;
}
}
table = null;
childs = null;
flag = null;
sortToCompress(restArray, restSpaces);
} /**
* add some blank view to make child elements look in alignment
*/
public void relayoutToAlign() {
int childCount = this.getChildCount();
if (0 == childCount) {
//no need to sort if FLayout has no child view
return;
}
int count = 0;
for (int i = 0; i < childCount; i++) {
View v = getChildAt(i);
if (v instanceof BlankView) {
//BlankView is just to make childs look in alignment, we should ignore them when we relayout
continue;
}
count++;
}
View[] childs = new View[count];
int[] spaces = new int[count];
int n = 0;
for (int i = 0; i < childCount; i++) {
View v = getChildAt(i);
if (v instanceof BlankView) {
//BlankView is just to make childs look in alignment, we should ignore them when we relayout
continue;
}
childs[n] = v;
LayoutParams childLp = v.getLayoutParams();
int childWidth = v.getMeasuredWidth();
if (childLp instanceof MarginLayoutParams) {
MarginLayoutParams mlp = (MarginLayoutParams) childLp;
spaces[n] = mlp.leftMargin + childWidth + mlp.rightMargin;
} else {
spaces[n] = childWidth;
}
n++;
}
int lineTotal = 0;
int start = 0;
this.removeAllViews();
for (int i = 0; i < count; i++) {
if (lineTotal + spaces[i] > usefulWidth) {
int blankWidth = usefulWidth - lineTotal;
int end = i - 1;
int blankCount = end - start;
if (blankCount >= 0) {
if (blankCount > 0) {
int eachBlankWidth = blankWidth / blankCount;
MarginLayoutParams lp = new MarginLayoutParams(eachBlankWidth, 0);
for (int j = start; j < end; j++) {
this.addView(childs[j]);
BlankView blank = new BlankView(mContext);
this.addView(blank, lp);
}
}
this.addView(childs[end]);
start = i;
i--;
lineTotal = 0;
} else {
this.addView(childs[i]);
start = i + 1;
lineTotal = 0;
}
} else {
lineTotal += spaces[i];
}
}
for (int i = start; i < count; i++) {
this.addView(childs[i]);
}
} public void setflineSpacing(int sp) {
lineSpacing = sp;
} /**
* use both of relayout methods together
*/
public void relayoutToCompressAndAlign() {
this.relayoutToCompress();
this.relayoutToAlign();
} /**
* cut the FLayout to the specified num of lines
*
* @param line_num
*/
public void specifyLines(int line_num) {
int childNum = 0;
if (line_num > lineNumList.size()) {
line_num = lineNumList.size();
}
for (int i = 0; i < line_num; i++) {
childNum += lineNumList.get(i);
}
List<View> viewList = new ArrayList<>();
for (int i = 0; i < childNum; i++) {
viewList.add(getChildAt(i));
}
removeAllViews();
for (View v : viewList) {
addView(v);
}
} @Override
protected LayoutParams generateLayoutParams(LayoutParams p) {
return new MarginLayoutParams(p);
} @Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new MarginLayoutParams(getContext(), attrs);
} @Override
protected LayoutParams generateDefaultLayoutParams() {
return new MarginLayoutParams(super.generateDefaultLayoutParams());
} class BlankView extends View { public BlankView(Context context) {
super(context);
}
}
}

自定义圆角图片类Circle_ImageView.java:

 package com.example.administrator.sbdemo;

 import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.support.annotation.ColorInt;
import android.support.annotation.ColorRes;
import android.support.annotation.DrawableRes;
import android.util.AttributeSet;
import android.widget.ImageView; /**
* Created by ${火龙裸先生} on 2016/9/5.
* 邮箱:791335000@qq.com
*/
public class Circle_ImageView extends ImageView {
private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP; private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;
private static final int COLORDRAWABLE_DIMENSION = 2; private static final int DEFAULT_BORDER_WIDTH = 0;
private static final int DEFAULT_BORDER_COLOR = Color.BLACK;
private static final int DEFAULT_FILL_COLOR = Color.TRANSPARENT;
private static final boolean DEFAULT_BORDER_OVERLAY = false; private final RectF mDrawableRect = new RectF();
private final RectF mBorderRect = new RectF(); private final Matrix mShaderMatrix = new Matrix();
private final Paint mBitmapPaint = new Paint();
private final Paint mBorderPaint = new Paint();
private final Paint mFillPaint = new Paint(); private int mBorderColor = DEFAULT_BORDER_COLOR;
private int mBorderWidth = DEFAULT_BORDER_WIDTH;
private int mFillColor = DEFAULT_FILL_COLOR; private Bitmap mBitmap;
private BitmapShader mBitmapShader;
private int mBitmapWidth;
private int mBitmapHeight; private float mDrawableRadius;
private float mBorderRadius; private ColorFilter mColorFilter; private boolean mReady;
private boolean mSetupPending;
private boolean mBorderOverlay;
private boolean mDisableCircularTransformation; public Circle_ImageView(Context context) {
super(context); init();
} public Circle_ImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
} public Circle_ImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView, defStyle, 0); mBorderWidth = a.getDimensionPixelSize(R.styleable.CircleImageView_civ_border_width, DEFAULT_BORDER_WIDTH);
mBorderColor = a.getColor(R.styleable.CircleImageView_civ_border_color, DEFAULT_BORDER_COLOR);
mBorderOverlay = a.getBoolean(R.styleable.CircleImageView_civ_border_overlay, DEFAULT_BORDER_OVERLAY);
mFillColor = a.getColor(R.styleable.CircleImageView_civ_fill_color, DEFAULT_FILL_COLOR); a.recycle(); init();
} private void init() {
super.setScaleType(SCALE_TYPE);
mReady = true; if (mSetupPending) {
setup();
mSetupPending = false;
}
} @Override
public ScaleType getScaleType() {
return SCALE_TYPE;
} @Override
public void setScaleType(ScaleType scaleType) {
if (scaleType != SCALE_TYPE) {
throw new IllegalArgumentException(String.format("ScaleType %s not supported.", scaleType));
}
} @Override
public void setAdjustViewBounds(boolean adjustViewBounds) {
if (adjustViewBounds) {
throw new IllegalArgumentException("adjustViewBounds not supported.");
}
} @Override
protected void onDraw(Canvas canvas) {
if (mDisableCircularTransformation) {
super.onDraw(canvas);
return;
} if (mBitmap == null) {
return;
} if (mFillColor != Color.TRANSPARENT) {
canvas.drawCircle(mDrawableRect.centerX(), mDrawableRect.centerY(), mDrawableRadius, mFillPaint);
}
canvas.drawCircle(mDrawableRect.centerX(), mDrawableRect.centerY(), mDrawableRadius, mBitmapPaint);
if (mBorderWidth > 0) {
canvas.drawCircle(mBorderRect.centerX(), mBorderRect.centerY(), mBorderRadius, mBorderPaint);
}
} @Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
setup();
} @Override
public void setPadding(int left, int top, int right, int bottom) {
super.setPadding(left, top, right, bottom);
setup();
} @Override
public void setPaddingRelative(int start, int top, int end, int bottom) {
super.setPaddingRelative(start, top, end, bottom);
setup();
} public int getBorderColor() {
return mBorderColor;
} public void setBorderColor(@ColorInt int borderColor) {
if (borderColor == mBorderColor) {
return;
} mBorderColor = borderColor;
mBorderPaint.setColor(mBorderColor);
invalidate();
} /**
* @deprecated Use {@link #setBorderColor(int)} instead
*/
@Deprecated
public void setBorderColorResource(@ColorRes int borderColorRes) {
setBorderColor(getContext().getResources().getColor(borderColorRes));
} /**
* Return the color drawn behind the circle-shaped drawable.
*
* @return The color drawn behind the drawable
* @deprecated Fill color support is going to be removed in the future
*/
@Deprecated
public int getFillColor() {
return mFillColor;
} /**
* Set a color to be drawn behind the circle-shaped drawable. Note that
* this has no effect if the drawable is opaque or no drawable is set.
*
* @param fillColor The color to be drawn behind the drawable
* @deprecated Fill color support is going to be removed in the future
*/
@Deprecated
public void setFillColor(@ColorInt int fillColor) {
if (fillColor == mFillColor) {
return;
} mFillColor = fillColor;
mFillPaint.setColor(fillColor);
invalidate();
} /**
* Set a color to be drawn behind the circle-shaped drawable. Note that
* this has no effect if the drawable is opaque or no drawable is set.
*
* @param fillColorRes The color resource to be resolved to a color and
* drawn behind the drawable
* @deprecated Fill color support is going to be removed in the future
*/
@Deprecated
public void setFillColorResource(@ColorRes int fillColorRes) {
setFillColor(getContext().getResources().getColor(fillColorRes));
} public int getBorderWidth() {
return mBorderWidth;
} public void setBorderWidth(int borderWidth) {
if (borderWidth == mBorderWidth) {
return;
} mBorderWidth = borderWidth;
setup();
} public boolean isBorderOverlay() {
return mBorderOverlay;
} public void setBorderOverlay(boolean borderOverlay) {
if (borderOverlay == mBorderOverlay) {
return;
} mBorderOverlay = borderOverlay;
setup();
} public boolean isDisableCircularTransformation() {
return mDisableCircularTransformation;
} public void setDisableCircularTransformation(boolean disableCircularTransformation) {
if (mDisableCircularTransformation == disableCircularTransformation) {
return;
} mDisableCircularTransformation = disableCircularTransformation;
initializeBitmap();
} @Override
public void setImageBitmap(Bitmap bm) {
super.setImageBitmap(bm);
initializeBitmap();
} @Override
public void setImageDrawable(Drawable drawable) {
super.setImageDrawable(drawable);
initializeBitmap();
} @Override
public void setImageResource(@DrawableRes int resId) {
super.setImageResource(resId);
initializeBitmap();
} @Override
public void setImageURI(Uri uri) {
super.setImageURI(uri);
initializeBitmap();
} @Override
public void setColorFilter(ColorFilter cf) {
if (cf == mColorFilter) {
return;
} mColorFilter = cf;
applyColorFilter();
invalidate();
} @Override
public ColorFilter getColorFilter() {
return mColorFilter;
} private void applyColorFilter() {
if (mBitmapPaint != null) {
mBitmapPaint.setColorFilter(mColorFilter);
}
} private Bitmap getBitmapFromDrawable(Drawable drawable) {
if (drawable == null) {
return null;
} if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
} try {
Bitmap bitmap; if (drawable instanceof ColorDrawable) {
bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION, BITMAP_CONFIG);
} else {
bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), BITMAP_CONFIG);
} Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
} catch (Exception e) {
e.printStackTrace();
return null;
}
} private void initializeBitmap() {
if (mDisableCircularTransformation) {
mBitmap = null;
} else {
mBitmap = getBitmapFromDrawable(getDrawable());
}
setup();
} private void setup() {
if (!mReady) {
mSetupPending = true;
return;
} if (getWidth() == 0 && getHeight() == 0) {
return;
} if (mBitmap == null) {
invalidate();
return;
} mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); mBitmapPaint.setAntiAlias(true);
mBitmapPaint.setShader(mBitmapShader); mBorderPaint.setStyle(Paint.Style.STROKE);
mBorderPaint.setAntiAlias(true);
mBorderPaint.setColor(mBorderColor);
mBorderPaint.setStrokeWidth(mBorderWidth); mFillPaint.setStyle(Paint.Style.FILL);
mFillPaint.setAntiAlias(true);
mFillPaint.setColor(mFillColor); mBitmapHeight = mBitmap.getHeight();
mBitmapWidth = mBitmap.getWidth(); mBorderRect.set(calculateBounds());
mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2.0f, (mBorderRect.width() - mBorderWidth) / 2.0f); mDrawableRect.set(mBorderRect);
if (!mBorderOverlay && mBorderWidth > 0) {
mDrawableRect.inset(mBorderWidth - 1.0f, mBorderWidth - 1.0f);
}
mDrawableRadius = Math.min(mDrawableRect.height() / 2.0f, mDrawableRect.width() / 2.0f); applyColorFilter();
updateShaderMatrix();
invalidate();
} private RectF calculateBounds() {
int availableWidth = getWidth() - getPaddingLeft() - getPaddingRight();
int availableHeight = getHeight() - getPaddingTop() - getPaddingBottom(); int sideLength = Math.min(availableWidth, availableHeight); float left = getPaddingLeft() + (availableWidth - sideLength) / 2f;
float top = getPaddingTop() + (availableHeight - sideLength) / 2f; return new RectF(left, top, left + sideLength, top + sideLength);
} private void updateShaderMatrix() {
float scale;
float dx = 0;
float dy = 0; mShaderMatrix.set(null); if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width() * mBitmapHeight) {
scale = mDrawableRect.height() / (float) mBitmapHeight;
dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f;
} else {
scale = mDrawableRect.width() / (float) mBitmapWidth;
dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f;
} mShaderMatrix.setScale(scale, scale);
mShaderMatrix.postTranslate((int) (dx + 0.5f) + mDrawableRect.left, (int) (dy + 0.5f) + mDrawableRect.top); mBitmapShader.setLocalMatrix(mShaderMatrix);
}
}

自定义圆角图片对应的attr文件属性定义(先在values文件夹下新建一个attr.xml文件):

 <!-- 自定义圆角ImageView -->
<declare-styleable name="CircleImageView">
<attr name="civ_border_width" format="dimension" />
<attr name="civ_border_color" format="color" />
<attr name="civ_border_overlay" format="boolean" />
<attr name="civ_fill_color" format="color" />
</declare-styleable>

自定义ListView类MyListview.java:

 package com.example.administrator.sbdemo;

 import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.ListView; /**
* 参数:Created by Administrator on 2017/3/13.
* 类作用:Created by Administrator on 2017/3/13.
*/
public class MyListview extends ListView {
public MyListview(Context context) {
super(context);
} public MyListview(Context context, AttributeSet attrs) {
super(context, attrs);
} public MyListview(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
} @Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return false;
} @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
}

自定义ScrollView类MyScrollView.java:

 package com.example.administrator.sbdemo;

 import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ScrollView; /**
* 参数:Created by Administrator on 2017/3/13.
* 类作用:Created by Administrator on 2017/3/13.
*/
public class MyScrollView extends ScrollView { private ImageView mImageView;
private int imageHeight = 0;
private int imageWidth = 0;
private View TitleBarView; public MyScrollView(Context context) {
super(context);
imageHeight = context.getResources().getDimensionPixelSize(R.dimen.size_default_height);
} public MyScrollView(Context context, AttributeSet attrs) { super(context, attrs);
imageHeight = context.getResources().getDimensionPixelSize(R.dimen.size_default_height); } public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
imageHeight = context.getResources().getDimensionPixelSize(R.dimen.size_default_height);
} public void setImageWidth(int width) {
this.imageWidth = width;
} public void setZoomImageView(ImageView iv) {
mImageView = iv;
} public void setTitleBarView(View view) {
this.TitleBarView = view;
} @Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
Log.i("xgr", t + "****" + imageHeight);
if (t <= 0) {
TitleBarView.setBackgroundColor(Color.argb((int) 0, 63, 81, 181));//AGB由相关工具获得,或者美工提供
} else if (t > 0 && t + TitleBarView.getHeight() <= imageHeight) {
float scale = (float) t / imageHeight;
float alpha = (255 * scale);
// 只是layout背景透明
TitleBarView.setBackgroundColor(Color.argb((int) alpha, 63, 81, 181));
} else {
TitleBarView.setBackgroundColor(Color.argb((int) 255, 63, 81, 181));
}
super.onScrollChanged(l, t, oldl, oldt);
} @Override
protected int computeScrollDeltaToGetChildRectOnScreen(Rect rect) {
return 0;
} }

最后MainActivity.java:

 package com.example.administrator.sbdemo;

 import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast; import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List; import butterknife.Bind;
import butterknife.ButterKnife;
import butterknife.OnClick; public class MainActivity extends AppCompatActivity implements View.OnTouchListener { @Bind(R.id.img)
ImageView img;
@Bind(R.id.fl)
FLayout fl;
@Bind(R.id.lv)
MyListview lv;
@Bind(R.id.scrollView)
MyScrollView scrollView;
@Bind(R.id.backImage)
ImageView backImage;
@Bind(R.id.titleBar)
RelativeLayout titleBar;
@Bind(R.id.senP)
TextView senP;
private int imageWidth = 0;
// 记录首次按下位置
private float mFirstPosition = 0;
// 是否正在放大
private Boolean mScaling = false; private Myadapter adapter;
private List<Model> data; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
initView();
} private void initView() {
// 获取控件
scrollView = (MyScrollView) findViewById(R.id.scrollView); titleBar = (RelativeLayout) findViewById(R.id.titleBar); img = (ImageView) findViewById(R.id.img);
img.post(new Runnable() {
@Override
public void run() {
imageWidth = img.getWidth();
scrollView.setImageWidth(imageWidth); }
});
scrollView.setZoomImageView(img);
scrollView.setTitleBarView(titleBar);
scrollView.setOnTouchListener(this);
for (int i = 0; i < 8; i++) {
TextView tv = new TextView(this);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.setMargins(20, 10, 20, 0);
tv.setLayoutParams(params);
tv.setPadding(20, 10, 20, 10);
tv.setText("标签" + i);
tv.setTextSize(20);
tv.setTextColor(getResources().getColor(android.R.color.white));
tv.setBackground(getResources().getDrawable(R.drawable.lv_item_tv_bg));
fl.addView(tv);
} data = new ArrayList<>();
for (int i = 0; i < 10; i++) {
Model model = new Model();
model.setCode("ABCDEFG" + i);
model.setMessage("Click me,重要的事情说" + i + "遍");
model.setMoney("交易金额¥" + i * 10);
model.setName("火龙裸先生+" + i);
model.setTime(getStringDate());
data.add(model);
}
adapter = new Myadapter(data, this);
lv.setAdapter(adapter);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Toast.makeText(MainActivity.this, "点击了" + i, Toast.LENGTH_SHORT).show();
}
});
} @OnClick(R.id.backImage)
public void back() {
Toast.makeText(this, "返回按钮", Toast.LENGTH_SHORT).show();
} @OnClick(R.id.senP)
public void sen() {
Toast.makeText(this, "发项目", Toast.LENGTH_SHORT).show();
} class Myadapter extends BaseAdapter {
private List<Model> data;
private LayoutInflater inflater; public Myadapter(List<Model> data, Context context) {
this.data = data;
this.inflater = LayoutInflater.from(context);
} @Override
public int getCount() {
if (data == null || data.size() <= 0) {
return 0;
}
return data.size();
} @Override
public Object getItem(int i) {
return null;
} @Override
public long getItemId(int i) {
return 0;
} @Override
public View getView(int i, View view, ViewGroup viewGroup) {
ViewHolder holder = null;
if (view == null) {
view = inflater.inflate(R.layout.item, viewGroup, false);
holder = new ViewHolder(view);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
} holder.Code.setText(data.get(i).getCode());
holder.message.setText(data.get(i).getMessage());
holder.money.setText(data.get(i).getMoney());
holder.time.setText(data.get(i).getTime());
holder.name.setText(data.get(i).getName()); return view;
} class ViewHolder {
@Bind(R.id.id_icon)
Circle_ImageView idIcon;
@Bind(R.id.name)
TextView name;
@Bind(R.id.Code)
Text;
@Bind(R.id.message)
TextView message;
@Bind(R.id.time)
TextView time;
@Bind(R.id.money)
TextView money; ViewHolder(View view) {
ButterKnife.bind(this, view);
}
}
} @Override
public boolean onTouch(View view, MotionEvent motionEvent) {
ViewGroup.LayoutParams lp = (ViewGroup.LayoutParams) img
.getLayoutParams();
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_UP:
// 手指离开后恢复图片
mScaling = false;
replyImage();
break;
case MotionEvent.ACTION_MOVE:
if (!mScaling) {
if (scrollView.getScrollY() == 0) {
mFirstPosition = motionEvent.getY();// 滚动到顶部时记录位置,否则正常返回
} else {
break;
}
}
int distance = (int) ((motionEvent.getY() - mFirstPosition) * 0.6); // 滚动距离乘以一个系数
if (distance < 0) { // 当前位置比记录位置要小,正常返回
break;
} // 处理放大
mScaling = true;
lp.width = imageWidth + distance;
//lp.height = (imageWidth + distance) * 9 / 16;
lp.height = getResources().getDimensionPixelSize(R.dimen.size_default_height) + distance;
img.setLayoutParams(lp);
return true; // 返回true表示已经完成触摸事件,不再处理
}
return false;
} // 回弹动画
public void replyImage() {
final ViewGroup.LayoutParams lp = (ViewGroup.LayoutParams) img
.getLayoutParams();
final float w = img.getLayoutParams().width;// 图片当前宽度
final float h = img.getLayoutParams().height;// 图片当前高度
final float newW = imageWidth;// 图片原宽度
final float newH = getResources().getDimensionPixelSize(R.dimen.size_default_height);// 图片原高度 // 设置动画
ValueAnimator anim = ObjectAnimator.ofFloat(0.0F, 1.0F)
.setDuration(200); anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float cVal = (Float) animation.getAnimatedValue();
lp.width = (int) (w - (w - newW) * cVal);
lp.height = (int) (h - (h - newH) * cVal);
img.setLayoutParams(lp);
}
});
anim.start(); } //获取时间
public static String getStringDate() {
Date currentTime = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateString = formatter.format(currentTime);
return dateString;
}
}

所有代码放一起,代码有些多,大家可以分开各个小功能去看,都是比较简单的东西。

自定义标签+阻尼动画+圆角图片+titleBar随滑动渐隐和显示的更多相关文章

  1. 自定义view实现圆角图片

    前两天想实现一个圆角图片的效果,通过网络搜索后找到一些答案.这里自己再记录一下,加深一下自己的认识和知识理解. 实现圆角图片的思路是自定义一个ImageView,然后通过Ondraw()重绘的功能,将 ...

  2. [转]Android UI:看看Google官方自定义带旋转动画的ImageView-----RotateImageView怎么写(附 图片淡入淡出效果)

    http://blog.csdn.net/yanzi1225627/article/details/22439119 众所周知,想要让ImageView旋转的话,可以用setRotation()让其围 ...

  3. CALayer 知识:创建带阴影效果的圆角图片图层和创建自定义绘画内容图层

    效果如下: KMLayerDelegate.h #import <UIKit/UIKit.h> @interface KMLayerDelegate : NSObject @end KML ...

  4. Django 六——自定义标签、图片验证码、发送邮件、评论树、组合搜索

    1.自定义标签 2.图片验证码 3.生成邮箱验证码.发送邮件 4.评论树实现 5.组合搜索(Q) 1.自定义标签 配置: a.在app中新建文件夹  templatetags,里面新建  xx.py文 ...

  5. Android UI:看看Google官方自定义带旋转动画的ImageView-----RotateImageView怎么写(附 图片淡入淡...)

    众所周知,想要让ImageView旋转的话,可以用setRotation()让其围绕中心点旋转,但这个旋转是不带动画的,也就是旋转屏幕时图片噌的一下就转过去了,看不到旋转的过程,此UI体验不大好,为此 ...

  6. css Cursor:url()自定义鼠标指针样式为图片

    css自定义鼠标指针样式为图片Cursor:url()的使用,今天在项目中,要用到自定义鼠标样式,格式: css:{cursor:url('绝对路径的图片(格式:cur,ico)'),-moz-zoo ...

  7. [转]Android中attr自定义标签详解

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:wen= ...

  8. 【转载】Android中attr自定义标签详解

    原文链接:http://blog.sina.com.cn/s/blog_62ef2f14010105vi.html:仅对排版进行优化,更方便阅读 <LinearLayout xmlns:andr ...

  9. Android学习笔记_41_TabHost自定义标签和TraceView性能测试

    一.tabhost第一种用法,通过在帧布局放入定义好的page页面来实现,这样导致在当前activity下代码量比较大. 1.页面布局: |        |        |        |    ...

随机推荐

  1. 【LeetCode】 617. 合并二叉树

    题目 给定两个二叉树,想象当你将它们中的一个覆盖到另一个上时,两个二叉树的一些节点便会重叠. 你需要将他们合并为一个新的二叉树.合并的规则是如果两个节点重叠,那么将他们的值相加作为节点合并后的新值,否 ...

  2. Java执行Shell脚本“No such file or directory” (win->Linux)异常的可能原因

    转自:http://blog.csdn.net/zlpdaisy/article/details/6134314 用Runtime.getRuntime().exec()方法执行Linux的一个She ...

  3. 【数组】Container With Most Water

    题目: Given n non-negative integers a1, a2, ..., an, where each represents a point at coordinate (i, a ...

  4. Chapter 3 Phenomenon——3

    It took every ounce of my concentration to make it down the icy brick driveway alive. 我用所有我的注意力去确定车道 ...

  5. Linux下安装了Xampp,但命令行使用不了MySQL

    引用:http://www.2cto.com/database/201406/309521.html   刚安装好Xampp,使用localhost也能正常运行, phpMyAdimin也能正常登录 ...

  6. 蝴蝶效应--由'sudo -s ...'引发的vim autocmd使用异常

    1. 背景介绍 自加入RedHat起,我就把家里的台式机(Ubuntu 16.04 LTS)的默认登录用户veli切换成了huanli, 主要是为了跟公司的电脑配置对齐以方便未来WFH,但引发了一个v ...

  7. lucene基本原理

    1.术语 lucene 在存储它的全文索引结构时,是有层次结构的,这涉及到5个层次:索引(Index):段(Segment):文档(Document):域(Field):词(Term),他们的关系如下 ...

  8. rails中常用的插件

    config.gem "acts-as-taggable-on", :version => '1.0.19' # tag类 config.gem "papercli ...

  9. SSH和SSL比较

    一.SSH介绍 什么是SSH? 传统的网络服务程序,如:ftp.pop和telnet在本质上都是不安全的,因为它们在网络上用明文传送口令和数据, 别有用心的人非常容易就可以截 获这些口令和数据.而且, ...

  10. 牛客网剑指offer java 全部题解

    经过数月的努力,终于更完了牛客网的66道剑指offer,以下的顺序和大家在牛客网的顺序是一样的(排序也花了不少时间),希望对大家找工作/提高算法能力能起到些许帮助. 每天一道剑指offer-二维数组中 ...