實現這個功能的關鍵是: 你需要知道哪個button處需要給個指引的高亮顯示,這個涉及到座標的運算,免得位置放偏。
先給大家看看做的效果圖:把沒有做好的也放上去,這樣更容易看出問題和需要注意的地方。(圖一是沒有設置padding,效果不好;圖二是是指padding之後的效果,但是位置沒有對準;圖三才是正確的姿勢)
看實現過程:
- 背景佈局和蒙版佈局需要實現重疊效果,就用了個RelativeLayout:
背景佈局不多說了(demo中會有完整的),現在看蒙版佈局:
<RelativeLayout
android:id="@+id/rl_guide"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#bb000000"
android:orientation="vertical"
android:clickable="true"
android:visibility="gone"
>
<LinearLayout
android:id="@+id/ll_guide"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="@android:color/white"
android:visibility="visible"
>
<ImageView
android:id="@+id/iv_guide"
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@mipmap/send_icon48x48"
android:layout_marginRight="10dp"
/>
<TextView
android:id="@+id/tv_guide"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="發消息"
android:gravity="center_vertical"
android:layout_gravity="center_vertical"
/>
</LinearLayout>
<ImageView
android:id="@+id/iv_imageGuide"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@mipmap/guide_msg"
android:layout_below="@+id/ll_guide"
android:visibility="gone"
android:clickable="true"
/>
</RelativeLayout>
2.分析activity中的代碼:
(1)根據背景中發消息的圖標,計算它在屏幕中的位置,然後設置蒙版中對應的位置:調用getLocationOnScreen()這個方法可以獲取座標,但是這個包含了通知欄的位置,所以要相應減去通知欄高度。
/**測量通知欄高度*/
private void getstatusBarHeight() {
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
statusBarHeight = getResources().getDimensionPixelSize(resourceId);
System.out.println("hxy:"+"statusBarHeight"+statusBarHeight);
}
}
(2)正式開始計算髮消息view的座標:
private void measureGuideLocation() {
//注意:此處需要開闢線程,延遲1s左右來做,以防測量不到座標
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
iv_sendMs.getLocationOnScreen(location);
rect.left = iv_sendMs.getLeft();
rect.top = iv_sendMs.getTop();
rect.right = iv_sendMs.getRight();
rect.bottom = iv_sendMs.getBottom();
xLocation = location[0];
yLocation = location[1];
System.out.println("hxy:"+"xLocation:"+xLocation+"yLocation:"+yLocation); System.out.println("hxy:"+"rect.left:"+rect.left+"rect.top:"+rect.top+"rect.right"+rect.right+"rect.bottom"+rect.bottom);
//更新控件的位置,放在UI線程中做:
runOnUiThread(new Runnable() {
@Override
public void run() {
setGuideLocation();
}
});
}
}).start();
}
(3)看setGuideLocation()中的方法:
實現圖一的效果的代碼,不設置padding:
layoutParams.setMargins((int)xLocation,(int)yLocation-statusBarHeight,0,0);
ll_guide.setLayoutParams(layoutParams);
實現圖二效果的代碼,設置padding之後有 誤差:
layoutParams.setMargins((int)xLocation,(int)yLocation-statusBarHeight,0,0);
ll_guide.setLayoutParams(layoutParams);
ll_guide.setPadding(rect.top,rect.top,rect.top,rect.top);
後面畫圖分析了下原因:
再次糾正代碼,完整如下,實現了圖三的效果:
private void setGuideLocation() {
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) ll_guide.getLayoutParams();
layoutParams.setMargins((int)xLocation-rect.top,(int)yLocation-statusBarHeight-rect.top,0,0);
ll_guide.setLayoutParams(layoutParams);
ll_guide.setPadding(rect.top,rect.top,rect.top,rect.top);
rl_guide.setVisibility(View.VISIBLE);
ll_guide.setVisibility(View.VISIBLE);
iv_imageGuide.setVisibility(View.VISIBLE);
}
通過以上步驟,就可以實現Android蒙版的效果了,大家可以試試,或許有更好的方法,可以一起分享。
demo下載地址點它