类似网易、今日头条等不感兴趣的弹窗

时间:2022-10-08 17:16:18

在项目开发的过程中,产品提出了一个类似网易和今日头条不感兴趣的那种弹窗,感觉效果还不错,网上相关的例子又没找到,为了让小伙伴们少加点班特意封装了一下供给大家使用。那个小尖角用的是贝塞尔曲线,如有更好的实现方法,请留言

===========================================================================================

版权所有,如需转载请标明出处: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;


    private Paint 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.class
import 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 弹出windowview  * @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();
    }
});