指示项,轮播图,圆角图片可拉伸,popwindow

public class ViewFlow extends AdapterView<Adapter> {


private static final int SNAP_VELOCITY = 200;
private static final int INVALID_SCREEN = -1;
private final static int TOUCH_STATE_REST = 0;
private final static int TOUCH_STATE_SCROLLING = 1;


private LinkedList<View> mLoadedViews;
private int mCurrentBufferIndex;
private int mCurrentAdapterIndex;
private int mSideBuffer = 2;
private Scroller mScroller;
private VelocityTracker mVelocityTracker;
private int mTouchState = TOUCH_STATE_REST;
private float mLastMotionX;
private int mTouchSlop;
private int mMaximumVelocity;
private int mCurrentScreen;
private int mNextScreen = INVALID_SCREEN;
private boolean mFirstLayout = true;
private ViewSwitchListener mViewSwitchListener;
private Adapter mAdapter;
private int mLastScrollDirection;
private AdapterDataSetObserver mDataSetObserver;
private FlowIndicator mIndicator;
private int mLastOrientation = -1;
private long timeSpan = 3000;
private Handler handler;
private OnGlobalLayoutListener orientationChangeListener = new OnGlobalLayoutListener() {


@Override
public void onGlobalLayout() {
getViewTreeObserver().removeGlobalOnLayoutListener(orientationChangeListener);
setSelection(mCurrentAdapterIndex);
}
};


/**
* 当一个新的接收调用支持{ @link视图
*/
public static interface ViewSwitchListener {


/**


* @param view
*            the {@link View} currently in focus.
* @param position
*            The position in the adapter of the {@link View} currently
*            in focus.
*/
void onSwitched(View view, int position);


}


public ViewFlow(Context context) {
super(context);
mSideBuffer = 3;
init();
}


public ViewFlow(Context context, int sideBuffer) {
super(context);
mSideBuffer = sideBuffer;


init();
}


public ViewFlow(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray styledAttrs = context.obtainStyledAttributes(attrs, R.styleable.ViewFlow);
mSideBuffer = styledAttrs.getInt(R.styleable.ViewFlow_sidebuffer, 3);
init();
}


private void init() {
mLoadedViews = new LinkedList<View>();
mScroller = new Scroller(getContext());
final ViewConfiguration configuration = ViewConfiguration.get(getContext());
mTouchSlop = configuration.getScaledTouchSlop();
mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
}


public void startAutoFlowTimer() {
handler = new Handler() {
@Override
public void handleMessage(Message msg) {


snapToScreen((mCurrentScreen + 1) % getChildCount());
Message message = handler.obtainMessage(0);
sendMessageDelayed(message, timeSpan);
}
};


Message message = handler.obtainMessage(0);
handler.sendMessageDelayed(message, timeSpan);
}


public void stopAutoFlowTimer() {
if (handler != null)
handler.removeMessages(0);
handler = null;
}


public void onConfigurationChanged(Configuration newConfig) {
if (newConfig.orientation != mLastOrientation) {
mLastOrientation = newConfig.orientation;
getViewTreeObserver().addOnGlobalLayoutListener(orientationChangeListener);
}
}


public int getViewsCount() {
return mSideBuffer;
}


@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);


final int width = MeasureSpec.getSize(widthMeasureSpec);
final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
if (widthMode != MeasureSpec.EXACTLY && !isInEditMode()) {
throw new IllegalStateException("ViewFlow can only be used in EXACTLY mode.");
}


final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if (heightMode != MeasureSpec.EXACTLY && !isInEditMode()) {
throw new IllegalStateException("ViewFlow can only be used in EXACTLY mode.");
}


// The children are given the same width and height as the workspace
final int count = getChildCount();
for (int i = 0; i < count; i++) {
getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);
}


if (mFirstLayout) {
mScroller.startScroll(0, 0, mCurrentScreen * width, 0, 0);
mFirstLayout = false;
}
}


@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int childLeft = 0;


final int count = getChildCount();
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() != View.GONE) {
final int childWidth = child.getMeasuredWidth();
child.layout(childLeft, 0, childLeft + childWidth, child.getMeasuredHeight());
childLeft += childWidth;
}
}
}


