android pop自定义弹出窗口实现

来源:互联网 发布:六一送什么礼物 知乎 编辑:程序博客网 时间:2024/05/18 01:58

效果如上图,其中弹出框样式可自由定义,

package lian.test.androidtest.pop;import java.util.HashMap;import java.util.Map;import android.content.Context;import android.graphics.Color;import android.graphics.Point;import android.graphics.Rect;import android.graphics.drawable.Drawable;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.view.ViewGroup;import android.view.View.OnTouchListener;import android.view.animation.AlphaAnimation;import android.view.animation.Animation;import android.view.animation.Animation.AnimationListener;import android.widget.ImageView;import android.widget.RelativeLayout;/** *  * 名称:AbPopoverView.java  * 描述:提示框 */public class MyPopView extends RelativeLayout implements OnTouchListener{/** * AbPopoverView的监听器 */public static interface PopoverViewListener{/** * Called when the popover is going to show * @param view The whole popover view */void popoverViewWillShow(MyPopView view);/** * Called when the popover did show * @param view The whole popover view */void popoverViewDidShow(MyPopView view);/** * Called when the popover is going to be dismissed * @param view The whole popover view */void popoverViewWillDismiss(MyPopView view);/** * Called when the popover was dismissed * @param view The whole popover view */void popoverViewDidDismiss(MyPopView view);}/** * Popover arrow points up. Integer to use with bit operators to tell the popover where the arrow should appear and from where the popover should appear */public final static int PopoverArrowDirectionUp    = 0x00000001;/** * Popover arrow points down. Integer to use with bit operators to tell the popover where the arrow should appear and from where the popover should appear */public final static int PopoverArrowDirectionDown  = 0x00000002;/** * Popover arrow points left. Integer to use with bit operators to tell the popover where the arrow should appear and from where the popover should appear */public final static int PopoverArrowDirectionLeft  = 0x00000004;/** * Popover arrow points right. Integer to use with bit operators to tell the popover where the arrow should appear and from where the popover should appear */public final static int PopoverArrowDirectionRight = 0x00000008;/** * Popover arrow points any direction. Integer to use with bit operators to tell the popover where the arrow should appear and from where the popover should appear */public final static int PopoverArrowDirectionAny = PopoverArrowDirectionUp|PopoverArrowDirectionDown|PopoverArrowDirectionLeft|PopoverArrowDirectionRight;/** * The delegate of the view */private PopoverViewListener popoverViewListener;/** * The main popover containing the view we want to show */private RelativeLayout popoverView;/** * The view group storing this popover. We need this so, when we dismiss the popover, we remove it from the view group */private ViewGroup superview;/** * The content size for the view in the popover */private Point contentSizeForViewInPopover = new Point(0, 0);/** * The real content size we will use (it considers the padding) */private Point realContentSize = new Point(0, 0);/** * A hash containing */private Map<Integer, Rect> possibleRects;/** * Whether the view is animating or not */private boolean isAnimating = false;/** * The fade animation time in milliseconds */private int fadeAnimationTime = 300;/** * The layout Rect, is the same as the superview rect */private Rect popoverLayoutRect;/** * The popover background drawable */private Drawable backgroundDrawable;/** * The popover arrow up drawable */private Drawable arrowUpDrawable;/** * The popover arrow down drawable */private Drawable arrowDownDrawable;/** * The popover arrow left drawable */private Drawable arrowLeftDrawable;/** * The popover arrow down drawable */private Drawable arrowRightDrawable;/** * 当前显示的箭头图标 */private ImageView arrowImageView = null;/** * 当前显示的提示的View */private View popoverContentView = null;/** * Constructor to create a popover with a popover view * @param context The context where we should create the popover view */public MyPopView(Context context) {super(context);initPopoverView();}/** * Constructor to create a popover with a popover view * @param context The context where we should create the popover view * @param attrs Attribute set to init the view */public MyPopView(Context context, AttributeSet attrs) {super(context, attrs);initPopoverView();}/** * Constructor to create a popover with a popover view * @param context The context where we should create the popover view * @param attrs Attribute set to init the view * @param defStyle The default style for this view */public MyPopView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);initPopoverView();}/** * Init the popover view * @param viewToEnclose The view we wan to insert inside the popover */private void initPopoverView(){//Init the relative layoutpopoverView = new RelativeLayout(getContext());setBackgroundColor(Color.WHITE);setOnTouchListener(this);}/** * Get the Rect frame for a view (relative to the Window of the application) * @param v The view to get the rect from * @return The rect of the view, relative to the application window */public static Rect getFrameForView(View v){int location [] = new int [2];v.getLocationOnScreen(location);Rect viewRect = new Rect(location[0], location[1], location[0]+v.getWidth(), location[1]+v.getHeight());return viewRect;}/** * Add the popover to the view with a defined rect inside the popover * @param insertRect The rect we want to insert the view */private void addPopoverInRect(Rect insertRect){//Set layout paramsLayoutParams insertParams = new LayoutParams(insertRect.width(), insertRect.height());insertParams.leftMargin = insertRect.left;insertParams.topMargin = insertRect.top;//Add the viewaddView(popoverView, insertParams);}private void initArrow(Rect originRect, Integer arrowDirection){//重新定位if(arrowImageView != null){removeView(arrowImageView);}//Add arrow drawablearrowImageView = new ImageView(getContext());Drawable arrowDrawable = null;int xPos = 0;int arrowWidth = 0;int yPos = 0;int arrowHeight = 0;//Get correct drawable, and get Width, Height, Xpos and yPos depending on the selected arrow directionif (arrowDirection == MyPopView.PopoverArrowDirectionUp){arrowDrawable = arrowUpDrawable;arrowWidth = arrowDrawable.getIntrinsicWidth();arrowHeight = arrowDrawable.getIntrinsicHeight();xPos = originRect.centerX() - (arrowWidth/2) - popoverLayoutRect.left;yPos = originRect.bottom - popoverLayoutRect.top;}else if (arrowDirection == MyPopView.PopoverArrowDirectionDown){arrowDrawable = arrowDownDrawable;arrowWidth = arrowDrawable.getIntrinsicWidth();arrowHeight = arrowDrawable.getIntrinsicHeight();xPos = originRect.centerX() - (arrowWidth/2) - popoverLayoutRect.left;yPos = originRect.top - arrowHeight - popoverLayoutRect.top;}else if (arrowDirection == MyPopView.PopoverArrowDirectionLeft){arrowDrawable = arrowLeftDrawable;arrowWidth = arrowDrawable.getIntrinsicWidth();arrowHeight = arrowDrawable.getIntrinsicHeight();xPos = originRect.right - popoverLayoutRect.left;yPos = originRect.centerY() - (arrowHeight/2) - popoverLayoutRect.top;}else if (arrowDirection == MyPopView.PopoverArrowDirectionRight){arrowDrawable = arrowRightDrawable;arrowWidth = arrowDrawable.getIntrinsicWidth();arrowHeight = arrowDrawable.getIntrinsicHeight();xPos = originRect.left - arrowWidth - popoverLayoutRect.left;yPos = originRect.centerY() - (arrowHeight/2) - popoverLayoutRect.top;}//Set drawablearrowImageView.setImageDrawable(arrowDrawable);//Init layout paramsLayoutParams arrowParams = new LayoutParams(arrowWidth, arrowHeight);arrowParams.leftMargin = xPos;arrowParams.topMargin = yPos;//add viewaddView(arrowImageView, arrowParams);}/** * Calculates the rect for showing the view with Arrow Up * @param originRect The origin rect * @return The calculated rect to show the view */private Rect getRectForArrowUp(Rect originRect){//Get available spaceint xAvailable = popoverLayoutRect.width();if (xAvailable < 0)xAvailable = 0;int yAvailable = popoverLayoutRect.height() - (originRect.bottom - popoverLayoutRect.top);if (yAvailable < 0)yAvailable = 0;//Get final width and heightint finalX = xAvailable;if ((realContentSize.x > 0) && (realContentSize.x < finalX))finalX = realContentSize.x;int finalY = yAvailable;if ((realContentSize.y > 0) && (realContentSize.y < finalY))finalY = realContentSize.y;//Get final origin X and Yint originX = (originRect.centerX()-popoverLayoutRect.left) - (finalX/2) ;if (originX < 0)originX = 0;else if (originX+finalX > popoverLayoutRect.width())originX = popoverLayoutRect.width() - finalX;int originY = (originRect.bottom - popoverLayoutRect.top);//Create rectRect finalRect = new Rect(originX, originY, originX+finalX, originY+finalY);//And returnreturn finalRect;}/** * Calculates the rect for showing the view with Arrow Down * @param originRect The origin rect * @return The calculated rect to show the view */private Rect getRectForArrowDown(Rect originRect){//Get available spaceint xAvailable = popoverLayoutRect.width();if (xAvailable < 0)xAvailable = 0;int yAvailable = (originRect.top - popoverLayoutRect.top);if (yAvailable < 0)yAvailable = 0;//Get final width and heightint finalX = xAvailable;if ((realContentSize.x > 0) && (realContentSize.x < finalX))finalX = realContentSize.x;int finalY = yAvailable;if ((realContentSize.y > 0) && (realContentSize.y < finalY))finalY = realContentSize.y;//Get final origin X and Yint originX = (originRect.centerX()-popoverLayoutRect.left) - (finalX/2) ;if (originX < 0)originX = 0;else if (originX+finalX > popoverLayoutRect.width())originX = popoverLayoutRect.width() - finalX;int originY = (originRect.top - popoverLayoutRect.top) - finalY;//Create rectRect finalRect = new Rect(originX, originY, originX+finalX, originY+finalY);//And returnreturn finalRect;}/** * Calculates the rect for showing the view with Arrow Right * @param originRect The origin rect * @return The calculated rect to show the view */private Rect getRectForArrowRight(Rect originRect){//Get available spaceint xAvailable = (originRect.left - popoverLayoutRect.left);if (xAvailable < 0)xAvailable = 0;int yAvailable = popoverLayoutRect.height();if (yAvailable < 0)yAvailable = 0;//Get final width and heightint finalX = xAvailable;if ((realContentSize.x > 0) && (realContentSize.x < finalX))finalX = realContentSize.x;int finalY = yAvailable;if ((realContentSize.y > 0) && (realContentSize.y < finalY))finalY = realContentSize.y;//Get final origin X and Yint originX = (originRect.left - popoverLayoutRect.left) - finalX;int originY = (originRect.centerY()-popoverLayoutRect.top) - (finalY/2) ;if (originY < 0)originY = 0;else if (originY+finalY > popoverLayoutRect.height())originY = popoverLayoutRect.height() - finalY;//Create rectRect finalRect = new Rect(originX, originY, originX+finalX, originY+finalY);//And returnreturn finalRect;}/** * Calculates the rect for showing the view with Arrow Left * @param originRect The origin rect * @return The calculated rect to show the view */private Rect getRectForArrowLeft(Rect originRect){//Get available spaceint xAvailable = popoverLayoutRect.width() - (originRect.right - popoverLayoutRect.left);if (xAvailable < 0)xAvailable = 0;int yAvailable = popoverLayoutRect.height();if (yAvailable < 0)yAvailable = 0;//Get final width and heightint finalX = xAvailable;if ((realContentSize.x > 0) && (realContentSize.x < finalX))finalX = realContentSize.x;int finalY = yAvailable;if ((realContentSize.y > 0) && (realContentSize.y < finalY))finalY = realContentSize.y;//Get final origin X and Yint originX = (originRect.right - popoverLayoutRect.left);int originY = (originRect.centerY()-popoverLayoutRect.top) - (finalY/2) ;if (originY < 0)originY = 0;else if (originY+finalY > popoverLayoutRect.height())originY = popoverLayoutRect.height() - finalY;//Create rectRect finalRect = new Rect(originX, originY, originX+finalX, originY+finalY);//And returnreturn finalRect;}/** * Add available rects for each selected arrow direction * @param originRect The rect where the popover will appear from * @param arrowDirections The bit mask for the possible arrow directions */private void addAvailableRects(Rect originRect, int arrowDirections){//Get popover rects for the available directionspossibleRects = new HashMap<Integer, Rect>();if ((arrowDirections & MyPopView.PopoverArrowDirectionUp) != 0){possibleRects.put(MyPopView.PopoverArrowDirectionUp, getRectForArrowUp(originRect));}if ((arrowDirections & MyPopView.PopoverArrowDirectionDown) != 0){possibleRects.put(MyPopView.PopoverArrowDirectionDown, getRectForArrowDown(originRect));}if ((arrowDirections & MyPopView.PopoverArrowDirectionRight) != 0){possibleRects.put(MyPopView.PopoverArrowDirectionRight, getRectForArrowRight(originRect));}if ((arrowDirections & MyPopView.PopoverArrowDirectionLeft) != 0){possibleRects.put(MyPopView.PopoverArrowDirectionLeft, getRectForArrowLeft(originRect));}}/** * Get the best available rect (bigger area) * @return The Integer key to get the Rect from posibleRects (PopoverArrowDirectionUp,PopoverArrowDirectionDown,PopoverArrowDirectionRight or PopoverArrowDirectionLeft) */private Integer getBestRect(){//Get the best one (bigger area)Integer best = null;for (Integer arrowDir : possibleRects.keySet()) {if (best == null){best = arrowDir;}else{Rect bestRect = possibleRects.get(best);Rect checkRect = possibleRects.get(arrowDir);if ((bestRect.width()*bestRect.height()) < (checkRect.width()*checkRect.height()))best = arrowDir;}}return best;}/** * Gets the current fade animation time * @return The fade animation time, in milliseconds */public int getFadeAnimationTime() {return fadeAnimationTime;}/** * Sets the fade animation time * @param fadeAnimationTime The time in milliseconds */public void setFadeAnimationTime(int fadeAnimationTime) {this.fadeAnimationTime = fadeAnimationTime;}/** * Get the content size for view in popover * @return The point with the content size */public Point getContentSizeForViewInPopover() {return contentSizeForViewInPopover;}/** * Sets the content size for the view in a popover, if point is (0,0) the popover will full the screen * @param contentSizeForViewInPopover */public void setContentSizeForViewInPopover(Point contentSizeForViewInPopover) {this.contentSizeForViewInPopover = contentSizeForViewInPopover;//Save the real content sizerealContentSize = new Point(contentSizeForViewInPopover);realContentSize.x += popoverView.getPaddingLeft()+popoverView.getPaddingRight();realContentSize.y += popoverView.getPaddingTop()+popoverView.getPaddingBottom();}public PopoverViewListener getPopoverViewListener() {return popoverViewListener;}public void setPopoverViewListener(PopoverViewListener popoverViewListener) {this.popoverViewListener = popoverViewListener;}/** * This method shows a popover in a ViewGroup, from an origin rect (relative to the Application Window) * @param group The group we want to insert the popup. Normally a Relative Layout so it can stand on top of everything * @param originRect The rect we want the popup to appear from (relative to the Application Window!) * @param arrowDirections The mask of bits to tell in which directions we want the popover to be shown * @param animated Whether is animated, or not */public void showPopoverFromRectInViewGroup(ViewGroup group, Rect originRect, int arrowDirections, boolean animated){//First, tell delegate we will showif (popoverViewListener != null)popoverViewListener.popoverViewWillShow(this);//Save superviewsuperview = group;//First, add the view to the view group. The popover will cover the whole areaandroid.view.ViewGroup.LayoutParams insertParams =  new  android.view.ViewGroup.LayoutParams(android.view.ViewGroup.LayoutParams.FILL_PARENT, android.view.ViewGroup.LayoutParams.FILL_PARENT);group.addView(this, insertParams);//Now, save rect for the layout (is the same as the superview)popoverLayoutRect = MyPopView.getFrameForView(superview);//Add available rectsaddAvailableRects(originRect, arrowDirections);//Get best rectInteger best = getBestRect();//Add popoverRect bestRect = possibleRects.get(best);addPopoverInRect(bestRect);//箭头图标initArrow(originRect, best);//If we don't want animation, just tell the delegateif (!animated){//Tell delegate we did showif (popoverViewListener != null)popoverViewListener.popoverViewDidShow(this);}//If we want animation, animate it!else{//Continue only if we are not animatingif (!isAnimating){//Create alpha animation, with its listenerAlphaAnimation animation = new AlphaAnimation(0.0f, 1.0f);animation.setDuration(fadeAnimationTime);animation.setAnimationListener(new AnimationListener() {@Overridepublic void onAnimationStart(Animation animation) {//Nothing to do here}@Overridepublic void onAnimationRepeat(Animation animation) {//Nothing to do here}@Overridepublic void onAnimationEnd(Animation animation) {//End animationisAnimating = false;//Tell delegate we did showif (popoverViewListener != null)popoverViewListener.popoverViewDidShow(MyPopView.this);}});//Start animationisAnimating = true;startAnimation(animation);}}}/** * Dismiss the current shown popover * @param animated Whether it should be dismissed animated or not */public void dissmissPopover(boolean animated){//Tell delegate we will dismissif (popoverViewListener != null)popoverViewListener.popoverViewWillDismiss(MyPopView.this);//If we don't want animationif (!animated){//Just remove viewspopoverView.removeAllViews();removeAllViews();superview.removeView(this);//Tell delegate we did dismissif (popoverViewListener != null)popoverViewListener.popoverViewDidDismiss(MyPopView.this);}else{//Continue only if there is not an animation in progressif (!isAnimating){//Create alpha animation, with its listenerAlphaAnimation animation = new AlphaAnimation(1.0f, 0.0f);animation.setDuration(fadeAnimationTime);animation.setAnimationListener(new AnimationListener() {@Overridepublic void onAnimationStart(Animation animation) {//Nothing to do here}@Overridepublic void onAnimationRepeat(Animation animation) {//Nothing to do here}@Overridepublic void onAnimationEnd(Animation animation) {//Remove the viewpopoverView.removeAllViews();removeAllViews();MyPopView.this.superview.removeView(MyPopView.this);//End animationisAnimating = false;//Tell delegate we did dismissif (popoverViewListener != null)popoverViewListener.popoverViewDidDismiss(MyPopView.this);}});//Start animationisAnimating = true;startAnimation(animation);}}}@Overridepublic boolean onTouch(View v, MotionEvent event) {//If we touched over the background popover view (this)if ((!isAnimating) && (v  == this)){dissmissPopover(true);}return true;}public Drawable getBackgroundDrawable() {return backgroundDrawable;}public void setBackgroundDrawable(Drawable backgroundDrawable) {this.backgroundDrawable = backgroundDrawable;popoverView.setBackgroundDrawable(backgroundDrawable);}public Drawable getArrowUpDrawable() {return arrowUpDrawable;}public void setArrowUpDrawable(Drawable arrowUpDrawable) {this.arrowUpDrawable = arrowUpDrawable;}public Drawable getArrowDownDrawable() {return arrowDownDrawable;}public void setArrowDownDrawable(Drawable arrowDownDrawable) {this.arrowDownDrawable = arrowDownDrawable;}public Drawable getArrowLeftDrawable() {return arrowLeftDrawable;}public void setArrowLeftDrawable(Drawable arrowLeftDrawable) {this.arrowLeftDrawable = arrowLeftDrawable;}public Drawable getArrowRightDrawable() {return arrowRightDrawable;}public void setArrowRightDrawable(Drawable arrowRightDrawable) {this.arrowRightDrawable = arrowRightDrawable;}public View getPopoverContentView() {return popoverContentView;}/** *  * 描述:设置显示的View * @param popoverContentView * @throws  */public void setPopoverContentView(View popoverContentView) {this.popoverContentView = popoverContentView;popoverView.removeAllViews();popoverView.addView(popoverContentView,LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);}}

package lian.test.androidtest.pop;import lian.test.androidtest.R;import android.app.Activity;import android.graphics.Point;import android.os.Bundle;import android.view.LayoutInflater;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.RelativeLayout;import android.widget.Toast;public class PopoverActivity extends Activity implements OnClickListener{   RelativeLayout rootView = null;MyPopView popoverView = null;@Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.popover);           /*     AbTitleBar mAbTitleBar = this.getTitleBar();        mAbTitleBar.setTitleText(R.string.popview_name);        mAbTitleBar.setLogo(R.drawable.button_selector_back);        mAbTitleBar.setTitleBarBackground(R.drawable.top_bg);        mAbTitleBar.setTitleTextMargin(10, 0, 0, 0);        mAbTitleBar.setLogoLine(R.drawable.line);*/                rootView = (RelativeLayout)findViewById(R.id.rootLayout);        popoverView = new MyPopView(this);        popoverView.setBackgroundDrawable(this.getResources().getDrawable(R.drawable.background_popover));        popoverView.setArrowLeftDrawable(this.getResources().getDrawable(R.drawable.popover_arrow_left));        popoverView.setArrowRightDrawable(this.getResources().getDrawable(R.drawable.popover_arrow_right));        popoverView.setArrowDownDrawable(this.getResources().getDrawable(R.drawable.popover_arrow_down));        popoverView.setArrowUpDrawable(this.getResources().getDrawable(R.drawable.popover_arrow_up));                popoverView.setContentSizeForViewInPopover(new Point(300, 300));        popoverView.setPopoverViewListener(new MyPopView.PopoverViewListener() {@Overridepublic void popoverViewWillShow(MyPopView view) {}@Overridepublic void popoverViewWillDismiss(MyPopView view) {}@Overridepublic void popoverViewDidShow(MyPopView view) {Button a=(Button)view.findViewById(R.id.button);a.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubToast.makeText(PopoverActivity.this, "dlkfjdlkk", 1000).show();}});}@Overridepublic void popoverViewDidDismiss(MyPopView view) {}});                findViewById(R.id.button1).setOnClickListener(this);        findViewById(R.id.button2).setOnClickListener(this);        findViewById(R.id.button3).setOnClickListener(this);        findViewById(R.id.button4).setOnClickListener(this);        findViewById(R.id.button5).setOnClickListener(this);        findViewById(R.id.button6).setOnClickListener(this);        findViewById(R.id.button7).setOnClickListener(this);        findViewById(R.id.button8).setOnClickListener(this);        findViewById(R.id.button9).setOnClickListener(this);    }@Overridepublic void onClick(View v) {LayoutInflater mInflater=getLayoutInflater();popoverView.setPopoverContentView(mInflater.inflate(R.layout.popover_showed_view, null));popoverView.showPopoverFromRectInViewGroup(rootView, MyPopView.getFrameForView(v), MyPopView.PopoverArrowDirectionAny, true);}}


0 0
原创粉丝点击