Android仿微信朋友圈2自定义点赞评论弹框

        最近在做类似微信朋友圈点赞评论的功能,有个点赞评论弹框交互,感觉效果很好,点击评论按钮弹框从按钮左边弹出,遇到了3个问题(弹出动画不对、弹框布局没有适配、弹出的位置显示不对),动画和布局好解决,弹出的位置调试了半天,下面给出解决方法.

1.弹出动画

push_botton_in.xml代码:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <scale
        android:duration="180"
        android:fromXScale="0"
        android:fromYScale="1"
        android:toYScale="1"
        android:pivotX="100%"
        android:pivotY="50%"
        android:toXScale="1" />
</set>

push_bottom_out.xml代码

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <scale
        android:duration="180"
        android:fromXScale="1"
        android:pivotX="100%"
        android:fromYScale="1"
        android:toYScale="1"
        android:pivotY="50%"
        android:toXScale="0" />
</set>

style样式代码:

<style name="anim_push_bottom" parent="@android:style/Animation">
    <item name="android:windowEnterAnimation">@anim/push_bottom_in</item>
    <item name="android:windowExitAnimation">@anim/push_bottom_out</item>
</style>

Activity的代码:

完整的Activity代码:

/**
 * @作者: njb
 * @时间: 2019/7/22 10:53
 * @描述: 仿微信朋友圈文本显示全文与收起
 */
public class MainActivity extends AppCompatActivity implements CircleAdapter.MyClickListener{
    private RecyclerView recyclerView;
    private CircleAdapter circleAdapter;
    private String content = "茫茫的长白大山,浩瀚的原始森林,大山脚下,原始森林环抱中散落着几十户人家的" +
            "一个小山村,茅草房,对面炕,烟筒立在屋后边。在村东头有一个独立的房子,那就是青年点," +
            "窗前有一道小溪流过。学子在这里吃饭,由这里出发每天随社员去地里干活。干的活要么上山伐" +
            "树,抬树,要么砍柳树毛子开荒种地。在山里,可听那吆呵声:“顺山倒了!”放树谨防回头棒!" +
            "树上的枯枝打到别的树上再蹦回来,这回头棒打人最厉害。";
    private List<String> strings;
    private LikePopupWindow likePopupWindow;
    private int page = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initViews();
        initData();
        initAdapter();
        setListener();
    }

    private void setListener() {

    }

    /**
     * 初始化控件
     */
    private void initViews() {
        recyclerView = findViewById(R.id.recyclerView);
    }

    /**
     * 初始化数据
     * @param
     */
    private void initData() {
        strings = new ArrayList<>();
        for (int i = 0; i < 14; i++) {
            strings.add(content);
        }
    }

    /**
     * 设置adapter
     */
    private void initAdapter() {
        circleAdapter = new CircleAdapter(this, strings,this);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.addItemDecoration(new SpaceDecoration(this));
        recyclerView.setAdapter(circleAdapter);

    }

    @Override
    public void onClick(int position,View v) {
        if (likePopupWindow == null) {
            likePopupWindow = new LikePopupWindow(this, 0);
        }
        likePopupWindow.setOnPraiseOrCommentClickListener(new OnPraiseOrCommentClickListener() {
            @Override
            public void onPraiseClick(int position) {

                likePopupWindow.dismiss();
            }

            @Override
            public void onCommentClick(int position) {

                likePopupWindow.dismiss();
            }

            @Override
            public void onClickFrendCircleTopBg() {

            }

            @Override
            public void onDeleteItem(String id, int position) {

            }
        }).setTextView(0).setCurrentPosition(position);
        if (likePopupWindow.isShowing()) {
            likePopupWindow.dismiss();
        } else {
            likePopupWindow.showPopupWindow(v);
        }
    }
}

弹框代码:

**
 * @作者: njb
 * @时间: 2019/7/24 11:32
 * @描述: 点赞评论popup
 */
public class LikePopupWindow extends PopupWindow implements View.OnClickListener {
    private Context mContext;

    private OnPraiseOrCommentClickListener mOnPraiseOrCommentClickListener;

