这篇文章给大家分享的是有关Android如何实现仿直播类app赠送礼物功能的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。
桑珠孜ssl适用于网站、小程序/APP、API接口等需要进行数据传输应用场景,ssl证书未来市场广阔!成为创新互联建站的ssl证书销售渠道,可以享受市场价格4-6折优惠!如果有意向欢迎电话联系或者加微信:18982081108(备注:SSL证书合作)期待与您的合作!
实现的是播放本地的视频文件:
/**
* 直播界面,用于对接直播功能
*/
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 如下:
滑动隐藏效果
需要实现的效果如下:

自定义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文件如下:
用户交互页 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:
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:
在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 :
用户交互页实现
MagicTextView动画效果
MagicTextView代码在文章最后展示。
我们先实现如下动画效果

动画:
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减速插值器:
/** * 刷礼物的方法 */ 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加速差值器
/** * 移除礼物列表里的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 outerShadows;
private ArrayList innerShadows;
private WeakHashMap> 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();
innerShadows = new ArrayList();
if (canvasStore == null) {
canvasStore = new WeakHashMap>();
}
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 感谢各位的阅读!关于“Android如何实现仿直播类app赠送礼物功能”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!
新闻名称:Android如何实现仿直播类app赠送礼物功能
网站网址:http://www.jxjierui.cn/article/gocsid.html


咨询
建站咨询
