android 带头像的弹幕,Android弹幕实现:基于B站弹幕开源系统(6)带用户头像且头像从网络加载...



Android弹幕实现:基于B站弹幕开源系统(6)带用户头像且头像从网络加载

在附录文章1,2,3,4,5基础上,实现一种特殊弹幕效果,实现弹幕带发表者头像。这种需求在一些开发场景中比较有用,比如在一些视频中,不同等级的用户显示不同的头像,或者本身发出来的弹幕就要求头像。

代码:

package zhangfei.danmaku;

import android.content.res.Configuration;

import android.graphics.Bitmap;

import android.graphics.BitmapFactory;

import android.graphics.Color;

import android.graphics.drawable.Drawable;

import android.support.annotation.NonNull;

import android.support.v4.graphics.drawable.RoundedBitmapDrawable;

import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory;

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

import android.text.Spannable;

import android.text.SpannableStringBuilder;

import android.text.style.BackgroundColorSpan;

import android.text.style.ImageSpan;

import android.util.Log;

import android.view.View;

import java.util.HashMap;

import java.util.concurrent.Callable;

import io.reactivex.Observable;

import io.reactivex.ObservableSource;

import io.reactivex.android.schedulers.AndroidSchedulers;

import io.reactivex.disposables.CompositeDisposable;

import io.reactivex.observers.DisposableObserver;

import io.reactivex.schedulers.Schedulers;

import master.flame.danmaku.controller.IDanmakuView;

import master.flame.danmaku.danmaku.model.BaseDanmaku;

import master.flame.danmaku.danmaku.model.DanmakuTimer;

import master.flame.danmaku.danmaku.model.IDanmakus;

import master.flame.danmaku.danmaku.model.IDisplayer;

import master.flame.danmaku.danmaku.model.android.BaseCacheStuffer;

import master.flame.danmaku.danmaku.model.android.DanmakuContext;

import master.flame.danmaku.danmaku.model.android.SpannedCacheStuffer;

import master.flame.danmaku.ui.widget.DanmakuView;

import okhttp3.OkHttpClient;

import okhttp3.Request;

import okhttp3.Response;

public class MainActivity extends AppCompatActivity {

private DanmakuView mDanmakuView;

private DanmakuContext mContext;

private AcFunDanmakuParser mParser;

private final String TAG = getClass().getSimpleName();

private OkHttpClient mOkHttpClient;

private CompositeDisposable mCompositeDisposable = new CompositeDisposable();

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mOkHttpClient = new OkHttpClient();

mContext = DanmakuContext.create();

mParser = new AcFunDanmakuParser();

initDanmakuView();

final String url="http://avatar.csdn.net/9/7/A/1_zhangphil.jpg";

findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View view) {

addItems(url);

}

});

}

private void initDanmakuView() {

// 设置最大显示行数

HashMap maxLinesPair = new HashMap<>();

maxLinesPair.put(BaseDanmaku.TYPE_SCROLL_RL, 5); // 滚动弹幕最大显示5行

// 设置是否禁止重叠

HashMap overlappingEnablePair = new HashMap();

overlappingEnablePair.put(BaseDanmaku.TYPE_SCROLL_RL, true);

overlappingEnablePair.put(BaseDanmaku.TYPE_FIX_TOP, true);

mDanmakuView = (DanmakuView) findViewById(R.id.sv_danmaku);

mContext.setDanmakuStyle(IDisplayer.DANMAKU_STYLE_STROKEN, 3)

.setDuplicateMergingEnabled(false).setScrollSpeedFactor(1.2f).setScaleTextSize(1.2f)

.setCacheStuffer(new SpannedCacheStuffer(), mCacheStufferAdapter) // 图文混排使用SpannedCacheStuffer

// .setCacheStuffer(new BackgroundCacheStuffer()) //

// 绘制背景使用BackgroundCacheStuffer

.setMaximumLines(maxLinesPair)

.preventOverlapping(overlappingEnablePair).setDanmakuMargin(40);

if (mDanmakuView != null) {

mDanmakuView.setCallback(new master.flame.danmaku.controller.DrawHandler.Callback() {

@Override

public void updateTimer(DanmakuTimer timer) {

}

@Override

public void drawingFinished() {

}

@Override

public void danmakuShown(BaseDanmaku danmaku) {

}

@Override

public void prepared() {

mDanmakuView.start();

}

});

mDanmakuView.setOnDanmakuClickListener(new IDanmakuView.OnDanmakuClickListener() {

@Override

public boolean onDanmakuClick(IDanmakus danmakus) {

BaseDanmaku latest = danmakus.last();

if (null != latest) {

return true;

}

return false;

}

@Override

public boolean onDanmakuLongClick(IDanmakus danmakus) {

return false;

}

@Override

public boolean onViewClick(IDanmakuView view) {

return false;

}

});

mDanmakuView.prepare(mParser, mContext);

// mDanmakuView.showFPS(true);

mDanmakuView.enableDanmakuDrawingCache(true);

}

}

