Android模仿Toast實(shí)現(xiàn)提示框效果
本文實(shí)例為大家分享了Android模仿Toast實(shí)現(xiàn)提示框效果的具體代碼,供大家參考,具體內(nèi)容如下
Toast提示只要提示的時(shí)間夠長(zhǎng),就可以浮動(dòng)到其他任何界面之上,所以我們可以模仿Toast來實(shí)現(xiàn)來電號(hào)碼歸屬地的提示框
1、WindowManager
The interface that apps use to talk to the window manager. Use Context.getSystemService(Context.WINDOW_SERVICE) to get one of these. Each window manager instance is bound to a particular Display.
1).void addView(View view,ViewGroup.LayoutParams params)
將一個(gè)View視圖顯示到當(dāng)前窗口,LayoutParams are used by views to tell their parents how they want to be laid out.
2).void removeView(View view); 將一個(gè)View視圖從當(dāng)前窗口中移除。
2、自定義窗體提示框(參考Toast源碼)
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);? View view = View.inflate(getApplicationContext(), R.layout.toast_location, ? ? ? ? ? ? ? ? null);? TextView tv = (TextView) view.findViewById(R.id.tv_toast_address); tv.setText(address); LayoutParams params = new LayoutParams(); params.height = WindowManager.LayoutParams.WRAP_CONTENT; params.width = WindowManager.LayoutParams.WRAP_CONTENT; params.gravity = Gravity.LEFT | Gravity.TOP; params.x = sp.getInt("lastx", 0); params.y = sp.getInt("lasty", 0); //本來還有一個(gè)FLAG_NOTUCHALBE為了讓下面能觸摸把這個(gè)給去掉了 params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; params.format = PixelFormat.TRANSLUCENT; ? ?//源碼中這里是TYPE_TAOST但是這里為了下面要進(jìn)行點(diǎn)擊拖動(dòng)事件,而Toast不能拖動(dòng), 所以這里改成了TYPE_PRIORITY_PHONE,這是一個(gè)系統(tǒng)類型的提示框,使用這個(gè)提示框必須要申請(qǐng)權(quán)限,android.permission.SYSTEM_ALERT_WINDOW params.type = WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;? wm.addView(view, params);?
3、WindowManager添加的顯示框的簡(jiǎn)單拖動(dòng)
該這個(gè)View注冊(cè)一個(gè)onTouchListener
public void showLocation(String address) { ? ? view = View.inflate(getApplicationContext(), R.layout.toast_location, ? ? ? ? ? ? null); ? ? // 得到spint which = sp.getInt("which", 0); ? ? view.setBackgroundResource(bgs[which]); ? ? view.setOnTouchListener(new OnTouchListener() { ? ? ? ? int startX ,startY; ? ? ? ? public boolean onTouch(View v, MotionEvent event) { ? ? ? ? ? ? switch (event.getAction()) { ? ? ? ? ? ? case MotionEvent.ACTION_DOWN:Log.i(TAG,"摸到"); ? ? ? ? ? ? ? ? startX = (int) event.getRawX(); ? ? ? ? ? ? ? ? startY ?= (int) event.getRawY(); ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? case MotionEvent.ACTION_MOVE:Log.i(TAG,"移動(dòng)"); ? ? ? ? ? ? ? ? int newX = (int) event.getRawX(); ? ? ? ? ? ? ? ? int newY ?= (int) event.getRawY(); ? ? ? ? ? ? ? ? int dx = newX - startX; ? ? ? ? ? ? ? ? int dy = newY - startY; ? ? ? ? ? ? ? ? params.x+=dx; ? ? ? ? ? ? ? ? params.y+=dy; ? //這里在WindowManager中不能夠使用layout方法了,無效,只能使用layoutparams來更新位置,這里的params就是上面的那個(gè)params ? ? ? ? ? ? ? ? wm.updateViewLayout(view, params); ? ? ? ? ? ? ? ? //重新初始化 手指的位置 ? ? ? ? ? ? ? ? startX = (int) event.getRawX(); ? ? ? ? ? ? ? ? startY ?= (int) event.getRawY(); ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? } ? ? ? ? ? ? return true; ? ? ? ? } ? ? }); }
4、普通ImageView隨手指拖動(dòng)改變位置
iv_drag_view.setOnTouchListener(new OnTouchListener() { ? ? //記錄住最初手指按下時(shí)的位置int startX , startY;? ? ? //onTouch方法的返回值如果是true監(jiān)聽器會(huì)把這個(gè)事件給消費(fèi)掉, false則監(jiān)聽器不會(huì)消費(fèi)掉這個(gè)事件public boolean onTouch(View v, MotionEvent event) { ? ? ? ? switch (event.getAction()) { ? ? ? ? ? ? ? case MotionEvent.ACTION_DOWN:Log.i(TAG,"摸到這個(gè)控件了"); ? ? ? ? ? ? ? ? startX = (int) event.getRawX();//記錄手指第一次點(diǎn)擊到屏幕時(shí)候距離x和y軸的距離 ? ? ? ? ? ? ? ? startY = (int) event.getRawY(); ? ? ? ? ? ? break; ? ? ? ? ? ? case MotionEvent.ACTION_MOVE:// 手指在屏幕上移動(dòng)的事件Log.i(TAG,"移動(dòng)"); ? ? ? ? ? ? ? ? int newX = (int) event.getRawX(); //在移動(dòng)的過程中不斷的獲取到手指當(dāng)前移動(dòng)到的位置int newY = (int) event.getRawY(); ? ? ? ? ? ? ? ? int dx = newX - startX; ? ? ? ? ? //計(jì)算出手指移動(dòng)了多少int dy = newY - startY; ? ? ? ? ? ? ? ? int l = iv_drag_view.getLeft(); //獲取圖片上下左右的長(zhǎng)度int r = iv_drag_view.getRight(); ? ? ? ? ? ? ? ? int b = iv_drag_view.getBottom(); ? ? ? ? ? ? ? ? int t = iv_drag_view.getTop(); ? ? ? ? ? ? ? ? int newl = l+dx; //計(jì)算圖片應(yīng)該移動(dòng)的距離int newr = r+dx; ? ? ? ? ? ? ? ? int newt = t+dy;//imageview 在窗體中新的位置int newb = b+dy; ? ? ? ? ? ? ? ? //判斷如果圖片準(zhǔn)備移動(dòng)到的位置超出了屏幕就不讓它移動(dòng),這里減去30是減去窗體上面的狀態(tài)欄的高度if(newl<0||newt < 0 ||newb>display.getHeight()-30||newr>display.getWidth()){ ? ? ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? ? ? ? ? //將圖片移動(dòng)到新的位置。直接調(diào)用ImageView的layout方法 ? ? ? ? ? ? ? ? iv_drag_view.layout(newl, ?newt, newr, newb);? ? ? ? ? ? ? ? ? //一旦圖片移動(dòng)到新的位置就重新計(jì)算手指當(dāng)前的位置,這樣循環(huán)下去就能實(shí)現(xiàn)隨著手指的拖動(dòng) ? ? ? ? ? ? ? ? startX = (int) event.getRawX(); ? ? ? ? ? ? ? ? startY = (int) event.getRawY(); ? ? ? ? ? ? break; ? ? ? ? ? ? case MotionEvent.ACTION_UP: // 手指在離開屏幕的一瞬間對(duì)應(yīng)的事件.Log.i(TAG,"放手"); ? ? ? ? ? ? int lasty = iv_drag_view.getTop();//得到最后在離屏幕上方的距離int lastx = iv_drag_view.getLeft();//得到最后離屏幕左邊的距離Editor editor = sp.edit(); ? ? ? ? ? ? editor.putInt("lastx", lastx); ? ? ? ? ? ? editor.putInt("lasty", lasty); ? ? ? ? ? ? editor.commit(); ? ? ? ? ? ? break; ? ? ? ? } ? ? ? ? ? ? return true; //這地方一定要返回true告訴系統(tǒng)這個(gè)事件做完了 ? ? } });
注意:在onCreate方法中使用layout方法是沒有效果的,因?yàn)樵谶M(jìn)入一個(gè)Activity中系統(tǒng)首先會(huì)執(zhí)行一個(gè)計(jì)算的操作,計(jì)算各個(gè)控件的布局,然后調(diào)用setContentView方法顯示出來這個(gè)控件,第二步才會(huì)執(zhí)行這個(gè)layout方法,但是在onCreate方法中設(shè)置了layout,在執(zhí)行l(wèi)ayout這段代碼的時(shí)候,窗體有可能還沒有計(jì)算完控件的布局,所以先執(zhí)行了這個(gè)layout,然后又執(zhí)行了計(jì)算控件布局來顯示,這樣layout就沒效了,這里要怎么弄呢只能是通過設(shè)置這個(gè)控件的layout布局,這樣在計(jì)算位置的時(shí)候就能計(jì)算了,這樣設(shè)置布局能讓它在計(jì)算的時(shí)候就計(jì)算了。如下,在onCreate方法中去這樣設(shè)置。
protected void onCreate(Bundle savedInstanceState) { ? ? super.onCreate(savedInstanceState); ? ? sp = getSharedPreferences("config", MODE_PRIVATE); ? ? // Have the system blur any windows behind this one. ? ? getWindow().setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND, ? ? ? ? ? ? WindowManager.LayoutParams.FLAG_BLUR_BEHIND); ? ? wm = (WindowManager) getSystemService(WINDOW_SERVICE);//窗體管理者 ? ? display = wm.getDefaultDisplay(); ? ? setContentView(R.layout.activity_drag_view); ? ? tv_drag_view = (TextView) findViewById(R.id.tv_drag_view); ? ? iv_drag_view = (ImageView) findViewById(R.id.iv_drag_view); ? ? int lastx = sp.getInt("lastx", 0); ? ? int lasty = sp.getInt("lasty", 0); ? ? RelativeLayout.LayoutParams params = (LayoutParams) iv_drag_view.getLayoutParams(); ? ? params.leftMargin = lastx; ? ? params.topMargin = lasty; ? ? iv_drag_view.setLayoutParams(params);? }
注意:在WindowManager中要想更新控件的距離就不能用layout方法了,只能用mWindowManager.updateViewLayout(view, params);
5、實(shí)現(xiàn)雙擊事件
1).雙擊的定義 Android中沒有提供雙擊的點(diǎn)擊事件,雙擊就是單位時(shí)間內(nèi)的兩次點(diǎn)擊
2).觸摸和點(diǎn)擊事件的區(qū)別 點(diǎn)擊事件: 一組動(dòng)作的集合 點(diǎn)擊 - 停留 - 離開. 觸摸事件: 手指按下屏幕 手指在屏幕上移動(dòng) 手指離開屏幕的一瞬間
public class DragViewActivity extends Activity { ? ? protected static final String TAG = "DragViewActivity"; ? ? private ImageView iv_drag_view; ? ? private TextView tv_drag_view; ? ? private SharedPreferences sp; ? ? private WindowManager wm; ? ? private Display ?display; //窗體的顯示的分辨率private long firstClickTime;//第一次點(diǎn)擊時(shí)候的事件@Overrideprotected void onCreate(Bundle savedInstanceState) { ? ? ? ? super.onCreate(savedInstanceState); ? ? ? ? sp = getSharedPreferences("config", MODE_PRIVATE); ? ? ? ? // Have the system blur any windows behind this one. ? ? ? ? getWindow().setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND, ? ? ? ? ? ? ? ? WindowManager.LayoutParams.FLAG_BLUR_BEHIND); ? ? ? ? wm = (WindowManager) getSystemService(WINDOW_SERVICE);//窗體管理者 ? ? ? ? display = wm.getDefaultDisplay(); ? ? ? ? setContentView(R.layout.activity_drag_view); ? ? ? ? tv_drag_view = (TextView) findViewById(R.id.tv_drag_view); ? ? ? ? iv_drag_view = (ImageView) findViewById(R.id.iv_drag_view); ? ? ? ? int lastx = sp.getInt("lastx", 0); ? ? ? ? int lasty = sp.getInt("lasty", 0); ? ? ? ? RelativeLayout.LayoutParams params = (LayoutParams) iv_drag_view.getLayoutParams(); ? ? ? ? params.leftMargin = lastx; ? ? ? ? params.topMargin = lasty; ? ? ? ? iv_drag_view.setLayoutParams(params); ? ? ? ? iv_drag_view.setOnClickListener(new OnClickListener() { ? ? ? ? ? ? public void onClick(View v) { ? ? ? ? ? ? ? ? Log.i(TAG,"被點(diǎn)擊了."); ? ? ? ? ? ? ? ? if(firstClickTime>0){//說明這是第二次點(diǎn)擊.long secondTime = System.currentTimeMillis(); ? ? ? ? ? ? ? ? ? ? long dtime = secondTime - firstClickTime; ? ? ? ? ? ? ? ? ? ? if(dtime<500){ ? ? ? ? ? ? ? ? ? ? ? ? //雙擊事件.Log.i(TAG,"雙擊居中"); ? ? ? ? ? ? ? ? ? ? ? ? int iv_width = iv_drag_view.getRight() - iv_drag_view.getLeft(); ? ? ? ? ? ? ? ? ? ? ? ? iv_drag_view.layout(display.getWidth()/2-iv_width/2, iv_drag_view.getTop(), display.getWidth()/2+iv_width/2, iv_drag_view.getBottom()); ? ? ? ? ? ? ? ? ? ? ? ? int lasty = iv_drag_view.getTop();//得到最后在離屏幕上方的距離int lastx = iv_drag_view.getLeft();//得到最后離屏幕左邊的距離Editor editor = sp.edit(); ? ? ? ? ? ? ? ? ? ? ? ? editor.putInt("lastx", lastx); ? ? ? ? ? ? ? ? ? ? ? ? editor.putInt("lasty", lasty); ? ? ? ? ? ? ? ? ? ? ? ? editor.commit(); ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? firstClickTime = 0;//將第一次點(diǎn)擊的時(shí)間還原成0。return; ? ? ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? //第一次點(diǎn)擊 ? ? ? ? ? ? ? ? ? ? firstClickTime = System.currentTimeMillis();// ?記錄第一次點(diǎn)擊的時(shí)間//新開一個(gè)線程,在這個(gè)子線程中如果是500毫秒內(nèi)沒有再點(diǎn)擊就將第一次點(diǎn)擊的時(shí)間設(shè)置為0new Thread(){ ? ? ? ? ? ? ? ? ? ? ? ? public void run() { ? ? ? ? ? ? ? ? ? ? ? ? ? ? try { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Thread.sleep(500); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? firstClickTime = 0; ? ? ? ? ? ? ? ? ? ? ? ? ? ? } catch (InterruptedException e) { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? ? ? }; ? ? ? ? ? ? ? ? ? ? }.start(); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ?? ? ? ? ? ? ? } ? ? ? ? }); ? ? } }
6、觸摸和雙擊同時(shí)發(fā)生時(shí)候的返回值
//onTouch方法的返回值,True if the listener has consumed the event, false otherwise,true 監(jiān)聽器會(huì)把這個(gè)事件給消費(fèi)掉, false 不會(huì)消費(fèi)掉這個(gè)事件 iv_drag_view.setOnTouchListener(new OnTouchListener() { ? ? int startX , startY; ? ? public boolean onTouch(View v, MotionEvent event) { ? ? ? ? switch (event.getAction()) { ? ? ? ? case MotionEvent.ACTION_DOWN:// 手指觸摸到屏幕的事件Log.i(TAG,"摸到這個(gè)控件了"); ? ? ? ? ? ? startX = (int) event.getRawX(); ? ? ? ? ? ? startY = (int) event.getRawY(); ? ? ? ? ? ? break; ? ? ? ? case MotionEvent.ACTION_MOVE:// 手指在屏幕上移動(dòng)的事件Log.i(TAG,"移動(dòng)"); ? ? ? ? ? ? int newX = (int) event.getRawX(); ? ? ? ? ? ? int newY = (int) event.getRawY(); ? ? ? ? ? ? int dx = newX - startX; ? ? ? ? ? ? int dy = newY - startY; ? ? ? ? ? ? int l = iv_drag_view.getLeft(); ? ? ? ? ? ? int r = iv_drag_view.getRight(); ? ? ? ? ? ? int b = iv_drag_view.getBottom(); ? ? ? ? ? ? int t = iv_drag_view.getTop(); ? ? ? ? ? ? int newl = l+dx; ? ? ? ? ? ? int newr = r+dx; ? ? ? ? ? ? int newt = t+dy;//imageview 在窗體中新的位置int newb = b+dy; ? ? ? ? ? ? if(newl<0||newt < 0 ||newb>display.getHeight()-30||newr>display.getWidth()){ ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? } ? ? ? ? ? ? int tv_height = tv_drag_view.getBottom() - tv_drag_view.getTop(); ? ? ? ? ? ? if(newt>display.getHeight()/2){//imageview在窗體的下方//textview在窗體的上方 ? ? ? ? ? ? ? ? tv_drag_view.layout(tv_drag_view.getLeft(), 0, tv_drag_view.getRight(), tv_height); ? ? ? ? ? ? }else{ ? ? ? ? ? ? ? ? tv_drag_view.layout(tv_drag_view.getLeft(), display.getHeight()-tv_height-30, tv_drag_view.getRight(), display.getHeight()-30); ? ? ? ? ? ? ? ? //textview在窗體的下方 ? ? ? ? ? ? } ? ? ? ? ? ? iv_drag_view.layout(newl, ?newt, newr, newb); ? ? ? ? ? ? //更新手指開始的位置. ? ? ? ? ? ? startX = (int) event.getRawX(); ? ? ? ? ? ? startY = (int) event.getRawY(); ? ? ? ? ? ? break; ? ? ? ? case MotionEvent.ACTION_UP: // 手指在離開屏幕的一瞬間對(duì)應(yīng)的事件.Log.i(TAG,"放手"); ? ? ? ? ? ? int lasty = iv_drag_view.getTop();//得到最后在離屏幕上方的距離int lastx = iv_drag_view.getLeft();//得到最后離屏幕左邊的距離Editor editor = sp.edit(); ? ? ? ? ? ? editor.putInt("lastx", lastx); ? ? ? ? ? ? editor.putInt("lasty", lasty); ? ? ? ? ? ? editor.commit(); ? ? ? ? ? ? break; ? ? ? ? } ? ? ? ? // 這里對(duì)于觸摸事件應(yīng)該是返回true為什么這里返回false呢,因?yàn)檫@里這一個(gè)控件同時(shí)實(shí)現(xiàn)了點(diǎn)擊和觸摸這兩個(gè)事件,如果返回true,// 那么就不可能發(fā)生點(diǎn)擊事件了,所以對(duì)于同時(shí)實(shí)現(xiàn)點(diǎn)擊和觸摸的控件返回值要為falsereturn false; ? ? } });
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android使用RadioGroup實(shí)現(xiàn)底部導(dǎo)航欄
這篇文章主要為大家詳細(xì)介紹了Android使用RadioGroup實(shí)現(xiàn)底部導(dǎo)航欄,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08Android實(shí)現(xiàn)側(cè)滑菜單DrawerLayout
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)側(cè)滑菜單DrawerLayout,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-05-05Android UI手機(jī)信息頁(yè)面設(shè)計(jì)
這篇文章主要為大家詳細(xì)介紹了Android UI手機(jī)信息頁(yè)面的設(shè)計(jì)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03android幾種不同對(duì)話框的實(shí)現(xiàn)方式
這篇文章介紹了android幾種不同對(duì)話框的實(shí)現(xiàn),主要包括:1、顯示提示消息的對(duì)話框.2、簡(jiǎn)單列表項(xiàng)對(duì)話框。3、單選列表項(xiàng)對(duì)話框。4、多選列表對(duì)話框。5、自定義列表項(xiàng)對(duì)話框。6、自定義View的對(duì)話框,需要的朋友可以參考下2015-08-08在Android中如何使用DataBinding詳解(Kotlin)
這篇文章主要給大家介紹了關(guān)于在Android中如何使用DataBinding(Kotlin)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11Android版微信跳一跳小游戲利用技術(shù)手段達(dá)到高分的操作方法
朋友圈到處都是曬微信跳一跳小游戲的,很多朋友能達(dá)到二三百分了。下面小編給大家分享Android版微信跳一跳小游戲利用技術(shù)手段達(dá)到高分的操作方法,需要的朋友一起看看吧2018-01-01Ionic2創(chuàng)建App啟動(dòng)頁(yè)左右滑動(dòng)歡迎界面
使用Ionic2創(chuàng)建應(yīng)用非常簡(jiǎn)單,只需在V1的命令后跟上--v2即可.這篇文章主要介紹了Ionic2創(chuàng)建App啟動(dòng)頁(yè)左右滑動(dòng)歡迎界面的相關(guān)資料,需要的朋友可以參考下2016-10-10