類似網易、今日頭條等不感興趣的彈窗
阿新 • • 發佈:2019-02-15
在專案開發的過程中,產品提出了一個類似網易和今日頭條不感興趣的那種彈窗,感覺效果還不錯,網上相關的例子又沒找到,為了讓小夥伴們少加點班特意封裝了一下供給大家使用。那個小尖角用的是貝塞爾曲線,如有更好的實現方法,請留言
===========================================================================================
版權所有,如需轉載請標明出處:http://blog.csdn.net/you4580
=============================================================
FitPopupWindowLayout.class
import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.RectF; import android.util.AttributeSet; import android.widget.RelativeLayout; /** * Created by you4580 on 2018/4/21. * <p>主要處理佈局邏輯* 氣泡 */ public class FitPopupWindowLayout extends RelativeLayout { public static final int UP = 1; public static final int RIGHT = 2; public static final int LEFT = 3; public static final int DOWN = 4; private int mHorizontal = LEFT; private int mVertical = DOWN; privatePaint mPaint; public static final int SHARP_WIDTH = 50; public static final int SHARP_HEIGHT = (int) (SHARP_WIDTH * 1.0f); private static final int RECT_CORNER = 10; private int mXoffset = 20; private Path mPath = new Path(); private Path mSharpPath = new Path(); public FitPopupWindowLayout(Context context) { this(context, null); } public FitPopupWindowLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } public FitPopupWindowLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setBackgroundColor(Color.TRANSPARENT); mPaint = new Paint(); mPaint.setColor(Color.WHITE); mPaint.setStyle(Paint.Style.FILL); mPaint.setAntiAlias(true); } private Path makeSharpPath() { mSharpPath.moveTo(mXoffset, getMeasuredHeight() - SHARP_HEIGHT); mSharpPath.cubicTo(mXoffset, getMeasuredHeight(), mXoffset, getMeasuredHeight() - SHARP_HEIGHT, SHARP_WIDTH + mXoffset, getMeasuredHeight() - SHARP_HEIGHT); return mSharpPath; } @Override protected void onDraw(Canvas canvas) { mPath.addRoundRect(new RectF(0, 0, getMeasuredWidth(), getMeasuredHeight() - SHARP_HEIGHT) , RECT_CORNER, RECT_CORNER, Path.Direction.CW); mPath.addPath(makeSharpPath()); canvas.drawPath(mPath, mPaint); if (mHorizontal == LEFT && mVertical == UP) { setScaleX(1); setScaleY(1); } else if (mHorizontal == LEFT && mVertical == DOWN) { setScaleX(1); setScaleY(-1); scaleChild(1, -1); } else if (mHorizontal == RIGHT && mVertical == UP) { setScaleX(-1); setScaleY(1); scaleChild(-1, 1); } else if (mHorizontal == RIGHT && mVertical == DOWN) { setScaleX(-1); setScaleY(-1); scaleChild(-1, -1); } } private void scaleChild(float scaleX, float scaleY) { for (int i = 0; i < getChildCount(); i++) { getChildAt(i).setScaleX(scaleX); getChildAt(i).setScaleY(scaleY); } } public void setOrientation(int horizontal, int vertical, int xOffset) { mHorizontal = horizontal; mVertical = vertical; mXoffset = xOffset; invalidate(); } }
=====================================================
FitPopupWindow.classimport android.app.Activity;import android.graphics.drawable.ColorDrawable;import android.support.v4.view.animation.FastOutSlowInInterpolator;import android.view.Gravity;import android.view.View;import android.view.ViewGroup;import android.view.Window;import android.view.WindowManager;import android.view.animation.AlphaAnimation;import android.view.animation.Animation;import android.view.animation.AnimationSet;import android.view.animation.ScaleAnimation;import android.widget.PopupWindow;import android.widget.RelativeLayout;import com.zol.android.R;import com.zol.android.util.image.Constants;/** * Created by you4580 on 2018/4/21.
*主要處理popWindow彈出位置的邏輯 */ public class FitPopupWindow extends PopupWindow implements PopupWindow.OnDismissListener { private View anchorView; private Activity context; private int mWindowWidth; private static final int PADDING = 0; //x軸座標 private int mXCoordinate; private int mHorizontal; private int mVertical; private int[] windowPos; private FitPopupWindowLayout mFitPopupWindowLayout; public FitPopupWindow(Activity context) { init(context, ViewGroup.LayoutParams.WRAP_CONTENT , ViewGroup.LayoutParams.WRAP_CONTENT); } public FitPopupWindow(Activity context, int width, int height) { mWindowWidth = width; init(context, width, height); } private void init(Activity context, int width, int height) { this.context = context; //popupwindow會預設忽略最外層的大小,所以應該再巢狀一層 setWidth(width); setHeight(height); setBackgroundDrawable(new ColorDrawable(0x00000000)); setOutsideTouchable(true); setFocusable(true); setOnDismissListener(this); setAnimationStyle(R.style.popp_anim); } public void setView(View contentView, View anchorView) { this.anchorView = anchorView; windowPos = calculatePopWindowPos(anchorView, contentView); mFitPopupWindowLayout = new FitPopupWindowLayout(context); RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, getHeight() - FitPopupWindowLayout.SHARP_HEIGHT); layoutParams.bottomMargin = FitPopupWindowLayout.SHARP_HEIGHT; contentView.setLayoutParams(layoutParams); mFitPopupWindowLayout.setOrientation(getHorizontal(), getVertical() , getXCoordinate()); mFitPopupWindowLayout.addView(contentView); setContentView(mFitPopupWindowLayout); } public void show() { showAtLocation(anchorView, Gravity.TOP | Gravity.END , windowPos[0], windowPos[1]); update(); Window window = context.getWindow(); WindowManager.LayoutParams lp = window.getAttributes(); lp.alpha = 0.7f; window.setAttributes(lp); } /** * @param anchorView 彈出window的view * @param contentView window的內容佈局 * @return window顯示的左上角的xOff, yOff座標 */ protected int[] calculatePopWindowPos(final View anchorView, final View contentView) { final int windowPos[] = new int[2]; final int anchorLoc[] = new int[2]; // 獲取錨點View在螢幕上的左上角座標位置 anchorView.getLocationOnScreen(anchorLoc); final int anchorHeight = anchorView.getHeight(); final int anchorWidth = anchorView.getWidth(); mXCoordinate = anchorLoc[0]; // 獲取螢幕的高寬 final int screenHeight = Constants.screenHeight; final int screenWidth = Constants.screenWidth; contentView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); // 計算contentView的高寬 int windowHeight = contentView.getMeasuredHeight(); mWindowWidth = mWindowWidth > 0 ? mWindowWidth : contentView.getMeasuredWidth(); // 判斷需要向上彈出還是向下彈出,如果要改變彈出策略,改變此處即可 // 目前是根據螢幕的一半進行判斷 final boolean isNeedShowUp = (screenHeight - anchorLoc[1] - anchorHeight < screenHeight / 2); // 判斷需要向左彈出還是向右彈出 final boolean isNeedShowLeft = (anchorLoc[0] < mWindowWidth / 2); setHorizontal(isNeedShowLeft ? FitPopupWindowLayout.LEFT : FitPopupWindowLayout.RIGHT); setVertical(isNeedShowUp ? FitPopupWindowLayout.UP : FitPopupWindowLayout.DOWN); // windowPos[0] = isNeedShowLeft ? // anchorLoc[0] - windowWidth : anchorLoc[0] + anchorWidth; windowPos[0] = (screenWidth - mWindowWidth) / 2; windowPos[1] = isNeedShowUp ? anchorLoc[1] - windowHeight - PADDING - FitPopupWindowLayout.SHARP_HEIGHT : anchorLoc[1] + anchorHeight + PADDING; return windowPos; } @Override public void dismiss() { super.dismiss(); } @Override public void onDismiss() { WindowManager.LayoutParams lp = context.getWindow().getAttributes(); lp.alpha = 1f; context.getWindow().setAttributes(lp); } public int getXCoordinate() { if (mXCoordinate > mWindowWidth / 2) { mXCoordinate = mWindowWidth - mXCoordinate - anchorView.getWidth() + 80; } return mXCoordinate; } private int getHorizontal() { return mHorizontal; } /** * @param mHorizontal 設定水平方向 */ private void setHorizontal(int mHorizontal) { this.mHorizontal = mHorizontal; } private int getVertical() { return mVertical; } /** * @param mVertical 設定豎直方向 */ private void setVertical(int mVertical) { this.mVertical = mVertical; } private void startAnimation(boolean isStart) { AnimationSet animationSet = new AnimationSet(true); ScaleAnimation sa; sa = new ScaleAnimation(0, 1f, 0, 1f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); sa.setDuration(150); sa.setInterpolator(new FastOutSlowInInterpolator()); sa.setFillAfter(true); AlphaAnimation aa = new AlphaAnimation(0f, 1f); aa.setDuration(150); aa.setFillAfter(true); animationSet.addAnimation(sa); animationSet.addAnimation(aa); mFitPopupWindowLayout.startAnimation(animationSet); } }
===============================================================
package com.zol.android.renew.news.ui.view.fitpopupwindow; import android.app.Activity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; import android.widget.TextView; import com.umeng.analytics.MobclickAgent; import com.zol.android.R; import com.zol.android.util.DensityUtil; import com.zol.android.util.StringUtils; import com.zol.android.util.image.Constants; /** * Created by you4580 on 2018/4/21.使用者操作的一些邏輯處理 */ public class FitPopupUtil implements View.OnClickListener { private View contentView; private Activity context; private LinearLayout reason_layout_1; private TextView reason1; private TextView reason2; private LinearLayout reason_layout_2; private TextView reason3; private TextView reason4; private TextView btnCommit; private boolean reason1Selected; private boolean reason2Selected; private boolean reason3Selected; private boolean reason4Selected; private FitPopupWindow mPopupWindow; private OnCommitClickListener listener; public FitPopupUtil(Activity context,String reasons) { this.context = context; LayoutInflater inflater = LayoutInflater.from(context); contentView = inflater.inflate(R.layout.layout_no_interest_popupwindow, null); reason1 = (TextView) contentView.findViewById(R.id.tv_reason1); reason2 = (TextView) contentView.findViewById(R.id.tv_reason2); reason3 = (TextView) contentView.findViewById(R.id.tv_reason3); reason4 = (TextView) contentView.findViewById(R.id.tv_reason4); reason_layout_2 = (LinearLayout) contentView.findViewById(R.id.reason_layout_2); btnCommit = (TextView) contentView.findViewById(R.id.btn_commit); reason1.setOnClickListener(this); reason2.setOnClickListener(this); reason3.setOnClickListener(this); reason4.setOnClickListener(this); setReasons(reasons); } public void setOnClickListener(OnCommitClickListener listener) { this.listener = listener; } /** * 彈出自適應位置的popupwindow * * @param anchorView 目標view */ public View showPopup(View anchorView) { if (mPopupWindow == null) { DensityUtil densityUtil = new DensityUtil(context); mPopupWindow = new FitPopupWindow(context, Constants.screenWidth - densityUtil.dip2px(20), ViewGroup.LayoutParams.WRAP_CONTENT ); } mPopupWindow.setView(contentView, anchorView); mPopupWindow.show(); return contentView; } @Override public void onClick(View v) { switch (v.getId()) { case R.id.tv_reason1: if(!reason1Selected){ MobclickAgent.onEvent(context,"zixun_toutiao_hate_detail", "zixun_toutiao_hate_detail_content"); } reason1Selected = !reason1Selected; reason1.setSelected(reason1Selected); break; case R.id.tv_reason2: if(!reason2Selected){ MobclickAgent.onEvent(context,"zixun_toutiao_hate_detail", "zixun_toutiao_hate_detail_ad"); } reason2Selected = !reason2Selected; reason2.setSelected(reason2Selected); break; case R.id.tv_reason3: if(!reason3Selected){ MobclickAgent.onEvent(context,"zixun_toutiao_hate_detail", "zixun_toutiao_hate_detail_source"); } reason3Selected = !reason3Selected; reason3.setSelected(reason3Selected); break; case R.id.tv_reason4: if(!reason4Selected){ MobclickAgent.onEvent(context,"zixun_toutiao_hate_detail", "zixun_toutiao_hate_detail_tag"); } reason4Selected = !reason4Selected; reason4.setSelected(reason4Selected); break; case R.id.btn_commit: if (listener != null) { listener.onClick(getReason()); } mPopupWindow.dismiss(); break; } if (reason1Selected || reason2Selected || reason3Selected || reason4Selected) { btnCommit.setOnClickListener(this); btnCommit.setText("確定"); } else { btnCommit.setOnClickListener(null); btnCommit.setText("不感興趣"); } } public void setReasons(String reasons){ if(StringUtils.isNotEmpty(reasons)){ String[] split = reasons.split("_"); if(split.length>0){ if(split.length == 1){ String rea1 = split[0]; if(StringUtils.isNotEmpty(rea1)){ reason1.setText(rea1); reason1.setVisibility(View.VISIBLE); reason2.setVisibility(View.INVISIBLE); reason3.setVisibility(View.GONE); reason4.setVisibility(View.GONE); reason_layout_2.setVisibility(View.GONE); } }else if(split.length == 2){ String rea1 = split[0]; if(StringUtils.isNotEmpty(rea1)){ reason1.setText(rea1); reason1.setVisibility(View.VISIBLE); } String rea2 = split[1]; if(StringUtils.isNotEmpty(rea2)){ reason2.setText(rea2); reason2.setVisibility(View.VISIBLE); } reason3.setVisibility(View.GONE); reason4.setVisibility(View.GONE); reason_layout_2.setVisibility(View.GONE); }else if(split.length == 3){ String rea1 = split[0]; if(StringUtils.isNotEmpty(rea1)){ reason1.setText(rea1); reason1.setVisibility(View.VISIBLE); } String rea2 = split[1]; if(StringUtils.isNotEmpty(rea2)){ reason2.setText(rea2); reason2.setVisibility(View.VISIBLE); } String rea3 = split[2]; if(StringUtils.isNotEmpty(rea3)){ reason3.setText(rea3); reason3.setVisibility(View.VISIBLE); } reason4.setVisibility(View.INVISIBLE); reason_layout_2.setVisibility(View.VISIBLE); }else if(split.length >= 3){ String rea1 = split[0]; if(StringUtils.isNotEmpty(rea1)){ reason1.setText(rea1); reason1.setVisibility(View.VISIBLE); } String rea2 = split[1]; if(StringUtils.isNotEmpty(rea2)){ reason2.setText(rea2); reason2.setVisibility(View.VISIBLE); } String rea3 = split[2]; if(StringUtils.isNotEmpty(rea3)){ reason3.setText(rea3); reason3.setVisibility(View.VISIBLE); } String rea4 = split[3]; if(StringUtils.isNotEmpty(rea4)){ reason4.setText(rea4); reason4.setVisibility(View.VISIBLE); } reason_layout_2.setVisibility(View.VISIBLE); } } }else{ reason1.setText("重複、舊聞"); reason1.setVisibility(View.VISIBLE); reason2.setText("廣告"); reason2.setVisibility(View.VISIBLE); reason3.setVisibility(View.GONE); reason4.setVisibility(View.GONE); reason_layout_2.setVisibility(View.GONE); } } public String getReason() { String content1 = reason1Selected ? reason1.getText().toString() + "_" : ""; String content2 = reason2Selected ? reason2.getText().toString() + "_" : ""; String content3 = reason3Selected ? reason3.getText().toString() + "_" : ""; String content4 = reason4Selected ? reason4.getText().toString() + "_" : ""; String s = content1 + content2 + content3 + content4; return s.substring(0, s.length() - 1); } public interface OnCommitClickListener { void onClick(String reason); } }
================================================
程式碼中如何呼叫:
FitPopupUtil fitPopupUtil = new FitPopupUtil((Activity) mContext,reasons); fitPopupUtil.showPopup(anchorView); fitPopupUtil.setOnClickListener(new FitPopupUtil.OnCommitClickListener() { @Override public void onClick(String reason) { deleteNoInterestDate(position,reason); Toast.makeText(mContext,reason,Toast.LENGTH_SHORT).show(); } });