    private int mPopupWindowHeight;
    private int mPopupWindowWidth;
    private int mCurrentPosition;
    private TextView commentPopupText;

    public LikePopupWindow(android.content.Context context, int isLike) {
        View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_like, null);
        this.setContentView(contentView);
        contentView.findViewById(R.id.ll_like).setOnClickListener(this);
        contentView.findViewById(R.id.ll_comment).setOnClickListener(this);
        //不设置宽高将无法显示popupWindow
        this.mPopupWindowHeight = Utils.dp2px(40);
        this.mPopupWindowWidth = Utils.dp2px(200);
        this.setHeight(mPopupWindowHeight);
        this.setWidth(mPopupWindowWidth);
        // 设置SelectPicPopupWindow弹出窗体可点击
        this.setFocusable(true);
        this.setOutsideTouchable(true);
        //弹出动画
        this.setAnimationStyle(R.style.anim_push_bottom);
        // 刷新状态
        this.update();
        // 实例化一个ColorDrawable颜色为半透明
        ColorDrawable dw = new ColorDrawable(0x00000000);
        this.setBackgroundDrawable(dw);
        commentPopupText = contentView.findViewById(R.id.tv_like);
        setTextView(isLike);
    }

    public LikePopupWindow setCurrentPosition(int currentPosition) {
        mCurrentPosition = currentPosition;
        return this;
    }

    public LikePopupWindow setTextView(int isLike) {
        commentPopupText.setText(isLike == 0 ? "点赞" : "取消点赞");
        return this;
    }

    public LikePopupWindow setOnPraiseOrCommentClickListener(OnPraiseOrCommentClickListener onPraiseOrCommentClickListener) {
        mOnPraiseOrCommentClickListener = onPraiseOrCommentClickListener;
        return this;
    }

    public void showPopupWindow(View anchor) {
        if (anchor == null) {
            return;
        }
        int[] location = new int[2];
        anchor.getLocationOnScreen(location);
        int xOffset = location[0] - mPopupWindowWidth - Utils.dp2px(10f);
        int yOffset = location[1] + (anchor.getHeight() - mPopupWindowHeight) / 2;
        showAtLocation(anchor, Gravity.NO_GRAVITY, xOffset, yOffset);
    }

    @Override
    public void onClick(View v) {
        dismiss();
        int i = v.getId();
        if (i == R.id.ll_like) {
            if (mOnPraiseOrCommentClickListener != null) {
                mOnPraiseOrCommentClickListener.onPraiseClick(mCurrentPosition);
            }

        } else if (i == R.id.ll_comment) {
            if (mOnPraiseOrCommentClickListener != null) {
                mOnPraiseOrCommentClickListener.onCommentClick(mCurrentPosition);
            }
        }
    }
}

2.Adapter的代码:在上篇的基础上加入了点击事件回调

/**
 * @作者: njb
 * @时间: 2019/7/25 10:47
 * @描述: 朋友圈适配器
 */
public class CircleAdapter extends RecyclerView.Adapter<CircleAdapter.CircleViewHolder>{
    private Context context;

    private List<String> list;
    private LayoutInflater layoutInflater;
    private MyClickListener myClickListener;

    public CircleAdapter(Context context, List<String> list,MyClickListener myClickListener) {
        this.context = context;
        this.list = list;
        this.layoutInflater = LayoutInflater.from(context);
        this.myClickListener = myClickListener;
    }

    @NonNull
    @Override
    public CircleViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_circle,
                parent, false);
        CircleViewHolder circleViewHolder = new CircleViewHolder(view);
        return circleViewHolder;
    }

    @Override
    public void onBindViewHolder(@NonNull CircleViewHolder holder, final int position) {
        holder.expandTextView.setText(list.get(position));
        holder.ivComment.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(myClickListener != null){
                    myClickListener.onClick(position,view);
                }
            }
        });
    }

    @Override
    public int getItemCount() {
        return list.size();
    }


    public class CircleViewHolder extends RecyclerView.ViewHolder {
        ExpandTextView expandTextView;
        ImageView ivComment;
        ImageView ivPhoto;
        public CircleViewHolder(@NonNull View itemView) {
            super(itemView);
            expandTextView = itemView.findViewById(R.id.expand_textView);
            ivComment = itemView.findViewById(R.id.iv_edit);
            ivPhoto = itemView.findViewById(R.id.iv_photo);
        }
    }

    //点击事件接口回调
    public interface MyClickListener{
        void onClick(int position,View v);
    }
}