@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (getChildCount() == 0)
return false;


if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(ev);


final int action = ev.getAction();
final float x = ev.getX();


switch (action) {
case MotionEvent.ACTION_DOWN:
/*
* If being flinged and user touches, stop the fling. isFinished
* will be false if being flinged.
*/
if (!mScroller.isFinished()) {
mScroller.abortAnimation();
}


// Remember where the motion event started
mLastMotionX = x;


mTouchState = mScroller.isFinished() ? TOUCH_STATE_REST : TOUCH_STATE_SCROLLING;
if (handler != null)
handler.removeMessages(0);
break;


case MotionEvent.ACTION_MOVE:
final int xDiff = (int) Math.abs(x - mLastMotionX);


boolean xMoved = xDiff > mTouchSlop;


if (xMoved) {
// Scroll if the user moved far enough along the X axis
mTouchState = TOUCH_STATE_SCROLLING;
}


if (mTouchState == TOUCH_STATE_SCROLLING) {
// Scroll to follow the motion event
final int deltaX = (int) (mLastMotionX - x);
mLastMotionX = x;


final int scrollX = getScrollX();
if (deltaX < 0) {
if (scrollX > 0) {
scrollBy(Math.max(-scrollX, deltaX), 0);
}
} else if (deltaX > 0) {
final int availableToScroll = getChildAt(getChildCount() - 1).getRight() - scrollX - getWidth();
if (availableToScroll > 0) {
scrollBy(Math.min(availableToScroll, deltaX), 0);
}
}
return true;
}
break;


case MotionEvent.ACTION_UP:
if (mTouchState == TOUCH_STATE_SCROLLING) {
final VelocityTracker velocityTracker = mVelocityTracker;
velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
int velocityX = (int) velocityTracker.getXVelocity();


if (velocityX > SNAP_VELOCITY && mCurrentScreen > 0) {
// Fling hard enough to move left
snapToScreen(mCurrentScreen - 1);
} else if (velocityX < -SNAP_VELOCITY && mCurrentScreen < getChildCount() - 1) {
// Fling hard enough to move right
snapToScreen(mCurrentScreen + 1);
} else {
snapToDestination();
}


if (mVelocityTracker != null) {
mVelocityTracker.recycle();
mVelocityTracker = null;
}
}


mTouchState = TOUCH_STATE_REST;
if (handler != null) {
Message message = handler.obtainMessage(0);
handler.sendMessageDelayed(message, timeSpan);
}
break;
case MotionEvent.ACTION_CANCEL:
mTouchState = TOUCH_STATE_REST;
}
return false;
}


@Override
public boolean onTouchEvent(MotionEvent ev) {
if (getChildCount() == 0)
return false;


if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(ev);


final int action = ev.getAction();
final float x = ev.getX();


switch (action) {
case MotionEvent.ACTION_DOWN:
/*
* If being flinged and user touches, stop the fling. isFinished
* will be false if being flinged.
*/
if (!mScroller.isFinished()) {
mScroller.abortAnimation();
}


// Remember where the motion event started
mLastMotionX = x;


mTouchState = mScroller.isFinished() ? TOUCH_STATE_REST : TOUCH_STATE_SCROLLING;
if (handler != null)
handler.removeMessages(0);
break;


case MotionEvent.ACTION_MOVE:
final int xDiff = (int) Math.abs(x - mLastMotionX);


boolean xMoved = xDiff > mTouchSlop;


if (xMoved) {
// Scroll if the user moved far enough along the X axis
mTouchState = TOUCH_STATE_SCROLLING;
}


if (mTouchState == TOUCH_STATE_SCROLLING) {
// Scroll to follow the motion event
final int deltaX = (int) (mLastMotionX - x);
mLastMotionX = x;


final int scrollX = getScrollX();
if (deltaX < 0) {
if (scrollX > 0) {
scrollBy(Math.max(-scrollX, deltaX), 0);
}
} else if (deltaX > 0) {
final int availableToScroll = getChildAt(getChildCount() - 1).getRight() - scrollX - getWidth();
if (availableToScroll > 0) {
scrollBy(Math.min(availableToScroll, deltaX), 0);
}
}
return true;
}
break;


case MotionEvent.ACTION_UP:
if (mTouchState == TOUCH_STATE_SCROLLING) {
final VelocityTracker velocityTracker = mVelocityTracker;
velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
int velocityX = (int) velocityTracker.getXVelocity();


if (velocityX > SNAP_VELOCITY && mCurrentScreen > 0) {
// Fling hard enough to move left
snapToScreen(mCurrentScreen - 1);
} else if (velocityX < -SNAP_VELOCITY && mCurrentScreen < getChildCount() - 1) {
// Fling hard enough to move right
snapToScreen(mCurrentScreen + 1);
}
// else if (velocityX < -SNAP_VELOCITY
// && mCurrentScreen == getChildCount() - 1) {
// snapToScreen(0);
// }
// else if (velocityX > SNAP_VELOCITY
// && mCurrentScreen == 0) {
// snapToScreen(getChildCount() - 1);
// }
else {
snapToDestination();
}


if (mVelocityTracker != null) {
mVelocityTracker.recycle();
mVelocityTracker = null;
}
}


mTouchState = TOUCH_STATE_REST;


if (handler != null) {
Message message = handler.obtainMessage(0);
handler.sendMessageDelayed(message, timeSpan);
}
break;
case MotionEvent.ACTION_CANCEL:
snapToDestination();
mTouchState = TOUCH_STATE_REST;
}
return true;
}


