Android仿直播类app赠送礼物功能

编辑: admin 分类: 安卓教程 发布时间: 2022-03-14 来源:互联网
目录
  • 直播界面
  • 滑动隐藏效果
  • 用户交互页实现
    • 礼物进入时动画
    • 礼物移出动画
  • 开启定时清理礼物列表

    直播界面

    实现的是播放本地的视频文件:

    /**
     * 直播界面,用于对接直播功能
     */
    public class LiveFrag extends Fragment {
    
     private ImageView img_thumb;
     private VideoView video_view;
    
     @Nullable
     @Override
     public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
     View view = inflater.inflate(R.layout.frag_live, null);
     img_thumb = view.findViewById(R.id.img_thumb);
     img_thumb.setVisibility(View.GONE);
     video_view = view.findViewById(R.id.video_view);
     video_view.setVisibility(View.VISIBLE);
     video_view.setVideoURI(Uri.parse("android.resource://" + getActivity().getPackageName() + "/" + R.raw.video_1));
     video_view.start();
     video_view.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
     @Override
     public void onCompletion(MediaPlayer mp) {
     video_view.setVideoURI(Uri.parse("android.resource://" + getActivity().getPackageName() + "/" + R.raw.video_1));
     //或 //mVideoView.setVideoPath(Uri.parse(_filePath));
     video_view.start();
     }
     });
     return view;
     }
    }

    布局文件 frag_live.xml 如下:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical">
     <VideoView
     android:id="@+id/video_view"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:clickable="false"
     android:focusable="false"
     android:visibility="gone" />
     <ImageView
     android:id="@+id/img_thumb"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:clickable="false"
     android:focusable="false"
     android:scaleType="centerCrop"
     android:src="@mipmap/img_video_1"
     android:visibility="visible" />
    </LinearLayout>

    滑动隐藏效果

    需要实现的效果如下:

    自定义DialogFragment,使用ViewPager,第一个为空的Fragment,第二个为我们需要的Fragment,左右滑动来切换显示和隐藏效果。

    观众功能交互页面 InteractiveFrag 如下:

    /**
     * 观众功能交互页面, 滑动隐藏效果
     */
    public class InteractiveFrag extends DialogFragment {
    
     public View view;
     public Context myContext;
     private ViewPager vp_interactive;
     private LayerFrag layerFrag;
    
     @Override
     public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
     view = inflater.inflate(R.layout.frag_interactive, null);
     // 初始化
     initView();
     initData();
     return view;
     }
    
     /**
     * 初始化View
     */
     public void initView() {
     vp_interactive = view.findViewById(R.id.vp_interactive);
     }
    
     /**
     * 初始化数据
     */
     public void initData() {
     // EmptyFrag:什么都没有
     // LayerFrag:交互界面
     // 这样就达到了滑动隐藏交互的需求
     vp_interactive.setAdapter(new FragmentPagerAdapter(getChildFragmentManager()) {
     @Override
     public int getCount() {
     return 2;
     }
    
     @Override
     public Fragment getItem(int position) {
     if (position == 0) {
     return new EmptyFrag(); // 返回空界面的fragment
     } else if (position == 1) {
     return layerFrag = new LayerFrag(); // 返回交互界面的frag
     } else { // 设置默认
    
     return new EmptyFrag();
     }
     }
     });
     // 设置默认显示交互界面
     vp_interactive.setCurrentItem(1);
    
     // 同时将界面改为resize已达到软键盘弹出时Fragment不会跟随移动
     getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
     }
    
     @Override
     public Dialog onCreateDialog(Bundle savedInstanceState) {
    
     // 设置DialogFragment的样式,这里的代码最好还是用我的,大家不要改动
     Dialog dialog = new Dialog(getActivity(), R.style.MainDialog) {
    
     @Override
     public void onBackPressed() {
     super.onBackPressed();
     getActivity().finish();
     }
     };
     return dialog;
     }
    }

    frag_interactive.xml文件如下:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical" >
    
     <androidx.viewpager.widget.ViewPager
     android:id="@+id/vp_interactive"
     android:layout_width="match_parent"
     android:layout_height="match_parent" />
    </LinearLayout>
    

    用户交互页 LayerFrag:

    public class LayerFrag extends Fragment {
     @Nullable
     @Override
     public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
     return inflater.inflate(R.layout.frag_layer, null);
     }
    }
    
    

    frag_layer:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout 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="match_parent"
     android:orientation="vertical">
     <LinearLayout
     android:id="@+id/ll_anchor"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:gravity="center_vertical"
     android:orientation="horizontal"
     android:paddingLeft="10dp"
     android:paddingTop="10dp">
     <RelativeLayout
     android:layout_width="wrap_content"
     android:layout_height="wrap_content">
     <LinearLayout
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_centerVertical="true"
     android:background="@drawable/bg_radius_top_black"
     android:gravity="center_vertical"
     android:orientation="vertical"
     android:paddingLeft="55dp"
     android:paddingTop="2dp"
     android:paddingRight="10dp"
     android:paddingBottom="2dp">
     <TextView
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:text="十三妹哦"
     android:textColor="@android:color/white"
     android:textSize="12sp" />
     <LinearLayout
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:gravity="center_vertical"
     android:orientation="horizontal">
     <ImageView
     android:layout_width="35dp"
     android:layout_height="20dp"
     android:src="@drawable/hani_icon_tag_exp" />
     <TextView
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_marginLeft="5dp"
     android:text="17万"
     android:textColor="@android:color/white"
     android:textSize="10sp" />
     </LinearLayout>
     </LinearLayout>
     <com.hongx.zhibo.utils.CircleImageView
     android:id="@+id/lv_anchorIcon"
     android:layout_width="50dp"
     android:layout_height="50dp"
     android:src="@drawable/zf"
     app:border_color="@color/colorWhite"
     app:border_width="1dp" />
     </RelativeLayout>
     <com.hongx.zhibo.utils.HorizontalListView
     android:id="@+id/hlv_audience"
     android:layout_width="match_parent"
     android:layout_height="45dp"
     android:layout_marginLeft="10dp" />
     </LinearLayout>
     <RelativeLayout
     android:id="@+id/rl_num"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:layout_below="@+id/ll_anchor"
     android:layout_marginTop="5dp"
     android:paddingLeft="10dp"
     android:paddingRight="10dp">
     <LinearLayout
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:background="@drawable/bg_radius_bottom_pink"
     android:gravity="center_vertical"
     android:paddingLeft="10dp"
     android:paddingTop="2dp"
     android:paddingRight="10dp"
     android:paddingBottom="2dp">
     <ImageView
     android:layout_width="20dp"
     android:layout_height="10dp"
     android:src="@drawable/molive_icon_charm_lv_20" />
     <TextView
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_marginLeft="5dp"
     android:text="小时榜单第5名"
     android:textColor="#fff"
     android:textSize="10sp" />
     </LinearLayout>
     <TextView
     android:id="@+id/tv_momocode"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_alignParentRight="true"
     android:layout_centerVertical="true"
     android:background="@drawable/bg_radius_top_black"
     android:paddingLeft="10dp"
     android:paddingTop="2dp"
     android:paddingRight="10dp"
     android:paddingBottom="2dp"
     android:text="MoMo: 12345678"
     android:textColor="@android:color/white"
     android:textSize="10sp" />
     </RelativeLayout>
     <LinearLayout
     android:id="@+id/ll_gift_group"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:layout_above="@+id/lv_message"
     android:layout_marginTop="10dp"
     android:layout_marginBottom="10dp"
     android:animateLayoutChanges="true"
     android:gravity="top"
     android:orientation="vertical" />
     <ListView
     android:id="@+id/lv_message"
     android:layout_width="230dp"
     android:layout_height="150dp"
     android:layout_above="@+id/fl_bottom"
     android:layout_marginLeft="10dp"
     android:cacheColorHint="#00000000"
     android:divider="@null"
     android:dividerHeight="5dp"
     android:listSelector="#00000000"
     android:scrollbarStyle="outsideOverlay"
     android:scrollbars="none"
     android:transcriptMode="normal" />
     <FrameLayout
     android:id="@+id/fl_bottom"
     android:layout_width="match_parent"
     android:layout_height="70dp"
     android:layout_alignParentStart="true"
     android:layout_alignParentBottom="true">
     <LinearLayout
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:background="@android:color/transparent"
     android:gravity="center_vertical"
     android:orientation="horizontal"
     android:paddingLeft="10dp"
     android:paddingRight="10dp">
     <Button
     android:id="@+id/tv_chat"
     android:layout_width="40dp"
     android:layout_height="70dp"
     android:gravity="center"
     android:text="聊天"
     android:textColor="#333"
     android:textSize="10sp" />
     <View
     android:layout_width="0dp"
     android:layout_height="1dp"
     android:layout_weight="1" />
     <Button
     android:id="@+id/btn_gift01"
     android:layout_width="40dp"
     android:layout_height="70dp"
     android:layout_marginRight="5dp"
     android:gravity="center"
     android:text="送香皂"
     android:textColor="#333"
     android:textSize="12sp" />
     <Button
     android:id="@+id/btn_gift02"
     android:layout_width="40dp"
     android:layout_height="70dp"
     android:layout_marginRight="5dp"
     android:gravity="center"
     android:text="送玫瑰"
     android:textColor="#333"
     android:textSize="12sp" />
     <Button
     android:id="@+id/btn_gift03"
     android:layout_width="40dp"
     android:layout_height="70dp"
     android:layout_marginRight="5dp"
     android:gravity="center"
     android:text="送爱心"
     android:textColor="#333"
     android:textSize="12sp" />
     <Button
     android:id="@+id/btn_gift04"
     android:layout_width="40dp"
     android:layout_height="70dp"
     android:layout_marginRight="5dp"
     android:gravity="center"
     android:text="送蛋糕"
     android:textColor="#333"
     android:textSize="12sp" />
     </LinearLayout>
     <LinearLayout
     android:id="@+id/ll_inputparent"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:layout_marginTop="5dp"
     android:background="@android:color/white"
     android:paddingLeft="10dp"
     android:paddingRight="10dp"
     android:visibility="gone">
     <LinearLayout
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:gravity="center_vertical"
     android:orientation="horizontal">
     <EditText
     android:id="@+id/et_chat"
     android:layout_width="0dp"
     android:layout_height="wrap_content"
     android:layout_weight="1"
     android:background="@android:color/white"
     android:hint="在此输入你要说的话!"
     android:maxLength="30"
     android:paddingTop="10dp"
     android:paddingBottom="10dp"
     android:textColor="#888889"
     android:textColorHint="#c8c8c8"
     android:textSize="12sp" />
     <TextView
     android:id="@+id/tv_send"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_marginLeft="10dp"
     android:background="@android:color/holo_blue_bright"
     android:paddingLeft="10dp"
     android:paddingTop="5dp"
     android:paddingRight="10dp"
     android:paddingBottom="5dp"
     android:text="发送"
     android:textColor="@android:color/white"
     android:textSize="12sp" />
     </LinearLayout>
     </LinearLayout>
     </FrameLayout>
    </RelativeLayout>
    
    

    EmptyFrag:

    /**
     * 空的fragment
     */
    public class EmptyFrag extends Fragment {
     @Nullable
     @Override
     public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
     return inflater.inflate(R.layout.frag_empty, null);
     }
    }
    
    

    frag_empty.xml:

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

    在MainActivity中使用FrameLayout布局,将观众功能交互页面 InteractiveFrag 覆盖在 直播页面LiveFrag上面。

    MainActivity:

    public class MainActivity extends AppCompatActivity {
    
     @Override
     protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.activity_main);
     // 加载直播fragment
     LiveFrag liveFrag = new LiveFrag();
     getSupportFragmentManager().beginTransaction().add(R.id.fl_root, liveFrag).commit();
     // 加载
     new InteractiveFrag().show(getSupportFragmentManager(), "InteractiveFrag");
     }
    }
    
    

    activity_main.xml :

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
     <FrameLayout
     android:id="@+id/fl_root"
     android:layout_width="match_parent"
     android:layout_height="match_parent" />
    </RelativeLayout>

    用户交互页实现

    MagicTextView动画效果

    MagicTextView代码在文章最后展示。

    我们先实现如下动画效果

    <com.hongx.zhibo.utils.MagicTextView
     android:id="@+id/mtv_giftNum"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_centerVertical="true"
     android:layout_marginLeft="5dp"
     android:layout_toRightOf="@+id/rlparent"
     android:includeFontPadding="false"
     android:text="x1"
     android:textColor="@android:color/holo_red_dark"
     android:textSize="30sp"
     android:textStyle="bold"
     app:strokeColor="@android:color/white"
     app:strokeJoinStyle="miter"
     app:strokeWidth="2" />
    
    

    动画:

     public class NumberAnim {
     private Animator lastAnimator;
     public void showAnimator(View v) {
     if (lastAnimator != null) {
     lastAnimator.removeAllListeners();
     lastAnimator.cancel();
     lastAnimator.end();
     }
     ObjectAnimator animScaleX = ObjectAnimator.ofFloat(v, "scaleX", 1.3f, 1.0f);
     ObjectAnimator animScaleY = ObjectAnimator.ofFloat(v, "scaleY", 1.3f, 1.0f);
     AnimatorSet animSet = new AnimatorSet();
     animSet.playTogether(animScaleX, animScaleY);
     animSet.setDuration(200);
     lastAnimator = animSet;
     animSet.start();
     }
     }
    
     mtv_giftNum.setText("x" + count);
     giftNumberAnim = new NumberAnim(); // 初始化数字动画 
     mtv_giftNum.setOnClickListener(new View.OnClickListener() {
     @Override
     public void onClick(View v) {
     count++;
     mtv_giftNum.setText("x" + count);
     giftNumberAnim.showAnimator(mtv_giftNum);
     }
     });
    

    礼物进入时动画

    进入动画设置为decelerate_interpolator减速插值器:

    <?xml version="1.0" encoding="utf-8"?>
    <translate xmlns:android="http://schemas.android.com/apk/res/android"
     android:duration="500"
     android:fromXDelta="-100%p"
     android:interpolator="@android:anim/decelerate_interpolator"
     android:toYDelta="0%p">
    </translate>
    
     /**
     * 刷礼物的方法
     */
     private void showGift(String tag) {
     View newGiftView = ll_gift_group.findViewWithTag(tag);
     // 是否有该tag类型的礼物
     if (newGiftView == null) {
     // 获取礼物
     newGiftView = getNewGiftView(tag);
     ll_gift_group.addView(newGiftView);
    
     // 播放动画
     newGiftView.startAnimation(inAnim);
     final MagicTextView mtv_giftNum = newGiftView.findViewById(R.id.mtv_giftNum);
     inAnim.setAnimationListener(new Animation.AnimationListener() {
    
     @Override
     public void onAnimationStart(Animation animation) {
     }
    
     @Override
     public void onAnimationRepeat(Animation animation) {
     }
    
     @Override
     public void onAnimationEnd(Animation animation) {
     giftNumberAnim.showAnimator(mtv_giftNum);
     }
     });
     } else {
     // 如果列表中已经有了该类型的礼物,则不再新建,直接拿出
     // 更新标识,记录最新修改的时间,用于回收判断
     ImageView iv_gift = newGiftView.findViewById(R.id.iv_gift);
     iv_gift.setTag(System.currentTimeMillis());
    
     // 更新标识,更新记录礼物个数
     MagicTextView mtv_giftNum = newGiftView.findViewById(R.id.mtv_giftNum);
     int giftCount = (int) mtv_giftNum.getTag() + 1; // 递增
     mtv_giftNum.setText("x" + giftCount);
     mtv_giftNum.setTag(giftCount);
     giftNumberAnim.showAnimator(mtv_giftNum);
     }
     }
    
     /**
     * 获取礼物
     */
     private View getNewGiftView(String tag) {
    
     // 添加标识, 该view若在layout中存在,就不在生成(用于findViewWithTag判断是否存在)
     View giftView = LayoutInflater.from(myContext).inflate(R.layout.item_gift, null);
     giftView.setTag(tag);
    
     // 添加标识, 记录生成时间,回收时用于判断是否是最新的,回收最老的
     ImageView iv_gift = giftView.findViewById(R.id.iv_gift);
     iv_gift.setTag(System.currentTimeMillis());
    
     // 添加标识,记录礼物个数
     MagicTextView mtv_giftNum = giftView.findViewById(R.id.mtv_giftNum);
     mtv_giftNum.setTag(1);
     mtv_giftNum.setText("x1");
    
     switch (tag) {
     case "gift01":
     iv_gift.setImageResource(GiftIcon[0]);
     break;
     case "gift02":
     iv_gift.setImageResource(GiftIcon[1]);
     break;
     case "gift03":
     iv_gift.setImageResource(GiftIcon[2]);
     break;
     case "gift04":
     iv_gift.setImageResource(GiftIcon[3]);
     break;
     }
    
     LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
     lp.topMargin = 10;
     giftView.setLayoutParams(lp);
    
     return giftView;
     }
    
     @Override
     public void onClick(View v) {
     switch (v.getId()) {
     case R.id.btn_gift01: // 礼物1,送香皂
     showGift("gift01");
     break;
     case R.id.btn_gift02: // 礼物2,送玫瑰
     showGift("gift02");
     break;
     case R.id.btn_gift03: // 礼物3,送爱心
     showGift("gift03");
     break;
     case R.id.btn_gift04: // 礼物4,送蛋糕
     showGift("gift04");
     break;
     }
     }

    礼物移出动画

    实现的效果如下:

    礼物移出时使用accelerate_interpolator加速差值器

    <?xml version="1.0" encoding="utf-8"?>
    <translate xmlns:android="http://schemas.android.com/apk/res/android"
     android:duration="500"
     android:fromYDelta="0%p"
     android:interpolator="@android:anim/accelerate_interpolator"
     android:toYDelta="-100%p">
    </translate>
    
     /**
     * 移除礼物列表里的giftView
     */
     private void removeGiftView(final int index) {
     // 移除列表,外加退出动画
     final View removeGiftView = ll_gift_group.getChildAt(index);
     outAnim.setAnimationListener(new Animation.AnimationListener() {
    
     @Override
     public void onAnimationStart(Animation animation) {
     }
    
     @Override
     public void onAnimationRepeat(Animation animation) {
     }
    
     @Override
     public void onAnimationEnd(Animation animation) {
     ll_gift_group.removeViewAt(index);
     }
     });
    
     // 开启动画,因为定时原因,所以可能是在子线程
     getActivity().runOnUiThread(new Runnable() {
     @Override
     public void run() {
     removeGiftView.startAnimation(outAnim);
     }
     });
     }

    如果显示的礼物大于3种,就将最早的那种礼物移除:

    // 是否有该tag类型的礼物
     if (newGiftView == null) {
     // 判断礼物列表是否已经有3个了,如果有那么删除掉一个没更新过的, 然后再添加新进来的礼物,始终保持只有3个
     if (ll_gift_group.getChildCount() >= 3) {
     // 获取前2个元素的最后更新时间
     View giftView01 = ll_gift_group.getChildAt(0);
     ImageView iv_gift01 = giftView01.findViewById(R.id.iv_gift);
     long lastTime1 = (long) iv_gift01.getTag();
    
     View giftView02 = ll_gift_group.getChildAt(1);
     ImageView iv_gift02 = giftView02.findViewById(R.id.iv_gift);
     long lastTime2 = (long) iv_gift02.getTag();
    
     if (lastTime1 > lastTime2) { // 如果第二个View显示的时间比较长
     removeGiftView(1);
     } else { // 如果第一个View显示的时间长
     removeGiftView(0);
     }
     }
    ...
    
    

    开启定时清理礼物列表

    礼物显示超过一定时间,自动将礼物在礼物列表中移除:

     /**
     * 定时清理礼物列表信息
     */
     private void clearTiming() {
     Timer timer = new Timer();
     timer.schedule(new TimerTask() {
    
     @Override
     public void run() {
     int childCount = ll_gift_group.getChildCount();
     long nowTime = System.currentTimeMillis();
     for (int i = 0; i < childCount; i++) {
    
     View childView = ll_gift_group.getChildAt(i);
     ImageView iv_gift = (ImageView) childView.findViewById(R.id.iv_gift);
     long lastUpdateTime = (long) iv_gift.getTag();
    
     // 更新超过3秒就刷新
     if (nowTime - lastUpdateTime >= 3000) {
     removeGiftView(i);
     }
     }
     }
     }, 0, 3000);
     }

    聊天实现

    case R.id.tv_chat:// 聊天
     tv_chat.setVisibility(View.GONE);
     ll_inputparent.setVisibility(View.VISIBLE);
     ll_inputparent.requestFocus(); // 获取焦点
     showKeyboard();
     break;
     case R.id.tv_send:// 发送消息
     String chatMsg = et_chat.getText().toString();
     if (!TextUtils.isEmpty(chatMsg)) {
     messageData.add("小明: " + chatMsg);
     et_chat.setText("");
     messageAdapter.NotifyAdapter(messageData);
     lv_message.setSelection(messageData.size());
     }
     hideKeyboard();
     break;
    
     /**
     * 显示软键盘
     */
     private void showKeyboard() {
     InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
     imm.showSoftInput(et_chat, InputMethodManager.SHOW_FORCED);
     }
    
     /**
     * 隐藏软键盘
     */
     public void hideKeyboard() {
     InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
     imm.hideSoftInputFromWindow(et_chat.getWindowToken(), 0);
     }
    
     view.setOnClickListener(new View.OnClickListener() {
    
     @Override
     public void onClick(View v) {
     if (ll_inputparent.getVisibility() == View.VISIBLE) {
     tv_chat.setVisibility(View.VISIBLE);
     ll_inputparent.setVisibility(View.GONE);
     hideKeyboard();
     }
     }
     });
    
     // 软键盘监听
     SoftKeyBoardListener.setListener(getActivity(), new SoftKeyBoardListener.OnSoftKeyBoardChangeListener() {
     @Override
     public void keyBoardShow(int height) {/*软键盘显示:执行隐藏title动画,并修改listview高度和装载礼物容器的高度*/
    
     // 输入文字时的界面退出动画
     AnimatorSet animatorSetHide = new AnimatorSet();
     ObjectAnimator leftOutAnim = ObjectAnimator.ofFloat(rl_num, "translationX", 0, -rl_num.getWidth());
     ObjectAnimator topOutAnim = ObjectAnimator.ofFloat(ll_anchor, "translationY", 0, -ll_anchor.getHeight());
     animatorSetHide.playTogether(leftOutAnim, topOutAnim);
     animatorSetHide.setDuration(300);
     animatorSetHide.start();
     // 改变listview的高度
     dynamicChangeListviewH(90);
     dynamicChangeGiftParentH(true);
     }
    
     @Override
     public void keyBoardHide(int height) {/*软键盘隐藏:隐藏聊天输入框并显示聊天按钮,执行显示title动画,并修改listview高度和装载礼物容器的高度*/
     tv_chat.setVisibility(View.VISIBLE);
     ll_inputparent.setVisibility(View.GONE);
     // 输入文字时的界面进入时的动画
     AnimatorSet animatorSetShow = new AnimatorSet();
     ObjectAnimator leftInAnim = ObjectAnimator.ofFloat(rl_num, "translationX", -rl_num.getWidth(), 0);
     ObjectAnimator topInAnim = ObjectAnimator.ofFloat(ll_anchor, "translationY", -ll_anchor.getHeight(), 0);
     animatorSetShow.playTogether(leftInAnim, topInAnim);
     animatorSetShow.setDuration(300);
     animatorSetShow.start();
    
     // 改变listview的高度
     dynamicChangeListviewH(150);
     dynamicChangeGiftParentH(false);
     }
     });
    
     /**
     * 动态的修改listview的高度
     */
     private void dynamicChangeListviewH(int heightPX) {
     ViewGroup.LayoutParams layoutParams = lv_message.getLayoutParams();
     layoutParams.height = DisplayUtil.dip2px(getActivity(), heightPX);
     lv_message.setLayoutParams(layoutParams);
     }
    
     /**
     * 动态修改礼物父布局的高度
     */
     private void dynamicChangeGiftParentH(boolean showhide) {
     if (showhide) {// 如果软键盘显示中
     if (ll_gift_group.getChildCount() != 0) {
    
     // 判断是否有礼物显示,如果有就修改父布局高度,如果没有就不作任何操作
     ViewGroup.LayoutParams layoutParams = ll_gift_group.getLayoutParams();
     layoutParams.height = ll_gift_group.getChildAt(0).getHeight();
     ll_gift_group.setLayoutParams(layoutParams);
     }
     } else {
     // 如果软键盘隐藏中
     // 就将装载礼物的容器的高度设置为包裹内容
     ViewGroup.LayoutParams layoutParams = ll_gift_group.getLayoutParams();
     layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
     ll_gift_group.setLayoutParams(layoutParams);
     }
     }
    
    

    MagicTextView代码

    /**
     * 该自定义view是用于显示礼物数字的,加了些效果,内发光,阴影等
     */
    public class MagicTextView extends TextView {
     private ArrayList<Shadow> outerShadows;
     private ArrayList<Shadow> innerShadows;
     private WeakHashMap<String, Pair<Canvas, Bitmap>> canvasStore;
     private Canvas tempCanvas;
     private Bitmap tempBitmap;
     private Drawable foregroundDrawable;
     private float strokeWidth;
     private Integer strokeColor;
     private Join strokeJoin;
     private float strokeMiter;
     private int[] lockedCompoundPadding;
     private boolean frozen = false;
     public MagicTextView(Context context) {
     super(context);
     init(null);
     }
     public MagicTextView(Context context, AttributeSet attrs) {
     super(context, attrs);
     init(attrs);
     }
     public MagicTextView(Context context, AttributeSet attrs, int defStyle) {
     super(context, attrs, defStyle);
     init(attrs);
     }
     public void init(AttributeSet attrs) {
     outerShadows = new ArrayList<Shadow>();
     innerShadows = new ArrayList<Shadow>();
     if (canvasStore == null) {
     canvasStore = new WeakHashMap<String, Pair<Canvas, Bitmap>>();
     }
     if (attrs != null) {
     TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.MagicTextView);
     String typefaceName = a.getString(R.styleable.MagicTextView_typeface);
     if (typefaceName != null) {
     Typeface tf = Typeface.createFromAsset(getContext().getAssets(), String.format("fonts/%s.ttf", typefaceName));
     setTypeface(tf);
     }
     if (a.hasValue(R.styleable.MagicTextView_foreground)) {
     Drawable foreground = a.getDrawable(R.styleable.MagicTextView_foreground);
     if (foreground != null) {
     this.setForegroundDrawable(foreground);
     } else {
     this.setTextColor(a.getColor(R.styleable.MagicTextView_foreground, 0xff000000));
     }
     }
     if (a.hasValue(R.styleable.MagicTextView_innerShadowColor)) {
     this.addInnerShadow(a.getFloat(R.styleable.MagicTextView_innerShadowRadius, 0),
     a.getFloat(R.styleable.MagicTextView_innerShadowDx, 0),
     a.getFloat(R.styleable.MagicTextView_innerShadowDy, 0),
     a.getColor(R.styleable.MagicTextView_innerShadowColor, 0xff000000));
     }
     if (a.hasValue(R.styleable.MagicTextView_outerShadowColor)) {
     this.addOuterShadow(a.getFloat(R.styleable.MagicTextView_outerShadowRadius, 0),
     a.getFloat(R.styleable.MagicTextView_outerShadowDx, 0),
     a.getFloat(R.styleable.MagicTextView_outerShadowDy, 0),
     a.getColor(R.styleable.MagicTextView_outerShadowColor, 0xff000000));
     }
     if (a.hasValue(R.styleable.MagicTextView_strokeColor)) {
     float strokeWidth = a.getFloat(R.styleable.MagicTextView_strokeWidth, 1);
     int strokeColor = a.getColor(R.styleable.MagicTextView_strokeColor, 0xff000000);
     float strokeMiter = a.getFloat(R.styleable.MagicTextView_strokeMiter, 10);
     Join strokeJoin = null;
     switch (a.getInt(R.styleable.MagicTextView_strokeJoinStyle, 0)) {
     case (0):
     strokeJoin = Join.MITER;
     break;
     case (1):
     strokeJoin = Join.BEVEL;
     break;
     case (2):
     strokeJoin = Join.ROUND;
     break;
     }
     this.setStroke(strokeWidth, strokeColor, strokeJoin, strokeMiter);
     }
     }
     }
     public void setStroke(float width, int color, Join join, float miter) {
     strokeWidth = width;
     strokeColor = color;
     strokeJoin = join;
     strokeMiter = miter;
     }
     public void setStroke(float width, int color) {
     setStroke(width, color, Join.MITER, 10);
     }
     public void addOuterShadow(float r, float dx, float dy, int color) {
     if (r == 0) {
     r = 0.0001f;
     }
     outerShadows.add(new Shadow(r, dx, dy, color));
     }
     public void addInnerShadow(float r, float dx, float dy, int color) {
     if (r == 0) {
     r = 0.0001f;
     }
     innerShadows.add(new Shadow(r, dx, dy, color));
     }
     public void clearInnerShadows() {
     innerShadows.clear();
     }
     public void clearOuterShadows() {
     outerShadows.clear();
     }
     public void setForegroundDrawable(Drawable d) {
     this.foregroundDrawable = d;
     }
     public Drawable getForeground() {
     return this.foregroundDrawable == null ? this.foregroundDrawable : new ColorDrawable(this.getCurrentTextColor());
     }
     @Override
     public void onDraw(Canvas canvas) {
     super.onDraw(canvas);
     freeze();
     Drawable restoreBackground = this.getBackground();
     Drawable[] restoreDrawables = this.getCompoundDrawables();
     int restoreColor = this.getCurrentTextColor();
     this.setCompoundDrawables(null, null, null, null);
     for (Shadow shadow : outerShadows) {
     this.setShadowLayer(shadow.r, shadow.dx, shadow.dy, shadow.color);
     super.onDraw(canvas);
     }
     this.setShadowLayer(0, 0, 0, 0);
     this.setTextColor(restoreColor);
     if (this.foregroundDrawable != null && this.foregroundDrawable instanceof BitmapDrawable) {
     generateTempCanvas();
     super.onDraw(tempCanvas);
     Paint paint = ((BitmapDrawable) this.foregroundDrawable).getPaint();
     paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP));
     this.foregroundDrawable.setBounds(canvas.getClipBounds());
     this.foregroundDrawable.draw(tempCanvas);
     canvas.drawBitmap(tempBitmap, 0, 0, null);
     tempCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
     }
     if (strokeColor != null) {
     TextPaint paint = this.getPaint();
    // paint.setTextAlign(Paint.Align.CENTER);
     paint.setStyle(Style.STROKE);
     paint.setStrokeJoin(strokeJoin);
     paint.setStrokeMiter(strokeMiter);
     this.setTextColor(strokeColor);
     paint.setStrokeWidth(strokeWidth);
     super.onDraw(canvas);
     paint.setStyle(Style.FILL);
     this.setTextColor(restoreColor);
     }
     if (innerShadows.size() > 0) {
     generateTempCanvas();
     TextPaint paint = this.getPaint();
     for (Shadow shadow : innerShadows) {
     this.setTextColor(shadow.color);
     super.onDraw(tempCanvas);
     this.setTextColor(0xFF000000);
     paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
     paint.setMaskFilter(new BlurMaskFilter(shadow.r, BlurMaskFilter.Blur.NORMAL));
     tempCanvas.save();
     tempCanvas.translate(shadow.dx, shadow.dy);
     super.onDraw(tempCanvas);
     tempCanvas.restore();
     canvas.drawBitmap(tempBitmap, 0, 0, null);
     tempCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
     paint.setXfermode(null);
     paint.setMaskFilter(null);
     this.setTextColor(restoreColor);
     this.setShadowLayer(0, 0, 0, 0);
     }
     }
     if (restoreDrawables != null) {
     this.setCompoundDrawablesWithIntrinsicBounds(restoreDrawables[0], restoreDrawables[1], restoreDrawables[2], restoreDrawables[3]);
     }
     this.setBackgroundDrawable(restoreBackground);
     this.setTextColor(restoreColor);
     unfreeze();
     }
     private void generateTempCanvas() {
     String key = String.format("%dx%d", getWidth(), getHeight());
     Pair<Canvas, Bitmap> stored = canvasStore.get(key);
     if (stored != null) {
     tempCanvas = stored.first;
     tempBitmap = stored.second;
     } else {
     tempCanvas = new Canvas();
     tempBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
     tempCanvas.setBitmap(tempBitmap);
     canvasStore.put(key, new Pair<Canvas, Bitmap>(tempCanvas, tempBitmap));
     }
     }
     public void freeze() {
     lockedCompoundPadding = new int[]{
     getCompoundPaddingLeft(),
     getCompoundPaddingRight(),
     getCompoundPaddingTop(),
     getCompoundPaddingBottom()
     };
     frozen = true;
     }
     public void unfreeze() {
     frozen = false;
     }
     @Override
     public void requestLayout() {
     if (!frozen) super.requestLayout();
     }
     @Override
     public void postInvalidate() {
     if (!frozen) super.postInvalidate();
     }
     @Override
     public void postInvalidate(int left, int top, int right, int bottom) {
     if (!frozen) super.postInvalidate(left, top, right, bottom);
     }
     @Override
     public void invalidate() {
     if (!frozen) super.invalidate();
     }
     @Override
     public void invalidate(Rect rect) {
     if (!frozen) super.invalidate(rect);
     }
     @Override
     public void invalidate(int l, int t, int r, int b) {
     if (!frozen) super.invalidate(l, t, r, b);
     }
     @Override
     public int getCompoundPaddingLeft() {
     return !frozen ? super.getCompoundPaddingLeft() : lockedCompoundPadding[0];
     }
     @Override
     public int getCompoundPaddingRight() {
     return !frozen ? super.getCompoundPaddingRight() : lockedCompoundPadding[1];
     }
     @Override
     public int getCompoundPaddingTop() {
     return !frozen ? super.getCompoundPaddingTop() : lockedCompoundPadding[2];
     }
     @Override
     public int getCompoundPaddingBottom() {
     return !frozen ? super.getCompoundPaddingBottom() : lockedCompoundPadding[3];
     }
     public static class Shadow {
     float r;
     float dx;
     float dy;
     int color;
    
     public Shadow(float r, float dx, float dy, int color) {
     this.r = r;
     this.dx = dx;
     this.dy = dy;
     this.color = color;
     }
     }
    }
    
    

    Github:https://github.com/345166018/AndroidUI/tree/master/HxZhibo

    总结

    以上所述是小编给大家介绍的Android仿直播类app赠送礼物功能,希望对大家有所帮助!

    更多阅读