3.工具类代码:

4.布局代码

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

item_circle

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="10dp"
    tools:ignore="ResourceName">

    <ImageView
        android:id="@+id/iv_photo"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:scaleType="fitXY"
        android:src="@mipmap/timg" />

    <TextView
        android:id="@+id/tv_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:text="一笑的小馆子"
        android:textColor="@color/color_8290AF"
        android:textSize="14sp"
        app:layout_constraintLeft_toRightOf="@+id/iv_photo" />

    <com.example.expandtextview.view.ExpandTextView
        android:id="@+id/expand_textView"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:ellipsize="end"
        android:lineSpacingExtra="3dp"
        android:maxLines="5"
        android:textSize="16sp"
        app:layout_constraintLeft_toRightOf="@+id/iv_photo"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/tv_name" />

    <ImageView
        android:id="@+id/video_view"
        android:layout_width="120dp"
        android:layout_height="180dp"
        android:layout_marginLeft="10dp"
        android:layout_marginTop="4dp"
        android:background="@color/colorAccent"
        app:layout_constraintLeft_toRightOf="@+id/iv_photo"
        app:layout_constraintTop_toBottomOf="@+id/expand_textView" />

    <ImageView
        android:id="@+id/videoViewBf"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:src="@mipmap/bf"
        app:layout_constraintBottom_toTopOf="@+id/video_view"
        app:layout_constraintLeft_toRightOf="@+id/video_view"
        app:layout_constraintRight_toLeftOf="@+id/video_view"
        app:layout_constraintTop_toBottomOf="@+id/video_view" />

    <TextView
        android:id="@+id/tv_time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_marginTop="15dp"
        android:text="16小时前"
        android:textColor="@color/black"
        android:textSize="12sp"
        app:layout_constraintLeft_toRightOf="@+id/iv_photo"
        app:layout_constraintTop_toBottomOf="@+id/video_view" />

    <TextView
        android:id="@+id/tv_delete"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_marginTop="15dp"
        android:text="删除"
        android:textColor="@color/black"
        android:textSize="12sp"
        app:layout_constraintLeft_toRightOf="@+id/tv_time"
        app:layout_constraintTop_toBottomOf="@+id/video_view" />

    <ImageView
        android:id="@+id/iv_edit"
        android:layout_width="20dp"
        android:layout_height="20dp"
        android:layout_marginTop="15dp"
        android:src="@drawable/comments_drawable_blue"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/video_view" />

</androidx.constraintlayout.widget.ConstraintLayout>

dialog_like.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="38dp"
    android:background="@drawable/shape_remind"
    android:gravity="center"
    android:orientation="horizontal">


    <LinearLayout
        android:id="@+id/ll_like"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:background="@drawable/selector_praise_or_comment_left_bg"
        android:gravity="center"
        android:orientation="horizontal">

        <ImageView
            android:layout_width="20dp"
            android:layout_height="wrap_content"
            app:srcCompat="@drawable/heart_drawable_white" />

        <TextView
            android:id="@+id/tv_like"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="6dp"
            android:text="赞"
            android:textColor="@color/white"
            android:textSize="14sp" />
    </LinearLayout>

    <LinearLayout
        android:id="@+id/ll_comment"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:background="@drawable/selector_praise_or_comment_right_bg"
        android:gravity="center"
        android:orientation="horizontal">

        <ImageView
            android:layout_width="20dp"
            android:layout_height="wrap_content"
            app:srcCompat="@drawable/comments_drawable_white" />

        <TextView
            android:id="@+id/tv_comment"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="6dp"
            android:text="评论"
            android:textColor="@color/white" />
    </LinearLayout>