@Override
protected void onScrollChanged(int h, int v, int oldh, int oldv) {
super.onScrollChanged(h, v, oldh, oldv);
if (mIndicator != null) {
/*
* The actual horizontal scroll origin does typically not match the
* perceived one. Therefore, we need to calculate the perceived
* horizontal scroll origin here, since we use a view buffer.
*/
int hPerceived = h + (mCurrentAdapterIndex - mCurrentBufferIndex) * getWidth();
mIndicator.onScrolled(hPerceived, v, oldh, oldv);
}
}


private void snapToDestination() {
final int screenWidth = getWidth();
final int whichScreen = (getScrollX() + (screenWidth / 2)) / screenWidth;


snapToScreen(whichScreen);
}


private void snapToScreen(int whichScreen) {
mLastScrollDirection = whichScreen - mCurrentScreen;
if (!mScroller.isFinished())
return;


whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1));


mNextScreen = whichScreen;


final int newX = whichScreen * getWidth();
final int delta = newX - getScrollX();
mScroller.startScroll(getScrollX(), 0, delta, 0, Math.abs(delta) * 2);
invalidate();
}


@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
postInvalidate();
} else if (mNextScreen != INVALID_SCREEN) {
mCurrentScreen = Math.max(0, Math.min(mNextScreen, getChildCount() - 1));
mNextScreen = INVALID_SCREEN;
postViewSwitched(mLastScrollDirection);
}
}


/**
* Scroll to the {@link View} in the view buffer specified by the index.

* @param indexInBuffer
*            Index of the view in the view buffer.
*/
private void setVisibleView(int indexInBuffer, boolean uiThread) {
mCurrentScreen = Math.max(0, Math.min(indexInBuffer, getChildCount() - 1));
int dx = (mCurrentScreen * getWidth()) - mScroller.getCurrX();
mScroller.startScroll(mScroller.getCurrX(), mScroller.getCurrY(), dx, 0, 0);
if (dx == 0)
onScrollChanged(mScroller.getCurrX() + dx, mScroller.getCurrY(), mScroller.getCurrX() + dx, mScroller.getCurrY());
if (uiThread)
invalidate();
else
postInvalidate();
}


/**
* Set the listener that will receive notifications every time the {code
* ViewFlow} scrolls.

* @param l
*            the scroll listener
*/
public void setOnViewSwitchListener(ViewSwitchListener l) {
mViewSwitchListener = l;
}


@Override
public Adapter getAdapter() {
return mAdapter;
}


@Override
public void setAdapter(Adapter adapter) {
setAdapter(adapter, 0);
}


public void setAdapter(Adapter adapter, int initialPosition) {
if (mAdapter != null) {
mAdapter.unregisterDataSetObserver(mDataSetObserver);
}


mAdapter = adapter;


if (mAdapter != null) {
mDataSetObserver = new AdapterDataSetObserver();
mAdapter.registerDataSetObserver(mDataSetObserver);


}
if (mAdapter == null || mAdapter.getCount() == 0)
return;


setSelection(initialPosition);
}


