目錄
效果展示
實現原理
這個效果主要是運用了貝塞爾曲線杰赛、自定義ViewGroup以及動畫的知識。
1.貝塞爾曲線(用于實現順暢的圓黄居铩)
一個自定義的ViewGroup中總共使用了三段貝塞爾曲線:
而要做到三段貝塞爾曲線完美對接幸缕,則需要使第一段貝塞爾曲線的控制點與第二段貝塞爾曲線的起始點和控制點涵亏,三點在一條直線上,因此B點需要隨著C點的升高惹挟。(如下圖所示)
2.自定義ViewGroup
這里為了簡單我是直接繼承LinearLayout通過重寫onMeasure方法來實現的伟端,主要是對控件 的高度做了調整,代碼如下:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if(imgChild == null){
//獲取ImageView 和ImageView 的寬度
for(int i = 0 ; i < getChildCount() ; i++){
View child = getChildAt(i);
if(child instanceof ImageView){
imgChild = (ImageView) child;
imgChildWidth = imgChild.getMeasuredWidth();
LinearLayout.LayoutParams layoutParams = (LayoutParams) imgChild.getLayoutParams();
layoutParams.topMargin += (imgChildWidth / 2 + offsetFloatHeight);//整體的高度等于自適應高度加浮動的高度加偏移的高度
imgChild.setLayoutParams(layoutParams);
Log.e("寬度",imgChildWidth+"");
break;
}
}
}
}
3.動畫
這里我總共定義了兩個動畫匪煌,一個用來浮起一個用來縮回责蝠,其中浮起的動畫加了個頂部回彈的效果,代碼如下:
/**
* 加載縮回的動畫
*/
private void initRestractAnim() {
if(animatorRestract == null){
animatorRestract = ValueAnimator.ofFloat(imgChildWidth / 2f, 0);
animatorRestract.setDuration(500);
animatorRestract.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float animatedValue = (float) animation.getAnimatedValue();
if(imgChild != null){
imgChild.setTranslationY(-animatedValue/3);
}
setFloatHeight(animatedValue);
}
});
}
}
/**
* 加載浮起的動畫
*/
private void initFloatAnim() {
if(animatorFloat == null){
animatorFloat = ValueAnimator.ofFloat(0, imgChildWidth / 2f + offsetFloatHeight,imgChildWidth / 2f);
animatorFloat.setDuration(500);
animatorFloat.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float animatedValue = (float) animation.getAnimatedValue();
if(imgChild != null){
imgChild.setTranslationY(-animatedValue/3);
}
setFloatHeight(animatedValue);
}
});
}
}
案例源碼
想要詳細了解的同學可以在這下載源碼:https://gitee.com/itfitness/FitnessLib