</LinearLayout>
selector_praise_or_comment_right_bg.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="false">
        <shape>
            <corners android:topRightRadius="2dp" android:bottomRightRadius="2dp" />
            <solid android:color="#222230" />
        </shape>
    </item>
    <item android:state_pressed="true">
        <shape>
            <corners android:topRightRadius="2dp" android:bottomRightRadius="2dp"  />
            <solid android:color="#000000" />
        </shape>
    </item>
</selector>
selector_praise_or_comment_left_bg.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="false">
        <shape>
            <corners android:bottomLeftRadius="2dp" android:topLeftRadius="2dp" />
            <solid android:color="#222230" />
        </shape>
    </item>
    <item android:state_pressed="true">
        <shape>
            <corners android:bottomLeftRadius="2dp" android:topLeftRadius="2dp"  />
            <solid android:color="#000000" />
        </shape>
    </item>
</selector>

shape_remind.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
    <corners android:radius="2dp" />
    <solid android:color="#222230" />
</shape>

5.动画很简单就不分析了,布局适配的代码核心:

根据屏幕大小动态适配布局,这里的宽高不是固定的,小伙伴们可以根据自己的需求进行自定义设置.

弹窗显示的位置:

两种方法:showAtLocation和showAsDropDown

1.showAtLocation,例如:showAtLocation(findViewById(R.id.search_ib), Gravity.TOP | Gravity.RIGHT,10, 10);
第一个参数:这个view是要能获取到window唯一标示的(也就是只要能获取到window 标示,view是什么控件都可以),应该是标示这个pw添加到哪个window里面,对控制pw出现位置没有影响;
第二个参数:请记住屏幕原点是屏幕的左上角。Gravity.TOP | Gravity.RIGHT指的就是屏幕的右上角,那么pw的中心点坐标是(屏幕宽,0)。pw默认是在屏幕的中间,也就是Gravity.LEFT表示pw的中心点坐标是(0,1/2屏幕高);
第三、四个参数:偏移量的方向与第二个参数有关。Gravity.TOP | Gravity.RIGHT,以屏幕右上角为原点,pw往X轴负方向偏移10个像素,往Y轴正方向偏移10个像素;如果是Gravity.BOTTOM| Gravity.LEFT,以屏幕左下角为原点,pw往X轴正方向偏移10个像素,往Y轴正方向偏移10个像素。设置Gravity.NO_GRAVITY的话,就相对屏幕左上角作为参照(即原点[0,0]是屏幕左上角),若设置Gravity.LEFT的话,则原点为 [0,1/2屏幕高],即[x=0,y=1/2屏幕高度];

注意:这个偏移量可以是正的,也可以是负的。无论偏移多大,pw是不会跑出屏幕。具体往轴的那个方向偏移,跟第二个参数有关,对于Gravity.CENTER的情况,偏移量负表示往轴的负方向,正往轴的正方向

2.showAsDropDown,例如:showAsDropDown(MainActivity.this.findViewById(R.id.logo_iv),100,0),
以R.id.logo_iv的左下角为原点,向X轴正方向偏移100个像素,Y轴方向偏移0个像素。
注意:这个偏移量可以是正的,也可以是负的。无论偏移多大,pw是不会跑出屏幕。

第一种方法的代码如下:

效果图如下:

第2种方法代码如下:

效果图如下:

从以上两个图可以明显看出,第2个位置显示不对,微信的点赞评论弹框应该是和评论按钮平行并在左侧弹出显示,以上就是大致步骤。

写得不好,还望见谅,下一篇会给出仿微信输入评论弹框及点击外部滑动时输入框键盘隐藏冲突事件.小伙伴们如果有更好地方法欢迎留言,一起学习.

项目完整地址:ExpandTextView: 实现仿微信朋友圈列表多类型布局,图片点击放大、保存,包含点赞、评论、消息提醒、视频播放等功能

csdn下载地址:ExpandTextView.zip-Android文档类资源-CSDN下载

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值