@Override
public View getSelectedView() {
return (mCurrentBufferIndex < mLoadedViews.size() ? mLoadedViews.get(mCurrentBufferIndex) : null);
}


@Override
public int getSelectedItemPosition() {
return mCurrentAdapterIndex;
}


/**
* Set the FlowIndicator

* @param flowIndicator
*/
public void setFlowIndicator(FlowIndicator flowIndicator) {
mIndicator = flowIndicator;
mIndicator.setViewFlow(this);
}


@Override
public void setSelection(int position) {
mNextScreen = INVALID_SCREEN;
mScroller.forceFinished(true);
if (mAdapter == null)
return;


position = Math.max(position, 0);
position = Math.min(position, mAdapter.getCount() - 1);


ArrayList<View> recycleViews = new ArrayList<View>();
View recycleView;
while (!mLoadedViews.isEmpty()) {
recycleViews.add(recycleView = mLoadedViews.remove());
detachViewFromParent(recycleView);
}


View currentView = makeAndAddView(position, true, (recycleViews.isEmpty() ? null : recycleViews.remove(0)));
mLoadedViews.addLast(currentView);


for (int offset = 1; mSideBuffer - offset >= 0; offset++) {
int leftIndex = position - offset;
int rightIndex = position + offset;
if (leftIndex >= 0)
mLoadedViews.addFirst(makeAndAddView(leftIndex, false, (recycleViews.isEmpty() ? null : recycleViews.remove(0))));
if (rightIndex < mAdapter.getCount())
mLoadedViews.addLast(makeAndAddView(rightIndex, true, (recycleViews.isEmpty() ? null : recycleViews.remove(0))));
}


mCurrentBufferIndex = mLoadedViews.indexOf(currentView);
mCurrentAdapterIndex = position;


for (View view : recycleViews) {
removeDetachedView(view, false);
}
requestLayout();
setVisibleView(mCurrentBufferIndex, false);
if (mIndicator != null) {
mIndicator.onSwitched(mLoadedViews.get(mCurrentBufferIndex), mCurrentAdapterIndex);
}
if (mViewSwitchListener != null) {
mViewSwitchListener.onSwitched(mLoadedViews.get(mCurrentBufferIndex), mCurrentAdapterIndex);
}
}


private void resetFocus() {
mLoadedViews.clear();
removeAllViewsInLayout();


for (int i = Math.max(0, mCurrentAdapterIndex - mSideBuffer); i < Math.min(mAdapter.getCount(), mCurrentAdapterIndex + mSideBuffer + 1); i++) {
mLoadedViews.addLast(makeAndAddView(i, true, null));
if (i == mCurrentAdapterIndex)
mCurrentBufferIndex = mLoadedViews.size() - 1;
}
requestLayout();
}


private void postViewSwitched(int direction) {
if (direction == 0)
return;


if (direction > 0) { // to the right
mCurrentAdapterIndex++;
mCurrentBufferIndex++;


// if(direction > 1) {
// mCurrentAdapterIndex += mAdapter.getCount() - 2;
// mCurrentBufferIndex += mAdapter.getCount() - 2;
// }


View recycleView = null;


// Remove view outside buffer range
if (mCurrentAdapterIndex > mSideBuffer) {
recycleView = mLoadedViews.removeFirst();
detachViewFromParent(recycleView);
// removeView(recycleView);
mCurrentBufferIndex--;
}


// Add new view to buffer
int newBufferIndex = mCurrentAdapterIndex + mSideBuffer;
if (newBufferIndex < mAdapter.getCount())
mLoadedViews.addLast(makeAndAddView(newBufferIndex, true, recycleView));


} else { // to the left
mCurrentAdapterIndex--;
mCurrentBufferIndex--;


// if(direction < -1) {
// mCurrentAdapterIndex -= mAdapter.getCount() - 2;
// mCurrentBufferIndex -= mAdapter.getCount() - 2;
// }


View recycleView = null;


// Remove view outside buffer range
if (mAdapter.getCount() - 1 - mCurrentAdapterIndex > mSideBuffer) {
recycleView = mLoadedViews.removeLast();
detachViewFromParent(recycleView);
}


// Add new view to buffer
int newBufferIndex = mCurrentAdapterIndex - mSideBuffer;
if (newBufferIndex > -1) {
mLoadedViews.addFirst(makeAndAddView(newBufferIndex, false, recycleView));
mCurrentBufferIndex++;
}


}


requestLayout();
setVisibleView(mCurrentBufferIndex, true);
if (mIndicator != null) {
mIndicator.onSwitched(mLoadedViews.get(mCurrentBufferIndex), mCurrentAdapterIndex);
}
if (mViewSwitchListener != null) {
mViewSwitchListener.onSwitched(mLoadedViews.get(mCurrentBufferIndex), mCurrentAdapterIndex);
}
}


