模仿美團(tuán)點(diǎn)評(píng)的Android應(yīng)用中價(jià)格和購買欄懸浮固定的效果
隨著移動(dòng)互聯(lián)網(wǎng)的快速發(fā)展,它已經(jīng)和我們的生活息息相關(guān)了,在公交地鐵里面都能看到很多人的人低頭看著自己的手機(jī)屏幕,從此“低頭族”一詞就產(chǎn)生了,作為一名移動(dòng)行業(yè)的開發(fā)人員,我自己也是一名“低頭族”,上下班時(shí)間在公交地鐵上看看新聞來打發(fā)下時(shí)間,有時(shí)候也會(huì)看看那些受歡迎的App的一些界面效果,為什么人家的app那么受歡迎?跟用戶體驗(yàn)跟UI設(shè)計(jì)也有直接的關(guān)系,最近在美團(tuán)和大眾點(diǎn)評(píng)的App看到如下效果,我感覺用戶好,很人性化,所以自己也嘗試著實(shí)現(xiàn)了下,接下來就講解下實(shí)現(xiàn)思路!
如上圖(2)我們看到了,當(dāng)立即搶購布局向上滑動(dòng)到導(dǎo)航欄布局的時(shí)候,立即搶購布局就貼在導(dǎo)航欄布局下面,下面的其他的布局還是可以滑動(dòng),當(dāng)我們向下滑動(dòng)的時(shí)候,立即搶購的布局又隨著往下滑動(dòng)了,看似有點(diǎn)復(fù)雜,但是一說思路可能你就頓時(shí)恍然大悟了。
當(dāng)我們向上滑動(dòng)過程中,我們判斷立即搶購的布局是否滑到導(dǎo)航欄布局下面,如果立即搶購的上面頂?shù)搅藢?dǎo)航欄,我們新建一個(gè)立即搶購的懸浮框來顯示在導(dǎo)航欄下面,這樣子就實(shí)現(xiàn)了立即搶購貼在導(dǎo)航欄下面的效果啦,而當(dāng)我們向下滑動(dòng)的時(shí)候,當(dāng)立即搶購布局的下面剛好到了剛剛新建的立即搶購懸浮框的下面的時(shí)候,我們就移除立即搶購懸浮框,可能說的有點(diǎn)拗口,既然知道了思路,接下來我們就來實(shí)現(xiàn)效果。
新建一個(gè)Android項(xiàng)目,取名MeiTuanDemo,先看立即搶購(buy_layout.xml)的布局,這里為了方便我直接從美團(tuán)上面截去了圖片
<?xml version="1.0" encoding="UTF-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content" > <ImageView android:id="@+id/buy_layout" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="@drawable/buy" /> </LinearLayout>
立即搶購的布局實(shí)現(xiàn)了,接下來實(shí)現(xiàn)主界面的布局,上面是導(dǎo)航欄布局,為了方便還是直接從美團(tuán)截取的圖片,然后下面的ViewPager布局,立即搶購布局,其他布局 放在ScrollView里面,界面還是很簡單的
<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:orientation="vertical" > <ImageView android:id="@+id/imageView1" android:scaleType="centerCrop" android:layout_width="match_parent" android:layout_height="45dip" android:src="@drawable/navigation_bar" /> <com.example.meituandemo.MyScrollView android:id="@+id/scrollView" android:layout_width="fill_parent" android:layout_height="fill_parent" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <ImageView android:id="@+id/iamge" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/pic" android:scaleType="centerCrop" /> <include android:id="@+id/buy" layout="@layout/buy_layout" /> <ImageView android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/one" android:scaleType="centerCrop" /> <ImageView android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/one" android:scaleType="centerCrop" /> <ImageView android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/one" android:scaleType="centerCrop" /> </LinearLayout> </com.example.meituandemo.MyScrollView> </LinearLayout>
你會(huì)發(fā)現(xiàn)上面的主界面布局中并不是ScrollView,而是自定義的一個(gè)MyScrollView,接下來就看看MyScrollView類中的代碼
package com.example.meituandemo; import android.content.Context; import android.os.Handler; import android.util.AttributeSet; import android.view.MotionEvent; import android.widget.ScrollView; /** * 博客地址:http://blog.csdn.net/xiaanming * * @author xiaanming * */ public class MyScrollView extends ScrollView { private OnScrollListener onScrollListener; /** * 主要是用在用戶手指離開MyScrollView,MyScrollView還在繼續(xù)滑動(dòng),我們用來保存Y的距離,然后做比較 */ private int lastScrollY; public MyScrollView(Context context) { this(context, null); } public MyScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public MyScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } /** * 設(shè)置滾動(dòng)接口 * @param onScrollListener */ public void setOnScrollListener(OnScrollListener onScrollListener) { this.onScrollListener = onScrollListener; } /** * 用于用戶手指離開MyScrollView的時(shí)候獲取MyScrollView滾動(dòng)的Y距離,然后回調(diào)給onScroll方法中 */ private Handler handler = new Handler() { public void handleMessage(android.os.Message msg) { int scrollY = MyScrollView.this.getScrollY(); //此時(shí)的距離和記錄下的距離不相等,在隔5毫秒給handler發(fā)送消息 if(lastScrollY != scrollY){ lastScrollY = scrollY; handler.sendMessageDelayed(handler.obtainMessage(), 5); } if(onScrollListener != null){ onScrollListener.onScroll(scrollY); } }; }; /** * 重寫onTouchEvent, 當(dāng)用戶的手在MyScrollView上面的時(shí)候, * 直接將MyScrollView滑動(dòng)的Y方向距離回調(diào)給onScroll方法中,當(dāng)用戶抬起手的時(shí)候, * MyScrollView可能還在滑動(dòng),所以當(dāng)用戶抬起手我們隔5毫秒給handler發(fā)送消息,在handler處理 * MyScrollView滑動(dòng)的距離 */ @Override public boolean onTouchEvent(MotionEvent ev) { if(onScrollListener != null){ onScrollListener.onScroll(lastScrollY = this.getScrollY()); } switch(ev.getAction()){ case MotionEvent.ACTION_UP: handler.sendMessageDelayed(handler.obtainMessage(), 5); break; } return super.onTouchEvent(ev); } /** * * 滾動(dòng)的回調(diào)接口 * * @author xiaanming * */ public interface OnScrollListener{ /** * 回調(diào)方法, 返回MyScrollView滑動(dòng)的Y方向距離 * @param scrollY * 、 */ public void onScroll(int scrollY); } }
一看代碼你也許明白了,就是對(duì)ScrollView的滾動(dòng)Y值進(jìn)行監(jiān)聽,我們知道ScrollView并沒有實(shí)現(xiàn)滾動(dòng)監(jiān)聽,所以我們必須自行實(shí)現(xiàn)對(duì)ScrollView的監(jiān)聽,我們很自然的想到在onTouchEvent()方法中實(shí)現(xiàn)對(duì)滾動(dòng)Y軸進(jìn)行監(jiān)聽,可是你會(huì)發(fā)現(xiàn),我們?cè)诨瑒?dòng)ScrollView的時(shí)候,當(dāng)我們手指離開ScrollView。它可能還會(huì)繼續(xù)滑動(dòng)一段距離,所以我們選擇在用戶手指離開的時(shí)候每隔5毫秒來判斷ScrollView是否停止滑動(dòng),并將ScrollView的滾動(dòng)Y值回調(diào)給OnScrollListener接口的onScroll(int scrollY)方法中,我們只需要對(duì)ScrollView調(diào)用我們只需要對(duì)ScrollView調(diào)用setOnScrollListener方法就能監(jiān)聽到滾動(dòng)的Y值。
實(shí)現(xiàn)了對(duì)ScrollView滾動(dòng)的Y值進(jìn)行監(jiān)聽,接下來就簡單了,我們只需要顯示立即搶購懸浮框和移除懸浮框了,接下來看看主界面Activity的代碼編寫
package com.example.meituandemo; import android.app.Activity; import android.content.Context; import android.graphics.PixelFormat; import android.os.Bundle; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.WindowManager; import android.view.WindowManager.LayoutParams; import android.widget.LinearLayout; import com.example.meituandemo.MyScrollView.OnScrollListener; /** * 博客地址:http://blog.csdn.net/xiaanming * * @author xiaanming * */ public class MainActivity extends Activity implements OnScrollListener{ private MyScrollView myScrollView; private LinearLayout mBuyLayout; private WindowManager mWindowManager; /** * 手機(jī)屏幕寬度 */ private int screenWidth; /** * 懸浮框View */ private static View suspendView; /** * 懸浮框的參數(shù) */ private static WindowManager.LayoutParams suspendLayoutParams; /** * 購買布局的高度 */ private int buyLayoutHeight; /** * myScrollView與其父類布局的頂部距離 */ private int myScrollViewTop; /** * 購買布局與其父類布局的頂部距離 */ private int buyLayoutTop; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); myScrollView = (MyScrollView) findViewById(R.id.scrollView); mBuyLayout = (LinearLayout) findViewById(R.id.buy); myScrollView.setOnScrollListener(this); mWindowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE); screenWidth = mWindowManager.getDefaultDisplay().getWidth(); } /** * 窗口有焦點(diǎn)的時(shí)候,即所有的布局繪制完畢的時(shí)候,我們來獲取購買布局的高度和myScrollView距離父類布局的頂部位置 */ @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if(hasFocus){ buyLayoutHeight = mBuyLayout.getHeight(); buyLayoutTop = mBuyLayout.getTop(); myScrollViewTop = myScrollView.getTop(); } } /** * 滾動(dòng)的回調(diào)方法,當(dāng)滾動(dòng)的Y距離大于或者等于 購買布局距離父類布局頂部的位置,就顯示購買的懸浮框 * 當(dāng)滾動(dòng)的Y的距離小于 購買布局距離父類布局頂部的位置加上購買布局的高度就移除購買的懸浮框 * */ @Override public void onScroll(int scrollY) { if(scrollY >= buyLayoutTop){ if(suspendView == null){ showSuspend(); } }else if(scrollY <= buyLayoutTop + buyLayoutHeight){ if(suspendView != null){ removeSuspend(); } } } /** * 顯示購買的懸浮框 */ private void showSuspend(){ if(suspendView == null){ suspendView = LayoutInflater.from(this).inflate(R.layout.buy_layout, null); if(suspendLayoutParams == null){ suspendLayoutParams = new LayoutParams(); suspendLayoutParams.type = LayoutParams.TYPE_PHONE; //懸浮窗的類型,一般設(shè)為2002,表示在所有應(yīng)用程序之上,但在狀態(tài)欄之下 suspendLayoutParams.format = PixelFormat.RGBA_8888; suspendLayoutParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_NOT_FOCUSABLE; //懸浮窗的行為,比如說不可聚焦,非模態(tài)對(duì)話框等等 suspendLayoutParams.gravity = Gravity.TOP; //懸浮窗的對(duì)齊方式 suspendLayoutParams.width = screenWidth; suspendLayoutParams.height = buyLayoutHeight; suspendLayoutParams.x = 0; //懸浮窗X的位置 suspendLayoutParams.y = myScrollViewTop; ////懸浮窗Y的位置 } } mWindowManager.addView(suspendView, suspendLayoutParams); } /** * 移除購買的懸浮框 */ private void removeSuspend(){ if(suspendView != null){ mWindowManager.removeView(suspendView); suspendView = null; } } }
上面的代碼比較簡單,根據(jù)ScrollView滑動(dòng)的距離來判斷顯示和移除懸浮框,懸浮框的實(shí)現(xiàn)主要是通過WindowManager這個(gè)類來實(shí)現(xiàn)的,調(diào)用這個(gè)類的addView方法用于添加一個(gè)懸浮框,removeView用于移除懸浮框。
通過上述代碼就實(shí)現(xiàn)了美團(tuán),大眾點(diǎn)評(píng)的這種效果,在運(yùn)行項(xiàng)目之前我們必須在AndroidManifest.xml中加入<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
我們運(yùn)行下項(xiàng)目看下效果吧
一個(gè)修改版
上面的代碼,其實(shí)我自己感覺效果并不是很好,如果快速滑動(dòng)界面,顯示懸浮框的時(shí)候會(huì)出現(xiàn)一卡的現(xiàn)象,有些朋友說有時(shí)候會(huì)出現(xiàn)兩個(gè)布局的情況,特別是對(duì)ScrollView滾動(dòng)的Y值得監(jiān)聽,我還使用了Handler來獲取,還有朋友給我介紹了Scrolling Tricks這個(gè)東西,我下載試了下,確實(shí)美團(tuán)網(wǎng),大眾點(diǎn)評(píng)的購買框用的是這種效果,但是Scrolling Tricks只能在API11以上使用,這個(gè)有點(diǎn)小悲劇,然后我做了下修改,并將實(shí)現(xiàn)思路分享給大家,實(shí)現(xiàn)起來很簡單
首先還是要先對(duì)ScrollView進(jìn)行滾動(dòng)監(jiān)聽,直接在onScrollChanged()方法中就能獲取滾動(dòng)的Y值,之前那里使用了Handler,走彎路了,直接看代碼吧
package com.example.meituandemo; import android.content.Context; import android.util.AttributeSet; import android.widget.ScrollView; public class MyScrollView extends ScrollView { private OnScrollListener onScrollListener; public MyScrollView(Context context) { this(context, null); } public MyScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public MyScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } /** * 設(shè)置滾動(dòng)接口 * @param onScrollListener */ public void setOnScrollListener(OnScrollListener onScrollListener) { this.onScrollListener = onScrollListener; } @Override public int computeVerticalScrollRange() { return super.computeVerticalScrollRange(); } @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if(onScrollListener != null){ onScrollListener.onScroll(t); } } /** * * 滾動(dòng)的回調(diào)接口 */ public interface OnScrollListener{ /** * 回調(diào)方法, 返回MyScrollView滑動(dòng)的Y方向距離 * @param scrollY * 、 */ public void onScroll(int scrollY); } }
接下來看看主界面的布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/parent_layout" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <ImageView android:id="@+id/imageView1" android:layout_width="match_parent" android:layout_height="45dip" android:scaleType="centerCrop" android:src="@drawable/navigation_bar" /> <com.example.meituandemo.MyScrollView android:id="@+id/scrollView" android:layout_width="fill_parent" android:layout_height="fill_parent" > <FrameLayout android:layout_width="match_parent" android:layout_height="wrap_content" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <ImageView android:id="@+id/iamge" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/pic" android:scaleType="centerCrop" /> <include android:id="@+id/buy" layout="@layout/buy_layout" /> <ImageView android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/one" android:scaleType="centerCrop" /> <ImageView android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/one" android:scaleType="centerCrop" /> <ImageView android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/one" android:scaleType="centerCrop" /> </LinearLayout> <include android:id="@+id/top_buy_layout" layout="@layout/buy_layout" /> </FrameLayout> </com.example.meituandemo.MyScrollView> </LinearLayout>
下面是布局的效果圖
從主界面的布局你可以看出,我們?cè)谏厦娣胖昧艘粋€(gè)購買的布局,可能你會(huì)想,先讓上面的布局隱藏起來,等下面的布局滑動(dòng)上來就將其顯示出來,如果這樣子就跟我之前寫的那篇文章差不多,效果不是很棒,所以這篇修改版的肯定不是這樣子的,我們還是先看主界面的代碼吧
package com.example.meituandemo; import android.app.Activity; import android.os.Bundle; import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.widget.LinearLayout; import com.example.meituandemo.MyScrollView.OnScrollListener; public class MainActivity extends Activity implements OnScrollListener{ /** * 自定義的MyScrollView */ private MyScrollView myScrollView; /** * 在MyScrollView里面的購買布局 */ private LinearLayout mBuyLayout; /** * 位于頂部的購買布局 */ private LinearLayout mTopBuyLayout; @SuppressWarnings("deprecation") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); myScrollView = (MyScrollView) findViewById(R.id.scrollView); mBuyLayout = (LinearLayout) findViewById(R.id.buy); mTopBuyLayout = (LinearLayout) findViewById(R.id.top_buy_layout); myScrollView.setOnScrollListener(this); //當(dāng)布局的狀態(tài)或者控件的可見性發(fā)生改變回調(diào)的接口 findViewById(R.id.parent_layout).getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() { @Override public void onGlobalLayout() { //這一步很重要,使得上面的購買布局和下面的購買布局重合 onScroll(myScrollView.getScrollY()); } }); } @Override public void onScroll(int scrollY) { int mBuyLayout2ParentTop = Math.max(scrollY, mBuyLayout.getTop()); mTopBuyLayout.layout(0, mBuyLayout2ParentTop, mTopBuyLayout.getWidth(), mBuyLayout2ParentTop + mTopBuyLayout.getHeight()); } }
主界面就短短的幾行代碼,可能看完這些代碼你還是沒有明白到底是怎么做到的,沒關(guān)系,我給大家說說,其實(shí)我們是讓上面的購買布局和下面的購買布局重合起來了,layout()這個(gè)方法是確定View的大小和位置的,然后將其繪制出來,里面的四個(gè)參數(shù)分別是View的四個(gè)點(diǎn)的坐標(biāo),他的坐標(biāo)不是相對(duì)屏幕的原點(diǎn),而且相對(duì)于他的父布局來說的,
我們?cè)谥黜撁孀钔鈱拥腣iewGroup添加了布局狀態(tài)改變的監(jiān)聽器,當(dāng)繪制完了屏幕會(huì)回調(diào)到方法onGlobalLayout()中,我們?cè)趏nGlobalLayout()方法中手動(dòng)調(diào)用了下onScroll()方法,剛開始myScrollView.getScrollY()等于0,所以說當(dāng)scrollY小于mBuyLayout.getTop()的時(shí)候,上面的購買布局的上邊緣到myScrollView的上邊緣的距離等于mBuyLayout.getTop()(即下面布局的上邊緣到myScrollView的上邊緣)所以剛開始上面的購買布局和下面的購買布局重合了。
當(dāng)myScrollView向上滾動(dòng),而上面購買布局的上邊緣始終要和myScrollView的上邊緣保持mBuyLayout.getTop()這個(gè)距離,所以上面的購買布局也跟著向上滾動(dòng),當(dāng)scrollY大于mBuyLayout.getTop()的時(shí)候,表示購買布局上邊緣滑動(dòng)到了導(dǎo)航欄布局,所以此時(shí)購買布局的上邊緣與myScrollView的上邊緣始終要保持scrollY這個(gè)距離,所以購買布局才會(huì)一直在導(dǎo)航欄下面,就好像粘住了一樣,不知道你了解了沒有?好了,不過根據(jù)這種思路你也可以剛開始使用一個(gè)懸浮框來覆蓋在下面的購買布局上面,然后onScroll()方法中更新懸浮框的位置,不過懸浮框的x,y不是相對(duì)于父布局的,這點(diǎn)要注意下,這樣子也能實(shí)現(xiàn)效果,不過相對(duì)于此,要復(fù)雜的多,所以我們遇到類似的功能直接使用這種就行了,簡潔明了,好了,你是不迫不及待的想看下效果,那我們接下來就運(yùn)行下程序吧
含有多個(gè)購買布局的效果,下一個(gè)購買布局會(huì)將上一個(gè)購買布局頂上去,使用方法也很簡單,只需要將你需要設(shè)置的布局設(shè)置Tag為sticky, 如
<FrameLayout android:layout_width="fill_parent" android:layout_height="100dip" android:background="#ff00ffff" android:tag="sticky" > <Button android:id="@+id/button" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Button" /> </FrameLayout>
這樣子這個(gè)布局滾動(dòng)到了頂部就會(huì)粘在頂部,大家可以試試!
- Android自定義StepView仿外賣配送進(jìn)度
- Android仿外賣購物車功能
- Android仿百度外賣自定義下拉刷新效果
- Android仿美團(tuán)下拉菜單(商品選購)實(shí)例代碼
- Android仿美團(tuán)分類下拉菜單實(shí)例代碼
- Android編程實(shí)現(xiàn)仿美團(tuán)或淘寶的多級(jí)分類菜單效果示例【附demo源碼下載】
- Android仿美團(tuán)淘寶實(shí)現(xiàn)多級(jí)下拉列表菜單功能
- Android模仿美團(tuán)頂部的滑動(dòng)菜單實(shí)例代碼
- Android使用RecyclerView仿美團(tuán)分類界面
- Android仿美團(tuán)外賣菜單界面
相關(guān)文章
探究Android中ListView復(fù)用導(dǎo)致布局錯(cuò)亂的解決方案
這篇文章主要介紹了探究Android中ListView復(fù)用導(dǎo)致布局錯(cuò)亂的解決方案,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-10-10Android使用onCreateOptionsMenu()創(chuàng)建菜單Menu的方法詳解
這篇文章主要介紹了Android使用onCreateOptionsMenu()創(chuàng)建菜單Menu的方法,結(jié)合實(shí)例形式較為詳細(xì)的分析了Android基于onCreateOptionsMenu創(chuàng)建菜單的具體步驟與相關(guān)操作技巧,需要的朋友可以參考下2016-11-11Android模仿To圈兒個(gè)人資料界面層疊淡入淡出顯示效果
這篇文章主要介紹了Android模仿To圈兒個(gè)人資料界面層疊淡入淡出顯示效果的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-07-07android實(shí)現(xiàn)倒計(jì)時(shí)功能(開始、暫停、0秒結(jié)束)
這篇文章主要為大家詳細(xì)介紹了android實(shí)現(xiàn)倒計(jì)時(shí)功能,開始、暫停、0秒結(jié)束,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-09-09Android打造流暢九宮格抽獎(jiǎng)活動(dòng)效果
抽獎(jiǎng)活動(dòng)有很多種形式,轉(zhuǎn)盤抽獎(jiǎng),九宮格抽獎(jiǎng),刮刮卡抽獎(jiǎng),這篇文章主要為大家詳細(xì)介紹了如何打造流暢九宮格抽獎(jiǎng)活動(dòng)效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11Flutter質(zhì)感設(shè)計(jì)之表單輸入
這篇文章主要為大家詳細(xì)介紹了Flutter質(zhì)感設(shè)計(jì)之表單輸入,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-08-08教你一步步實(shí)現(xiàn)Android微信自動(dòng)搶紅包
自從微信添加搶紅包的功能,微信的電商之旅算是正式開始正式火爆起來。但是作為Android開發(fā)者來說,我們首先考慮的是如何實(shí)現(xiàn)Android微信自動(dòng)搶紅包呢,下面我們來一起看看吧。2016-08-08