private BaseCacheStuffer.Proxy mCacheStufferAdapter = new BaseCacheStuffer.Proxy() {

@Override

public void prepareDrawing(final BaseDanmaku danmaku, boolean fromWorkerThread) {

}

@Override

public void releaseResource(BaseDanmaku danmaku) {

// TODO 重要:清理含有ImageSpan的text中的一些占用内存的资源 例如drawable

}

};

private void addItems(final String url) {

DisposableObserver disposableObserver = new DisposableObserver() {

@Override

public void onNext(@NonNull Bitmap bmp) {

addDanmaKuShowTextAndImage(bmp, "zhang phil @ csdn", Color.DKGRAY, Color.RED, false);

}

@Override

public void onComplete() {

}

@Override

public void onError(Throwable e) {

Log.e(TAG, e.toString(), e);

}

};

mCompositeDisposable.add(

getBitmapObservable(url)

.subscribeOn(Schedulers.io())

.observeOn(AndroidSchedulers.mainThread())

.subscribeWith(disposableObserver)

);

}

private Observable getBitmapObservable(@NonNull final String url) {

return Observable.defer(new Callable>() {

@Override

public ObservableSource call() throws Exception {

Bitmap bmp = null;

//同步方法返回观察者需要的数据结果

//在这里处理线程化的操作

Request request = new Request.Builder().url(url).build();

Response response = mOkHttpClient.newCall(request).execute();

try {

if (response.isSuccessful()) {

byte[] bytes = response.body().bytes();

bmp = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);

}

} catch (Exception e) {

e.printStackTrace();

}

return Observable.just(bmp);

}

});

}

private void addDanmaKuShowTextAndImage(Bitmap bitmap, String msg, int textColor, int bgColor, boolean islive) {

BaseDanmaku danmaku = mContext.mDanmakuFactory.createDanmaku(BaseDanmaku.TYPE_SCROLL_RL);

if (danmaku == null) {

Log.e(TAG, "BaseDanmaku空");

}

//最里面的图像

RoundedBitmapDrawable drawable = RoundedBitmapDrawableFactory.create(getResources(), bitmap);

drawable.setCircular(true);

drawable.setAntiAlias(true);

drawable.setCornerRadius(Math.max(bitmap.getWidth(), bitmap.getHeight()));

drawable.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight());

SpannableStringBuilder spannable = createSpannable(drawable, msg, bgColor);

danmaku.text = spannable;

danmaku.padding = 5;

danmaku.priority = 1; // 一定会显示, 一般用于本机发送的弹幕

danmaku.isLive = islive;

danmaku.setTime(mDanmakuView.getCurrentTime() + 1200);

danmaku.textSize = 25f * (mParser.getDisplayer().getDensity() - 0.6f);

danmaku.textColor = textColor;

danmaku.textShadowColor = 0; // 重要:如果有图文混排,最好不要设置描边(设textShadowColor=0),否则会进行两次复杂的绘制导致运行效率降低

//danmaku.underlineColor = Color.GREEN;

mDanmakuView.addDanmaku(danmaku);

}

private SpannableStringBuilder createSpannable(Drawable drawable, String msg, int color) {

String text = "image";

SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(text);

spannableStringBuilder.append(msg);

ImageSpan span = new ImageSpan(drawable);// ImageSpan.ALIGN_BOTTOM);

spannableStringBuilder.setSpan(span, 0, text.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

spannableStringBuilder.setSpan(new BackgroundColorSpan(color), 0, spannableStringBuilder.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

return spannableStringBuilder;

}

@Override

protected void onPause() {

super.onPause();

if (mDanmakuView != null && mDanmakuView.isPrepared()) {

mDanmakuView.pause();

}

}

@Override

protected void onResume() {

super.onResume();

if (mDanmakuView != null && mDanmakuView.isPrepared() && mDanmakuView.isPaused()) {

mDanmakuView.resume();

}

}

@Override

protected void onDestroy() {

super.onDestroy();

if (mDanmakuView != null) {

// dont forget release!

mDanmakuView.release();

mDanmakuView = null;

}

//取消所有Okhttp的网络请求

mOkHttpClient.dispatcher().cancelAll();

mCompositeDisposable.clear();

}

@Override

public void onBackPressed() {

super.onBackPressed();

if (mDanmakuView != null) {

// dont forget release!

mDanmakuView.release();

mDanmakuView = null;

}

}

@Override

public void onConfigurationChanged(Configuration newConfig) {

super.onConfigurationChanged(newConfig);

if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {

mDanmakuView.getConfig().setDanmakuMargin(20);

} else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {

mDanmakuView.getConfig().setDanmakuMargin(40);

}

}

}

代码运行结果:

1ff03301c488369805becc65cf788a35.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值