Android 는 3 단계 베 세 르 곡선 을 이용 하여 운동 궤적 의 예 를 그립 니 다.
좋아요 효과 구현,시작 점 및 운동 궤적 사용자 정의
효과 그림:
xml 레이아웃:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/rl_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="stone.wshh.com.touch.MainActivity">
<stone.wshh.com.touch.MyLoveLayout
android:layout_marginBottom="100dp"
android:layout_marginRight="15dp"
android:id="@+id/love_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
</stone.wshh.com.touch.MyLoveLayout>
<Button
android:id="@+id/bt_bottom"
android:text="begin"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="20dp"
android:layout_width="100dp"
android:layout_height="50dp" />
</RelativeLayout>
MainActivity 클래스:
public class MainActivity extends Activity implements View.OnClickListener{
private Button btBottom;
// private WaitNoticeDialog dialog;
// public Handler handler;
private MyLoveLayout love;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btBottom = (Button) findViewById(R.id.bt_bottom);
love = (MyLoveLayout) findViewById(R.id.love_layout);
btBottom.setOnClickListener(this);
// handler=new IHandler(this);
// dialog = new WaitNoticeDialog(this);
}
static class IHandler extends Handler {
private WeakReference<MainActivity> ui;
IHandler(MainActivity ui) {
this.ui = new WeakReference<MainActivity>(ui);
}
@Override
public void handleMessage(Message msg) {
if(ui!=null&&ui.get()!=null){
ui.get().handleMsg(msg);
}
}
}
/**
*
* @param msg
*/
public void handleMsg(Message msg){
switch (msg.what) {
}
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.bt_bottom:
love.addHeart();
break;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
// handler.removeCallbacksAndMessages(null);
}
}
사용자 정의 보기:MyLoveLayout
public class MyLoveLayout extends RelativeLayout {
private Drawable[] drawables;
private Interpolator[] mInterpolators;
private int dWidth, mWidth;
private int dHeight, mHeight;
private LayoutParams lp;
private Random random = new Random();
public MyLoveLayout(Context context, AttributeSet attrs) {
super(context, attrs);
//imageView MyLoveLayout
init();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//
mWidth = getMeasuredWidth();
mHeight = getMeasuredHeight();
}
private void init() {
//
drawables = new Drawable[7];
drawables[0] = getResources().getDrawable(R.drawable.heart_1);
drawables[1] = getResources().getDrawable(R.drawable.heart_2);
drawables[2] = getResources().getDrawable(R.drawable.heart_3);
drawables[3] = getResources().getDrawable(R.drawable.heart_4);
drawables[4] = getResources().getDrawable(R.drawable.heart_5);
drawables[5] = getResources().getDrawable(R.drawable.heart_6);
drawables[6] = getResources().getDrawable(R.drawable.heart_7);
//
mInterpolators = new Interpolator[4];
mInterpolators[0] = new LinearInterpolator();//
mInterpolators[1] = new AccelerateInterpolator();//
mInterpolators[2] = new DecelerateInterpolator();//
mInterpolators[3] = new AccelerateDecelerateInterpolator();//
//
// dWidth = drawables[0].getIntrinsicWidth();
// dHeight = drawables[0].getIntrinsicHeight();
//
dWidth = dip2px(getContext(), 40);
dHeight = dip2px(getContext(), 40);
lp = new LayoutParams(dWidth, dHeight);
// view
// lp.addRule(CENTER_HORIZONTAL, TRUE);// TRUE true
lp.addRule(ALIGN_PARENT_RIGHT, TRUE);
lp.addRule(ALIGN_PARENT_BOTTOM, TRUE);
}
/**
* dp px
*/
private int dip2px(Context context, float dpValue) {
float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
/**
* ,
* alpha (80%-0%)
* scaleX target(20%-100%)
* scaleY
* @param target
* @return
*/
private AnimatorSet getEnterAnimator(final View target) {
ObjectAnimator alpha = ObjectAnimator.ofFloat(target, View.ALPHA, 0.2f, 1f);
ObjectAnimator scaleX = ObjectAnimator.ofFloat(target, View.SCALE_X, 0.2f, 1f);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(target, View.SCALE_Y, 0.2f, 1f);
AnimatorSet enter = new AnimatorSet();
enter.setTarget(target);
enter.setInterpolator(new LinearInterpolator());
enter.setDuration(500).playTogether(alpha, scaleX, scaleY);
return enter;
}
private ValueAnimator getBezierValueAnimator(final View target) {
//
// , 3
BezierEvaluator evaluator = new BezierEvaluator(getPointF(2), getPointF(1));
// , , new PointF()
// ValueAnimator animator = ValueAnimator.ofObject(evaluator, new PointF((mWidth - dWidth) /
// 2, mHeight - dHeight), new PointF(random.nextInt(getWidth()), 0));
// ,
ValueAnimator animator = ValueAnimator.ofObject(evaluator, new PointF(mWidth - dWidth, mHeight - dHeight), new PointF(0, 0));
animator.setTarget(target);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
// x y view
PointF pointF = (PointF) valueAnimator.getAnimatedValue();
target.setX(pointF.x);
target.setY(pointF.y);
// alpha ,
// target.setAlpha(1 - valueAnimator.getAnimatedFraction());
target.setAlpha(1 - valueAnimator.getAnimatedFraction() + 0.3f);
}
});
animator.setDuration(3000);
return animator;
}
private PointF getPointF(int i) {
PointF pointF = new PointF();
//pointF.x,pointF.y , n
pointF.x = random.nextInt(mWidth);//0~loveLayout.Width
// , P2 P1 , ??
// , p1 (1/2height~height), p2 (0~1/2height), ;
//0~loveLayout.Height/2
if (i == 1) {
pointF.y = random.nextInt(mHeight / 2) + mHeight / 2;//P1 Y
} else if (i == 2) {//P2 Y
pointF.y = random.nextInt(mHeight / 2);
}
//
// if (i == 1) {
// pointF.x=mWidth-dWidth*2;
// pointF.y = 3*dHeight;
// } else if (i == 2) {
// pointF.x=dWidth*2;
// pointF.y = mHeight -dHeight;
// }
return pointF;
}
public void addHeart() {
final ImageView imageView = new ImageView(getContext());
//
imageView.setImageDrawable(drawables[random.nextInt(6)]);
imageView.setLayoutParams(lp);
addView(imageView);
AnimatorSet finalSet = new AnimatorSet();
AnimatorSet enterAnimatorSet = getEnterAnimator(imageView);//
ValueAnimator bezierValueAnimator = getBezierValueAnimator(imageView);//
finalSet.playSequentially(enterAnimatorSet, bezierValueAnimator);
// finalSet.playSequentially(bezierValueAnimator);
finalSet.setInterpolator(mInterpolators[random.nextInt(4)]);
finalSet.setTarget(imageView);
finalSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
removeView((imageView));//
}
});
finalSet.start();
}
}
베 세 르 평가 기:Bezier Evaluator
public class BezierEvaluator implements TypeEvaluator<PointF> {
private PointF mControlP1;
private PointF mControlP2;
public BezierEvaluator(PointF controlP1, PointF controlP2) {
this.mControlP1 = controlP1;
this.mControlP2 = controlP2;
}
@Override
public PointF evaluate(float time, PointF start, PointF end) {
float timeLeft = 1.0f - time;
PointF point = new PointF();
point.x = timeLeft * timeLeft * timeLeft * (start.x) + 3 * timeLeft * timeLeft * time *
(mControlP1.x) + 3 * timeLeft * time *
time * (mControlP2.x) + time * time * time * (end.x);
point.y = timeLeft * timeLeft * timeLeft * (start.y) + 3 * timeLeft * timeLeft * time *
(mControlP1.y) + 3 * timeLeft * time *
time * (mControlP2.y) + time * time * time * (end.y);
return point;
}
}
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Bitrise에서 배포 어플리케이션 설정 테스트하기이 글은 Bitrise 광고 달력의 23일째 글입니다. 자체 또는 당사 등에서 Bitrise 구축 서비스를 사용합니다. 그나저나 며칠 전 Bitrise User Group Meetup #3에서 아래 슬라이드를 발표했...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.