高仿QQ的个性名片Word格式.docx
《高仿QQ的个性名片Word格式.docx》由会员分享,可在线阅读,更多相关《高仿QQ的个性名片Word格式.docx(14页珍藏版)》请在冰豆网上搜索。
,一共四个方向,每个方向90°
,我们按照小于等于90°
来计算,然后再放到相应的方向上
//cx,cy是容器的中心点,也是圆形头像的中心点,计算气泡的位置就是已cx,cy为基准来计算的
intcx=mWidth/2;
//容器中心x坐标
intcy=mHeight/2;
//容器中心y坐标
intradius=mMinSize/2/2/2+mMinSize/2/2;
//动态气泡的组成圆的半径
intleft=0;
inttop=0;
intright=0;
intbottom=0;
inta=0,b=0;
//a是基于cx的偏移量,b是基于cy的偏移量,
//intr=mMinSize/6/2;
//气泡半径
for(inti=0;
i<
textViews.size();
i++){
intr=textViews.get(i).getMeasuredWidth()/2;
//计算得来//固定死的mMinSize/6/2;
if(angle>
=0&
&
angle<
rightAngle){//0-90度是计算偏移量
//保持角度在0-90
a=(int)(radius*Math.sin(Math.abs(angle%rightAngle)));
b=(int)(radius*Math.cos(Math.abs(angle%rightAngle)));
left=cx+a-r;
//cx+a为气泡的中心点,要想得到left,还需减去半径r
top=cy-b-r;
right=left+2*r;
bottom=top+2*r;
}elseif(angle>
=rightAngle&
rightAngle*2){//90-180
left=cx+b-r;
top=cy+a-r;
=rightAngle*2&
rightAngle*3){//180-270
left=cx-a-r;
top=cy+b-r;
=rightAngle*3&
rightAngle*4){//270-360
left=cx-b-r;
top=cy-a-r;
}
//将计算好的left,top,right,bottom,angle保存起来
mRatioFrameList.add(newRatioFrame(left,top,right,bottom,angle));
//角度再加一个梯度值
angle+=grad;
计算好气泡的布局left,top,right,bottom,下面就开始布局这起气泡,布局中的代码就简单的多了
@Override
protectedvoidonLayout(booleanchanged,intl,intt,intr,intb){
if(mImageView==null)return;
intwidth=mImageView.getMeasuredWidth();
//计算圆形头像的宽
intheight=mImageView.getMeasuredHeight();
//计算圆形头像的高
//计算圆形头像的left,top,right,bottom
intleft=mWidth/2-width/2;
inttop=mHeight/2-height/2;
intright=mWidth/2+width/2;
intbottom=mHeight/2+height/2;
//开始布局
mImageView.layout(left,top,right,bottom);
//布局爱心动画
mLoveXinList.size();
ImageViewimageView=mLoveXinList.get(i);
left=mWidth/2+width/4-imageView.getMeasuredWidth()/2;
bottom=mHeight/2+height/3;
top=bottom-imageView.getMeasuredHeight();
right=left+imageView.getMeasuredWidth();
imageView.layout(left,top,right,bottom);
//布局所有气泡
mTextViews.size();
TextViewtextView=mTextViews.get(i);
//RatioFrameratioFrame=mRatioFrameList.get(i);
//无动画时使用
//有动画的时候,执行期间left,top,right,bottom都在变
if(mCurrentRatioFrameList!
=null){
//ValueAnimator执行动画是所产生的所有气泡left,top,right,bottom
RatioFrameratioFrame=mCurrentRatioFrameList.get(i);
textView.layout(ratioFrame.mLeft,ratioFrame.mTop,ratioFrame.mRight,ratioFrame.mBottom);
好了,静态的气泡排版到这里就好了,下面的问题是,展开时如何使气泡从中心点,以弧形的路径展开,并且气泡的大小也是由小到大变化。
这里就用到的动画类ValueAnimator和ScaleAnimation,详解请参考:
向外展开的效果我们可以使用view.layout()不断的重新布局气泡view,让其产生一个平移的效果,下面的一个问题就是如何计算平移轨道上面的left,top,right,bottom,然后重新请求布局就可以了,那么下面就解决如何计算这个轨迹,分析
弧形轨迹计算,其实就是在直线轨迹的基础上加上偏移量(moveX和moveY),就形成了弧形轨迹,直线轨迹很好计算,关键的就是这个偏移量,因为在首位的偏移量小,而在中间的偏移量大,且在不同的方向上,moveX和moveY的值的正负也不一样。
偏移的距离因为是由小到大再由大到小,所以我们用二次函数(-2*Math.pow(fraction,2)+2*fraction)来计算距离,用此二次函数得到的值乘以一个设定的最大值,这个最大值的就会是由小到大再由大到小的变化,然后再用不同的角度来计算它的正负
if(endRatioFrame.mAngle>
0&
endRatioFrame.mAngle<
=rightAngle){//(0<
=90)上移,左移
moveX=(int)(temp*Math.abs(Math.cos(endRatioFrame.mAngle)));
//上移就应该在原本的轨迹上减去moveX
moveY=(int)(temp*Math.abs(Math.sin(endRatioFrame.mAngle)));
}elseif(endRatioFrame.mAngle>
rightAngle&
=rightAngle*2){//(90<
=180)右移,上移
moveX=(int)(-temp*Math.abs(Math.cos(endRatioFrame.mAngle)));
rightAngle*2&
=rightAngle*3){//(180<
=2700)下移,右移
moveY=(int)(-temp*Math.abs(Math.sin(endRatioFrame.mAngle)));
rightAngle*3&
=rightAngle*4||endRatioFrame.mAngle==0){//(270<
=360或者angle==0)左移,下移
根据三角函数的变化值,上面的代码可以简化为
moveX=(int)(temp*Math.cos(endRatioFrame.mAngle));
moveY=(int)(temp*Math.sin(endRatioFrame.mAngle));
通过上面的计算公式逻辑,就可以得到气泡展开时的类型估算器的实现类,退出气泡就将逻辑反一下就可以了
packagecom.cj.dynamicavatarview.ratio;
importandroid.animation.TypeEvaluator;
importandroid.content.Context;
importandroid.util.TypedValue;
importjava.util.ArrayList;
importjava.util.List;
*Createdbychenjon2016/10/19.
publicclassEnterRatioFrameEvaluatorimplementsTypeEvaluator{
publicstaticfinalintOFFSET_DISTANCE=80;
privateContextmContext;
privateintmOffsetDistance;
publicEnterRatioFrameEvaluator(Contextcontext){
this.mContext=context;
mOffsetDistance=(int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,OFFSET_DISTANCE,mContext.getResources().getDisplayMetrics());
@Override
publicObjectevaluate(floatfraction,ObjectstartValue,ObjectendValue){
List<
RatioFrame>
startRatioFrameList=(List<
)startValue;
//开始值
endRatioFrameList=(List<
)endValue;
//结束值
ratioFrameList=newArrayList<
>
();
//产生的新值
endRatioFrameList.size();
RatioFrameendRatioFrame=endRatioFrameList.get(i);
RatioFramestartRatioFrame=startRatioFrameList.get(i);
//计算left,top,right,bottom
doublet=(-2*Math.pow(fraction,2)+2*fraction);
//倾斜变化率
inttemp=(int)((mOffsetDistance)*t);
intmoveX=0,moveY=0;
//让气泡上、下、左、右平移,形成弧度的平移路线
moveX=(int)(temp*Math.cos(endRatioFrame.mAngle));
moveY=(int)(temp*Math.sin(endRatioFrame.mAngle));
//重新得到left,top,right,bottom
intleft=(int)(startRatioFrame.mLeft+((endRatioFrame.mLeft-startRatioFrame.mLeft)*fraction)-moveX);
inttop=(int)(startRatioFrame.mTop+((endRatioFrame.mTop-startRatioFrame.mTop)*fraction)-moveY);
intright=(int)(startRatioFrame.mRight+((endRatioFrame.mRight-startRatioFrame.mRight)*fraction)-moveX);
intbottom=(int)(startRatioFrame.mBottom+((endRatioFrame.mBottom-startRatioFrame.mBottom)*fraction)-moveY);
ratioFrameList.add(newRatioFrame(left,top,right,bottom));
returnratioFrameList;
}
下面就可以用ValueAnimator来实现弧形平移轨迹了
ValueAnimatormAnimatorEnetr=ValueAnimator.ofObject(newEnterRatioFrameEvaluator(getContext()),getRatioFrameCenterList(mRatioFrameCenter,mRatioFrameList),mRatioFrameList);
mAnimatorEnetr.addUpdateListener(newValueAnimator.AnimatorUpdateListener(){
publicvoidonAnimationUpdate(ValueAnimatoranimation){
//获取新的布局值
mCurrentRatioFrameList=(List<
)animation.getAnimatedValue();
//请求重新布局
requestLayout();
});
mAnimatorEnetr.setDuration(OPEN_BUBBLE_TIME);
mAnimatorEnetr.start();
好了,从中心点向外展开的弧形动画到这就实现了,然后再加上缩放的动画就可以了,缩放的动画使用View动画就可以实现。
*气泡由小到大缩放
privatevoidscaleSmallToLarge(List<
//以view中心为缩放点,由初始状态缩小到看不间
ScaleAnimationanimation=newScaleAnimation(
0.0f,1.0f,//一点点变小知道看不见为止
0.0f,1.0f,
Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f//中间缩放
);
animation.setDuration(OPEN_BUBBLE_TIME);
//要和平移的时间一致
//再执行动画
textViews.get(i).startAnimation(animation);
下面解决的就是展开后,气泡开始浮动,点击气泡后停止浮动,滑动手指的之后气泡跟着手指移动,松开手指后气泡返回到原来的位置,返回时的动画效果和气泡展开的动画效果非常的类似,气泡跟着手指移动也很好实现,只需要将气泡view设置onTouch事件,再onTouch中计算滑动的距离,然后重新view.layout()就可以了,所以这里我们解决浮动问题就可以了。
浮动是不规则的,并且浮动的距离和速度也是不一样的,我用View动画实现的效果不是很好,然后就改用了属性动画来实现。
只需要将view平移x轴和y轴,让其平移的距离和时间都不同,看上去就像无规则的移动,让其反复的做这样的平移就可以实现浮动的效果。
*给指定的View设置浮动效果
*@paramview
*@return
privateAnimatorSetsetAnimFloat(Viewview){
Animator>
animators=newArrayList<
//getRandomDp()得到一个随机的值
ObjectAnimatortranslationXAnim=ObjectAnimator.ofFloat(view,"
translationX"
0f,getRandomDp(),getRandomDp(),0);
translationXAnim.setDuration(getRandomTime());
translationXAnim.setRepeatCount(ValueAnimator.INFINITE);
//无限循环
translationXAnim.setRepeatMode(ValueAnimator.I