private View setupChild(View child, boolean addToEnd, boolean recycle) {
ViewGroup.LayoutParams p = (ViewGroup.LayoutParams) child.getLayoutParams();
if (p == null) {
p = new AbsListView.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, 0);
}
if (recycle)
attachViewToParent(child, (addToEnd ? -1 : 0), p);
else
addViewInLayout(child, (addToEnd ? -1 : 0), p, true);
return child;
}


private View makeAndAddView(int position, boolean addToEnd, View convertView) {
View view = mAdapter.getView(position, convertView, this);
return setupChild(view, addToEnd, convertView != null);
}


class AdapterDataSetObserver extends DataSetObserver {


@Override
public void onChanged() {
View v = getChildAt(mCurrentBufferIndex);
if (v != null) {
for (int index = 0; index < mAdapter.getCount(); index++) {
if (v.equals(mAdapter.getItem(index))) {
mCurrentAdapterIndex = index;
break;
}
}
}
resetFocus();
}


@Override
public void onInvalidated() {
// Not yet implemented!
}


}


public void setTimeSpan(long timeSpan) {
this.timeSpan = timeSpan;
}


public void setmSideBuffer(int mSideBuffer) {
this.mSideBuffer = mSideBuffer;
}

}







public class RoundImageView extends ImageView{


/**
* 图片的类型,圆形or圆角
*/
private int type;
private static final int TYPE_CIRCLE = 0;
private static final int TYPE_ROUND = 1;


/**
* 圆角大小的默认值
*/
//private static final int BODER_RADIUS_DEFAULT = 10;
private static final int BODER_RADIUS_DEFAULT = 10;
/**
* 圆角的大小
*/
private int mBorderRadius;


/**
* 绘图的Paint
*/
private Paint mBitmapPaint;
/**
* 圆角的半径
*/
private int mRadius;
/**
* 3x3 矩阵,主要用于缩小放大
*/
private Matrix mMatrix;
/**
* 渲染图像,使用图像为绘制图形着色
*/
private BitmapShader mBitmapShader;
/**
* view的宽度
*/
private int mWidth;
private RectF mRoundRect;


public RoundImageView(Context context, AttributeSet attrs){
super(context, attrs);
mMatrix = new Matrix();
mBitmapPaint = new Paint();
mBitmapPaint.setAntiAlias(true);


TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.RoundImageView);


mBorderRadius = a.getDimensionPixelSize(
R.styleable.RoundImageView_borderRadius, (int) TypedValue
.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
BODER_RADIUS_DEFAULT, getResources().getDisplayMetrics()));// 默认为10dp
type = a.getInt(R.styleable.RoundImageView_type, TYPE_CIRCLE);// 默认为Circle


a.recycle();
}
@Override
protected void onDraw(Canvas canvas)
{
if (getDrawable() == null)
{
return;
}
setUpShader();


if (type == TYPE_ROUND)
{
canvas.drawRoundRect(mRoundRect, mBorderRadius, mBorderRadius,
mBitmapPaint);
} else
{
canvas.drawCircle(mRadius, mRadius, mRadius, mBitmapPaint);
// drawSomeThing(canvas);
}
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
super.onSizeChanged(w, h, oldw, oldh);
// 圆角图片的范围
if (type == TYPE_ROUND)
mRoundRect = new RectF(0, 0, getWidth(), getHeight());
}


