多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國(guó)內(nèi)最全I(xiàn)T社區(qū)平臺(tái) 聯(lián)系我們 | 收藏本站
阿里云優(yōu)惠2
您當(dāng)前位置:首頁(yè) > php開(kāi)源 > 綜合技術(shù) > Android 利用二次貝塞爾曲線模仿購(gòu)物車(chē)添加物品拋物線動(dòng)畫(huà)

Android 利用二次貝塞爾曲線模仿購(gòu)物車(chē)添加物品拋物線動(dòng)畫(huà)

來(lái)源:程序員人生   發(fā)布時(shí)間:2016-11-20 16:29:29 閱讀次數(shù):3551次

Android 利用2次貝塞爾曲線模仿購(gòu)物車(chē)添加物品拋物線動(dòng)畫(huà)


0.首先,先給出1張效果gif圖。


1.貝塞爾曲線原理及相干公式參考:http://www.jianshu.com/p/c0d7ad796cee 作者:許方鎮(zhèn) 。

2.原理:計(jì)算被點(diǎn)擊 view、購(gòu)物車(chē)view 和他們所在父容器相對(duì)屏幕的坐標(biāo)。

3.在唄點(diǎn)擊View坐標(biāo)位置 父容器通過(guò)addView 增加需要完成動(dòng)畫(huà)的imgview。

4.自定義估值器 通過(guò)2次貝塞爾曲線公式(2個(gè)數(shù)據(jù)點(diǎn),1個(gè)控制點(diǎn))完成拋物線路徑上的點(diǎn)xy坐標(biāo)計(jì)算。

5.利用屬性動(dòng)畫(huà) +自定義估值器 完成imgview在父容器內(nèi)部的拋物線動(dòng)畫(huà)。

6.先給布局,其中包括1個(gè)ListView、 1個(gè)ImageView 、需要用到的父容器。

<?xml version="1.0" encoding="utf⑻"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#00ffe1" android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity"> <RelativeLayout android:id="@+id/main_container" android:layout_width="match_parent" android:layout_height="match_parent"> <ListView android:id="@+id/main_lv" android:layout_width="match_parent" android:layout_height="match_parent" android:divider="#0011ff" android:dividerHeight="2dp"/> <!-- shop img--> <ImageView android:id="@+id/main_img" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_marginBottom="20dp" android:layout_marginLeft="20dp" android:src="@mipmap/shop"/> </RelativeLayout> </LinearLayout>

7. 給出ListView Item 布局:

<?xml version="1.0" encoding="utf⑻"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#FFF" android:padding="30dp"> <TextView android:id="@+id/item_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:textColor="#F00" android:textSize="20sp"/> <ImageView android:id="@+id/item_img" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:src="@mipmap/add"/> </RelativeLayout>

8.給出ListView Adapter代碼 僅僅是點(diǎn)擊時(shí)增加了回調(diào)接口:

public class ItemAdapter extends BaseAdapter implements View.OnClickListener { List<String> data = new ArrayList<>(); Context mContext; public ItemAdapter(Context context) { mContext = context; for (int i = 0; i < 30; i++) { data.add("item+" + i); } } @Override public int getCount() { return data.size(); } @Override public Object getItem(int position) { return data.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = LayoutInflater.from(mContext).inflate(R.layout.item, parent, false); convertView.setTag(new ViewH(convertView)); } ViewH holder = (ViewH) convertView.getTag(); holder.tv.setText(data.get(position)); holder.img.setOnClickListener(this); return convertView; } @Override public void onClick(View v) { if (mListener != null) { mListener.add(v); } } private AddClickListener mListener; public void setListener(AddClickListener listener) { mListener = listener; } public interface AddClickListener { void add(View v); } public static class ViewH { private ImageView img; private TextView tv; public ViewH(View view) { img = ((ImageView) view.findViewById(R.id.item_img)); tv = ((TextView) view.findViewById(R.id.item_text)); } } }
9.其中自定義MoveImageView僅僅是增加了1個(gè)set方法方便屬性動(dòng)畫(huà) update時(shí)調(diào)用。

public class MoveImageView extends ImageView { public MoveImageView(Context context) { super(context); } public void setMPointF(PointF pointF) { setX(pointF.x); setY(pointF.y); } }


10.重要的實(shí)現(xiàn)在Activity部份:

public class MainActivity extends AppCompatActivity implements ItemAdapter.AddClickListener, Animator.AnimatorListener { private ImageView shopImg;//購(gòu)物車(chē) IMG private RelativeLayout container;//ListView 購(gòu)物車(chē)View的父布局 private ListView itemLv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViews(); initViews(); } private void initViews() { ItemAdapter adapter = new ItemAdapter(this); //當(dāng)前Activity實(shí)現(xiàn) adapter內(nèi)部 點(diǎn)擊的回調(diào) adapter.setListener(this); itemLv.setAdapter(adapter); } /** * ListView + 點(diǎn)擊回調(diào)方法 */ @Override public void add(View addV) { int[] childCoordinate = new int[2]; int[] parentCoordinate = new int[2]; int[] shopCoordinate = new int[2]; //1.分別獲得被點(diǎn)擊View、父布局、購(gòu)物車(chē)在屏幕上的坐標(biāo)xy。 addV.getLocationInWindow(childCoordinate); container.getLocationInWindow(parentCoordinate); shopImg.getLocationInWindow(shopCoordinate); //2.自定義ImageView 繼承ImageView MoveImageView img = new MoveImageView(this); img.setImageResource(R.mipmap.heart1); //3.設(shè)置img在父布局中的坐標(biāo)位置 img.setX(childCoordinate[0] - parentCoordinate[0]); img.setY(childCoordinate[1] - parentCoordinate[1]); //4.父布局添加該Img container.addView(img); //5.利用 2次貝塞爾曲線 需首先計(jì)算出 MoveImageView的2個(gè)數(shù)據(jù)點(diǎn)和1個(gè)控制點(diǎn) PointF startP = new PointF(); PointF endP = new PointF(); PointF controlP = new PointF(); //開(kāi)始的數(shù)據(jù)點(diǎn)坐標(biāo)就是 addV的坐標(biāo) startP.x = childCoordinate[0] - parentCoordinate[0]; startP.y = childCoordinate[1] - parentCoordinate[1]; //結(jié)束的數(shù)據(jù)點(diǎn)坐標(biāo)就是 shopImg的坐標(biāo) endP.x = shopCoordinate[0] - parentCoordinate[0]; endP.y = shopCoordinate[1] - parentCoordinate[1]; //控制點(diǎn)坐標(biāo) x等于 購(gòu)物車(chē)x;y等于 addV的y controlP.x = endP.x; controlP.y = startP.y; //啟動(dòng)屬性動(dòng)畫(huà) ObjectAnimator animator = ObjectAnimator.ofObject(img, "mPointF", new PointFTypeEvaluator(controlP), startP, endP); animator.setDuration(1000); animator.addListener(this); animator.start(); } @Override public void onAnimationStart(Animator animation) { } @Override public void onAnimationEnd(Animator animation) { //動(dòng)畫(huà)結(jié)束后 父布局移除 img Object target = ((ObjectAnimator) animation).getTarget(); container.removeView((View) target); //shopImg 開(kāi)始1個(gè)放大動(dòng)畫(huà) Animation scaleAnim = AnimationUtils.loadAnimation(this, R.anim.shop_scale); shopImg.startAnimation(scaleAnim); } @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } /** * 自定義估值器 */ public class PointFTypeEvaluator implements TypeEvaluator<PointF> { /** * 每一個(gè)估值器對(duì)應(yīng)1個(gè)屬性動(dòng)畫(huà),每一個(gè)屬性動(dòng)畫(huà)僅對(duì)應(yīng)唯逐一個(gè)控制點(diǎn) */ PointF control; /** * 估值器返回值 */ PointF mPointF = new PointF(); public PointFTypeEvaluator(PointF control) { this.control = control; } @Override public PointF evaluate(float fraction, PointF startValue, PointF endValue) { return getBezierPoint(startValue, endValue, control, fraction); } /** * 2次貝塞爾曲線公式 * * @param start 開(kāi)始的數(shù)據(jù)點(diǎn) * @param end 結(jié)束的數(shù)據(jù)點(diǎn) * @param control 控制點(diǎn) * @param t float 0⑴ * @return 不同t對(duì)應(yīng)的PointF */ private PointF getBezierPoint(PointF start, PointF end, PointF control, float t) { mPointF.x = (1 - t) * (1 - t) * start.x + 2 * t * (1 - t) * control.x + t * t * end.x; mPointF.y = (1 - t) * (1 - t) * start.y + 2 * t * (1 - t) * control.y + t * t * end.y; return mPointF; } } private void findViews() { shopImg = (ImageView) findViewById(R.id.main_img); container = (RelativeLayout) findViewById(R.id.main_container); itemLv = (ListView) findViewById(R.id.main_lv); } }

11.購(gòu)物車(chē)有1個(gè)Scale的補(bǔ)間動(dòng)畫(huà):

<?xml version="1.0" encoding="utf⑻"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:duration="200" android:repeatCount="1" android:repeatMode="reverse"> <scale android:fromXScale="1.0" android:fromYScale="1.0" android:pivotX="50%" android:pivotY="50%" android:toXScale="1.2" android:toYScale="1.2"/> </set>

12.供參考~完~~


生活不易,碼農(nóng)辛苦
如果您覺(jué)得本網(wǎng)站對(duì)您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈(zèng)
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關(guān)閉
程序員人生
主站蜘蛛池模板: 国产一级做a爰大片免费久久 | 在线观看国内自拍 | 亚洲国产精品乱码在线观看97 | 日本亚洲中午字幕乱码 | 啪啪午夜| 久久国产精品1区2区3区网页 | 最近最新免费中文字幕一 | 亚洲人成在线播放网站 | 日韩欧美一级a毛片欧美一级 | 亚洲免费中文字幕 | 日本成在线人视频免费视频 | 看一级黄色毛片 | 免费高清毛片在线播放视频 | 久久久精品3d动漫一区二区三区 | 天天视频国产 | 亚洲日韩男人网在线 | 日韩三级免费 | 色综合欧美亚洲另类久久 | www操操操| 亚洲图片 自拍 | 国内视频自拍在线视频 | 操你.com| 亚洲人成片在线观看 | 看一级毛片国产一级毛片 | 国产精品久久在线观看 | 亚洲免费网 | japanese性护士tube | 国产精品天天看天天爽 | 手机在线完整视频免费观看 | 最近新中文字幕大全高清 | 欧美一区二区三区精品 | 中文天堂在线视频 | 91四虎国自产在线播放线 | 老司机午夜精品视频 | 色综合久久久久久久久五月 | 欧美videofree性欧美另类 | 欧美一欧美一区二三区性 | 日韩人成 | 2018av在线| 亚洲日韩中文字幕在线播放 | 亚洲精品久久久久综合91 |