您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關Android項目中項目實現一個控件懸浮效果,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。
效果圖:
新建一個Android項目,取名MeiTuanDemo,先看立即搶購(buy_layout.xml)的布局,這里為了方便我直接從美團上面截去了圖片
<?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>
立即搶購的布局實現了,接下來實現主界面的布局,上面是導航欄布局,為了方便還是直接從美團截取的圖片,然后下面的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>
你會發現上面的主界面布局中并不是ScrollView,而是自定義的一個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還在繼續滑動,我們用來保存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); } /** * 設置滾動接口 * @param onScrollListener */ public void setOnScrollListener(OnScrollListener onScrollListener) { this.onScrollListener = onScrollListener; } /** * 用于用戶手指離開MyScrollView的時候獲取MyScrollView滾動的Y距離,然后回調給onScroll方法中 */ private Handler handler = new Handler() { public void handleMessage(android.os.Message msg) { int scrollY = MyScrollView.this.getScrollY(); //此時的距離和記錄下的距離不相等,在隔5毫秒給handler發送消息 if(lastScrollY != scrollY){ lastScrollY = scrollY; handler.sendMessageDelayed(handler.obtainMessage(), 5); } if(onScrollListener != null){ onScrollListener.onScroll(scrollY); } }; }; /** * 重寫onTouchEvent, 當用戶的手在MyScrollView上面的時候, * 直接將MyScrollView滑動的Y方向距離回調給onScroll方法中,當用戶抬起手的時候, * MyScrollView可能還在滑動,所以當用戶抬起手我們隔5毫秒給handler發送消息,在handler處理 * MyScrollView滑動的距離 */ @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); } /** * * 滾動的回調接口 * * @author xiaanming * */ public interface OnScrollListener{ /** * 回調方法, 返回MyScrollView滑動的Y方向距離 * @param scrollY * 、 */ public void onScroll(int scrollY); } }
一看代碼你也許明白了,就是對ScrollView的滾動Y值進行監聽,我們知道ScrollView并沒有實現滾動監聽,所以我們必須自行實現對ScrollView的監聽,我們很自然的想到在onTouchEvent()方法中實現對滾動Y軸進行監聽,可是你會發現,我們在滑動ScrollView的時候,當我們手指離開ScrollView。它可能還會繼續滑動一段距離,所以我們選擇在用戶手指離開的時候每隔5毫秒來判斷ScrollView是否停止滑動,并將ScrollView的滾動Y值回調給OnScrollListener接口的onScroll(int scrollY)方法中,我們只需要對ScrollView調用我們只需要對ScrollView調用setOnScrollListener方法就能監聽到滾動的Y值。
實現了對ScrollView滾動的Y值進行監聽,接下來就簡單了,我們只需要顯示立即搶購懸浮框和移除懸浮框了,接下來看看主界面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; /** * 手機屏幕寬度 */ private int screenWidth; /** * 懸浮框View */ private static View suspendView; /** * 懸浮框的參數 */ 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(); } /** * 窗口有焦點的時候,即所有的布局繪制完畢的時候,我們來獲取購買布局的高度和myScrollView距離父類布局的頂部位置 */ @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if(hasFocus){ buyLayoutHeight = mBuyLayout.getHeight(); buyLayoutTop = mBuyLayout.getTop(); myScrollViewTop = myScrollView.getTop(); } } /** * 滾動的回調方法,當滾動的Y距離大于或者等于 購買布局距離父類布局頂部的位置,就顯示購買的懸浮框 * 當滾動的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; //懸浮窗的類型,一般設為2002,表示在所有應用程序之上,但在狀態欄之下 suspendLayoutParams.format = PixelFormat.RGBA_8888; suspendLayoutParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_NOT_FOCUSABLE; //懸浮窗的行為,比如說不可聚焦,非模態對話框等等 suspendLayoutParams.gravity = Gravity.TOP; //懸浮窗的對齊方式 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; } } }
上面的代碼比較簡單,根據ScrollView滑動的距離來判斷顯示和移除懸浮框,懸浮框的實現主要是通過WindowManager這個類來實現的,調用這個類的addView方法用于添加一個懸浮框,removeView用于移除懸浮框。
通過上述代碼就實現了美團,大眾點評的這種效果,在運行項目之前我們必須在AndroidManifest.xml中加入<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
我們運行下項目看下效果吧
看完上述內容,你們對Android項目中項目實現一個控件懸浮效果有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。