/**
* 初始化BitmapShader
*/
private void setUpShader()
{
Drawable drawable = getDrawable();
if (drawable == null)
{
return;
}


Bitmap bmp = drawableToBitamp(drawable);
// 将bmp作为着色器,就是在指定区域内绘制bmp
mBitmapShader = new BitmapShader(bmp, TileMode.CLAMP, TileMode.CLAMP);
float scale = 1.0f;
if (type == TYPE_CIRCLE)
{
// 拿到bitmap宽或高的小值
int bSize = Math.min(bmp.getWidth(), bmp.getHeight());
scale = mWidth * 1.0f / bSize;


} else if (type == TYPE_ROUND)
{
// 如果图片的宽或者高与view的宽高不匹配,计算出需要缩放的比例;缩放后的图片的宽高,一定要大于我们view的宽高;所以我们这里取大值;
scale = Math.max(getWidth() * 1.0f / bmp.getWidth(), getHeight()
* 1.0f / bmp.getHeight());
}
// shader的变换矩阵,我们这里主要用于放大或者缩小
mMatrix.setScale(scale, scale);
// 设置变换矩阵
mBitmapShader.setLocalMatrix(mMatrix);
// 设置shader
mBitmapPaint.setShader(mBitmapShader);
}

/**
* drawable转bitmap

* @param drawable
* @return
*/
private Bitmap drawableToBitamp(Drawable drawable)
{
if (drawable instanceof BitmapDrawable)
{
BitmapDrawable bd = (BitmapDrawable) drawable;
return bd.getBitmap();
}
int w = drawable.getIntrinsicWidth();
int h = drawable.getIntrinsicHeight();
Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(10, 10, 10,10);
drawable.draw(canvas);
return bitmap;
}


public void setBorderRadius(int borderRadius)
{
int pxVal = dp2px(borderRadius);
if (this.mBorderRadius != pxVal)
{
this.mBorderRadius = pxVal;
invalidate();
}
}


public void setType(int type)
{
if (this.type != type)
{
this.type = type;
if (this.type != TYPE_ROUND && this.type != TYPE_CIRCLE)
{
this.type = TYPE_CIRCLE;
}
requestLayout();
}


}


public int dp2px(int dpVal)
{
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
dpVal, getResources().getDisplayMetrics());
}
}




public class PopupwindowTip {


private Context mContext;
private PopupWindow popupWindow;
private View anchor;
private TextView tvContent;


public PopupWindow getPopupWindow() {
return popupWindow;
}


public void setPopupWindow(PopupWindow popupWindow) {
this.popupWindow = popupWindow;
}


public PopupwindowTip(Context context, View view, String msg) {
this.mContext = context;
this.anchor = view;
initView(msg);
}


private void initView(String msg) {
View view = LayoutInflater.from(mContext).inflate(
R.layout.popupwindow_tip, null);
// 设置内容
tvContent = (TextView) view.findViewById(R.id.pop_tv_content);
tvContent.setText(msg);
// 创建悬浮窗
popupWindow = new PopupWindow(view, LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT, true);
popupWindow.setTouchable(true);
popupWindow.setTouchInterceptor(new OnTouchListener() {


@Override
public boolean onTouch(View v, MotionEvent event) {
return false;
}
});
// 如果不设置PopupWindow的背景,无论是点击外部区域还是Back键都无法dismiss弹框
// 我觉得这里是API的一个bug
popupWindow.setBackgroundDrawable(new ColorDrawable(-000000));
// 设置在控件的上方显示
view.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
// int popupWidth = view.getMeasuredWidth();
int popupHeight = view.getMeasuredHeight();
int[] location = new int[2];
anchor.getLocationOnScreen(location);
popupWindow.showAtLocation(anchor, Gravity.NO_GRAVITY, location[0],
location[1] - popupHeight);
}


public void popDismiss() {
if (popupWindow != null) {
popupWindow.dismiss();
}
}
}



<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/pop_biaoqian_bg"
    android:orientation="vertical" >


    <TextView
        android:id="@+id/pop_tv_content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/transparent"
        android:gravity="center"
        android:maxWidth="200dp"
        android:padding="8dp"
        android:text="提示内容"
        android:textColor="@color/pink" />


</LinearLayout>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值