...
 
Commits (5)
......@@ -95,14 +95,15 @@ def enableProguardInReleaseBuilds = false
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
defaultConfig {
applicationId "com.polyvrncloudclassdemo"
applicationId "com.easefun.polyvsdk.cloudclass"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"
multiDexEnabled true
ndk {
abiFilters "armeabi-v7a", "x86"
}
......@@ -134,9 +135,17 @@ android {
}
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
compile project(':react-native-gesture-handler')
compile project(':react-native-reanimated')
api project(':polyvsdk')
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
implementation "com.facebook.react:react-native:+" // From node_modules
......
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<application android:usesCleartextTraffic="true" tools:targetApi="28" tools:ignore="GoogleAppIndexingWarning" />
</manifest>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.polyvrncloudclassdemo">
xmlns:tools="http://schemas.android.com/tools"
package="com.easefun.polyvsdk.cloudclass">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<application
android:name=".MainApplication"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:allowBackup="false"
android:theme="@style/AppTheme">
android:name=".MainApplication"
android:hardwareAccelerated="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@drawable/ic_launcher"
android:supportsRtl="true"
android:theme="@style/Theme.AppCompat.Light.NoActionBar"
tools:replace="android:icon,android:theme">
<activity
android:name=".MainActivity"
android:name="com.easefun.polyvsdk.cloudclass.MainActivity"
android:label="@string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:windowSoftInputMode="adjustResize">
......
package com.polyvrncloudclassdemo;
package com.easefun.polyvsdk.cloudclass;
import com.facebook.react.ReactActivity;
import com.facebook.react.ReactActivityDelegate;
import com.facebook.react.ReactRootView;
import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;
public class MainActivity extends ReactActivity {
......@@ -12,4 +15,14 @@ public class MainActivity extends ReactActivity {
protected String getMainComponentName() {
return "PolyvRNCloudClassDemo";
}
@Override
protected ReactActivityDelegate createReactActivityDelegate() {
return new ReactActivityDelegate(this, getMainComponentName()) {
@Override
protected ReactRootView createRootView() {
return new RNGestureHandlerEnabledRootView(MainActivity.this);
}
};
}
}
package com.polyvrncloudclassdemo;
package com.easefun.polyvsdk.cloudclass;
import android.app.Application;
import com.blankj.utilcode.util.AppUtils;
import com.easefun.polyv.cloudclassdemo.PolyvCloudClassApp;
import com.easefun.polyv.foundationsdk.utils.PolyvAppUtils;
import com.easefun.polyvsdk.cloudclass.rn.PolyvCloudClassRNPackage;
import com.facebook.react.ReactApplication;
import com.swmansion.gesturehandler.react.RNGestureHandlerPackage;
import com.swmansion.reanimated.ReanimatedPackage;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
......@@ -11,7 +17,7 @@ import com.facebook.soloader.SoLoader;
import java.util.Arrays;
import java.util.List;
public class MainApplication extends Application implements ReactApplication {
public class MainApplication extends PolyvCloudClassApp implements ReactApplication {
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
......@@ -22,7 +28,10 @@ public class MainApplication extends Application implements ReactApplication {
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage()
new MainReactPackage(),
new RNGestureHandlerPackage(),
new ReanimatedPackage(),
new PolyvCloudClassRNPackage()
);
}
......@@ -39,6 +48,7 @@ public class MainApplication extends Application implements ReactApplication {
@Override
public void onCreate() {
PolyvAppUtils.init(this);
super.onCreate();
SoLoader.init(this, /* native exopackage */ false);
}
......
package com.easefun.polyvsdk.cloudclass;
import android.app.Application;
import android.content.Context;
import com.easefun.polyv.businesssdk.vodplayer.PolyvVodSDKClient;
import com.easefun.polyv.cloudclass.config.PolyvLiveSDKClient;
import com.easefun.polyv.foundationsdk.log.PolyvCommonLog;
/**
* @author df
* @create 2019/9/6
* @Describe
*/
public class PolyvInitManager {
public static void init(String vodKey, String decodeKey, String decodeIv, Context context){
// Normal app init code...
PolyvCommonLog.setDebug(true);
PolyvLiveSDKClient liveSDKClient = PolyvLiveSDKClient.getInstance();
liveSDKClient.initContext(null);
PolyvVodSDKClient client = PolyvVodSDKClient.getInstance();
//使用SDK加密串来配置
client.setConfig(vodKey, decodeKey, decodeIv);
}
}
package com.easefun.polyvsdk.cloudclass.rn;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* @author df
* @create 2019/9/6
* @Describe
*/
public class PolyvCloudClassRNPackage implements ReactPackage {
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new PolyvCloudClassRNModule(reactContext));
return modules;
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
}
package com.easefun.polyvsdk.cloudclass.rn;
/**
* @author df
* @create 2019/1/26
* @Describe
*/
public class PolyvErrorCode {
/**
* code,返回码定义:
* 0 成功
* -1 AppId为空
* -2 AppSecret为空
* -3 viewerId为空
* -4 UserId为空
* -5 ChannelId为空
* -6 频道加载失败
*/
public final static int success = 0;
public final static int noAppId = -1;
public final static int noAppScrect = -2;
public final static int noViewId = -3;
public final static int noUserId = -4;
public final static int noChannelId = -5;
public final static int noVideoId = -6;
public final static int noVodKey = -7;
public final static int noDecodeKey = -8;
public final static int noDecodeIv = -9;
public final static int channleLoadFailed = -10;
public static String getDesc(int code) {
switch (code) {
case PolyvErrorCode.success:
return "成功";
case PolyvErrorCode.noAppId:
return "AppId为空";
case PolyvErrorCode.noAppScrect:
return "AppSecret为空";
case PolyvErrorCode.noViewId:
return "viewerId为空";
case PolyvErrorCode.noUserId:
return "UserId为空";
case PolyvErrorCode.noChannelId:
return "ChannelId为空";
case PolyvErrorCode.noVideoId:
return "videoId为空";
case PolyvErrorCode.channleLoadFailed:
return "频道加载失败";
case PolyvErrorCode.noVodKey:
return "VodKey为空";
case PolyvErrorCode.noDecodeKey:
return "DecodeKey为空";
case PolyvErrorCode.noDecodeIv:
return "DecodeIv为空";
default:
return "";
}
}
}
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext {
buildToolsVersion = "27.0.3"
minSdkVersion = 16
compileSdkVersion = 27
targetSdkVersion = 26
supportLibVersion = "27.1.1"
}
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.4'
classpath("com.android.tools.build:gradle:3.3.0")
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
......@@ -23,17 +16,29 @@ buildscript {
allprojects {
repositories {
mavenLocal()
maven {
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
url("$rootDir/../node_modules/react-native/android")
}
maven {
// Android JSC is installed from npm
url("$rootDir/../node_modules/jsc-android/dist")
}
google()
jcenter()
maven { url "https://jitpack.io" }
maven {
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
url "$rootDir/../node_modules/react-native/android"
url 'http://maven.aliyun.com/nexus/content/repositories/releases/'
}
maven { url 'https://dl.bintray.com/polyv/abn' }
}
}
task wrapper(type: Wrapper) {
gradleVersion = '4.4'
distributionUrl = distributionUrl.replace("bin", "all")
ext {
supportLibVersion = "27.1.1"
compileSdkVersion = 27
minSdkVersion = 16
targetSdkVersion = 27
versionCode = 8202
versionName = "0.8.2.02"
}
apply plugin: 'com.android.library'
android {
compileSdkVersion rootProject.ext.compileSdkVersion
defaultConfig {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode rootProject.ext.versionCode
versionName rootProject.ext.versionName
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
qatest {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
lintOptions {
checkReleaseBuilds false
// Or, if you prefer, you can continue to check for errors in release builds,
// but continue the build even when errors are found:
abortOnError false
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:27.1.1'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
api 'com.android.support:design:27.1.1'
api 'com.easefun.polyv:polyvSDKCloudClass:0.8.2.02'
//glide
api 'jp.wasabeef:glide-transformations:3.3.0'
api "com.github.bumptech.glide:okhttp3-integration:4.7.1"
annotationProcessor 'com.github.bumptech.glide:compiler:4.7.1'
}
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
package com.easefun.polyv.commonui;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("com.polyv.easefun.commonui.test", appContext.getPackageName());
}
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.easefun.polyv.commonui" />
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link href="./css/app.973c3fa15a0659d368b8.css" rel="stylesheet"></head>
<body>
<div id="answerCard" class="ppt-answer-card-wrap"></div>
<div id="questionnaire" class="ppt-questionnaire-wrap ppt-hide"></div>
<div id="lottery" class="ppt-lottery-wrap"></div>
<div id="sign" class="ppt-sign-wrap"></div>
<div id="announcement" class="ppt-announcement-wrap ppt-hide">
<div class="ppt-announcement">
<div class="ppt-announcement-head">
公告
<span data-el="close">×</span>
</div>
<div class="ppt-announcement-content" data-el="content">暂无公告</div>
<div class="ppt-announcement-foot">
<span data-el="know">知道了</span>
</div>
</div>
</div>
<script type="text/javascript" src="./vendors~app.973c3fa15a0659d368b8.bundle.js"></script><script type="text/javascript" src="./app.973c3fa15a0659d368b8.bundle.js"></script></body>
</html>
\ No newline at end of file
package com.easefun.polyv.commonui;
import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.easefun.polyv.businesssdk.api.common.meidaControl.IPolyvMediaController;
import com.easefun.polyv.businesssdk.api.common.player.microplayer.PolyvCommonVideoView;
import com.easefun.polyv.businesssdk.model.video.PolyvBitrateVO;
import com.easefun.polyv.businesssdk.model.video.PolyvDefinitionVO;
import com.easefun.polyv.businesssdk.model.video.PolyvLiveLinesVO;
import com.easefun.polyv.commonui.player.adapter.PolyvBitRateAdapter;
import com.easefun.polyv.foundationsdk.log.PolyvCommonLog;
import com.easefun.polyv.foundationsdk.utils.PolyvScreenUtils;
import java.util.List;
import java.util.ListIterator;
/**
* @author df
* @create 2018/8/16
* @Describe 公共的控制类
*/
public abstract class PolyvCommonMediacontroller<T extends PolyvCommonVideoView> extends FrameLayout
implements IPolyvMediaController<T>, View.OnClickListener {
private static final String TAG = "PolyvCommonMediacontoller";
protected View rootView, parentView;
protected TextView bitrateChange;
protected TextView bitrateChangeLand;
//控制栏显示的时间
protected static final int SHOW_TIME = 5000;
protected boolean showPPTSubView = true;//ppt显示在副屏
protected RelativeLayout videoControllerPort;
protected RelativeLayout videoControllerLand;
protected Activity context;
protected T polyvVideoView;
protected volatile int currentBitratePos;
protected PolyvBitrateVO polyvLiveBitrateVO;
//更多
protected ImageView ivMorePortrait;
protected ImageView ivMoreLand;
private ViewGroup contentView, fullVideoViewParent;
private ViewGroup.LayoutParams portraitLP;//(需要移动的整个播放器布局)在竖屏下的LayoutParams
private ViewGroup fullVideoView;//需要移动的整个播放器布局
private static final String landTag = "land";
private static final String portraitTag = "portrait";
protected boolean joinLinkMic;
private Runnable hideTask = new Runnable() {
@Override
public void run() {
hide();
}
};
public PolyvCommonMediacontroller(@NonNull Context context) {
this(context, null);
}
public PolyvCommonMediacontroller(@NonNull Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public PolyvCommonMediacontroller(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initialView();
}
protected abstract void initialView();
/**
* 切换主副平
*/
public abstract void changePPTVideoLocation();
@Override
public void setMediaPlayer(T player) {
polyvVideoView = player;
}
@Override
public T getMediaPlayer() {
return polyvVideoView;
}
@Override
public void changeToLandscape() {
if(PolyvScreenUtils.isLandscape(context)){
return;
}
// context.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
PolyvScreenUtils.setLandscape(context);
hide();
}
public void setLandscapeController() {
post(new Runnable() {
@Override
public void run() {
// // 通过移除整个播放器布局到窗口的上层布局中,并改变整个播放器布局的大小,实现全屏的播放器。
// if (fullVideoView == null) {
// fullVideoView = ((ViewGroup) polyvVideoView.getParent().getParent());
// fullVideoViewParent = (ViewGroup) fullVideoView.getParent();
// contentView = (ViewGroup) context.findViewById(Window.ID_ANDROID_CONTENT);
// }
// if (!landTag.equals(fullVideoView.getTag())) {
// fullVideoView.setTag(landTag);
// portraitLP = fullVideoView.getLayoutParams();
// fullVideoViewParent.removeView(fullVideoView);
// FrameLayout.LayoutParams flp = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
// fullVideoView.setLayoutParams(flp);
// contentView.addView(fullVideoView);
// }
ViewGroup.LayoutParams vlp = parentView.getLayoutParams();
vlp.width = ViewGroup.LayoutParams.MATCH_PARENT;
vlp.height = ViewGroup.LayoutParams.MATCH_PARENT;
videoControllerPort.setVisibility(View.GONE);
videoControllerLand.setVisibility(View.VISIBLE);
}
});
}
@Override
public void changeToPortrait() {
if(PolyvScreenUtils.isPortrait(context)){
return;
}
// context.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
PolyvScreenUtils.setPortrait(context);
hide();
}
@Override
public void initialConfig(ViewGroup view) {
parentView = view;
changeToPortrait();
}
private void setPortraitController() {
post(new Runnable() {
@Override
public void run() {
ViewGroup.LayoutParams vlp = parentView.getLayoutParams();
vlp.width = ViewGroup.LayoutParams.MATCH_PARENT;
vlp.height = PolyvScreenUtils.getHeight();
videoControllerLand.setVisibility(View.GONE);
videoControllerPort.setVisibility(View.VISIBLE);
}
});
}
@Override
public void hide() {
setVisibility(View.GONE);
}
@Override
public boolean isShowing() {
return isShown();
}
@Override
public void show() {
show(SHOW_TIME);
}
@Override
public void show(int timeout) {
setVisibility(VISIBLE);
if(getHandler() != null){
getHandler().removeCallbacks(hideTask);
}
postDelayed(hideTask, timeout);
}
@Override
protected void onConfigurationChanged(Configuration newConfig) {
PolyvCommonLog.d(TAG,"onConfigurationChanged");
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
PolyvScreenUtils.hideStatusBar(context);
setLandscapeController();
} else {
PolyvScreenUtils.showStatusBar(context);
setPortraitController();
}
}
protected void goneWithAnimation(View view) {
view.setVisibility(View.GONE);
view.startAnimation(AnimationUtils.loadAnimation(context, R.anim.polyv_ltor_right));
}
protected void visibleWithAnimation(View view) {
view.setVisibility(View.VISIBLE);
view.startAnimation(AnimationUtils.loadAnimation(context, R.anim.polyv_rtol_right));
}
@Override
public void onClick(View view) {
}
@Override
public void initialBitrate(PolyvBitrateVO bitrateVO) {
}
@Override
public void initialLines(List<PolyvLiveLinesVO> linesVO) {
}
public abstract void updatePPTShowStatus(boolean showPPT);
}
package com.easefun.polyv.commonui.adapter;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import com.bumptech.glide.request.RequestOptions;
import com.easefun.polyv.commonui.adapter.viewholder.ClickableViewHolder;
import com.easefun.polyv.commonui.utils.glide.progress.PolyvMyProgressManager;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public abstract class PolyvBaseRecyclerViewAdapter extends
RecyclerView.Adapter<ClickableViewHolder> {
protected Context context;
protected RecyclerView mRecyclerView;
private List<RecyclerView.OnScrollListener> mListeners = new ArrayList<>();
protected RequestOptions requestOptions_t;
protected RequestOptions requestOptions_s;
protected Map<String, List<Integer>> loadImgMap = new HashMap<>();
public PolyvBaseRecyclerViewAdapter(RecyclerView recyclerView) {
this.mRecyclerView = recyclerView;
this.mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView rv, int newState) {
for (RecyclerView.OnScrollListener listener : mListeners) {
listener.onScrollStateChanged(rv, newState);
}
}
@Override
public void onScrolled(RecyclerView rv, int dx, int dy) {
for (RecyclerView.OnScrollListener listener : mListeners) {
listener.onScrolled(rv, dx, dy);
}
}
});
}
public void addOnScrollListener(RecyclerView.OnScrollListener listener) {
mListeners.add(listener);
}
public Map<String, List<Integer>> getLoadImgMap() {
return loadImgMap;
}
public RequestOptions getRequestOptions_t() {
return requestOptions_t;
}
public RequestOptions getRequestOptions_s() {
return requestOptions_s;
}
public void onDestory(){
if (getLoadImgMap() != null) {
for (String key : getLoadImgMap().keySet()) {
for (int value : getLoadImgMap().get(key)) {
PolyvMyProgressManager.removeListener(key, value);
}
}
}
};
public interface OnItemClickListener {
void onItemClick(int position, ClickableViewHolder holder);
}
interface OnItemLongClickListener {
boolean onItemLongClick(int position, ClickableViewHolder holder);
}
private OnItemClickListener itemClickListener;
private OnItemLongClickListener itemLongClickListener;
public void setOnItemClickListener(OnItemClickListener listener) {
this.itemClickListener = listener;
}
public void setOnItemLongClickListener(OnItemLongClickListener listener) {
this.itemLongClickListener = listener;
}
public void bindContext(Context context) {
this.context = context;
}
public Context getContext() {
return this.context;
}
@Override
public void onBindViewHolder(final ClickableViewHolder holder, final int position) {
holder.getParentView().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (itemClickListener != null) {
itemClickListener.onItemClick(position, holder);
}
}
});
holder.getParentView().setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
return itemLongClickListener != null
&& itemLongClickListener.onItemLongClick(position, holder);
}
});
}
@Override
public void onViewRecycled(@NonNull ClickableViewHolder holder) {
super.onViewRecycled(holder);
}
}
\ No newline at end of file
package com.easefun.polyv.commonui.adapter;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class PolyvHeaderViewRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int HEADERS_START = Integer.MIN_VALUE;
private static final int FOOTERS_START = Integer.MIN_VALUE + 10;
private static final int ITEMS_START = Integer.MIN_VALUE + 20;
private static final int ADAPTER_MAX_TYPES = 100;
private RecyclerView.Adapter mWrappedAdapter;
private List<View> mHeaderViews, mFooterViews;
private Map<Class, Integer> mItemTypesOffset;
public PolyvHeaderViewRecyclerAdapter(RecyclerView.Adapter adapter) {
mHeaderViews = new ArrayList<>();
mFooterViews = new ArrayList<>();
mItemTypesOffset = new HashMap<>();
setWrappedAdapter(adapter);
}
public void setAdapter(RecyclerView.Adapter adapter) {
if (mWrappedAdapter != null && mWrappedAdapter.getItemCount() > 0) {
notifyItemRangeRemoved(getHeaderCount(), mWrappedAdapter.getItemCount());
}
setWrappedAdapter(adapter);
notifyItemRangeInserted(getHeaderCount(), mWrappedAdapter.getItemCount());
}
@Override
public int getItemViewType(int position) {
int hCount = getHeaderCount();
if (position < hCount) {
return HEADERS_START + position;
} else {
int itemCount = mWrappedAdapter.getItemCount();
if (position < hCount + itemCount) {
return getAdapterTypeOffset() + mWrappedAdapter.getItemViewType(position - hCount);
} else {
return FOOTERS_START + position - hCount - itemCount;
}
}
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
if (viewType < HEADERS_START + getHeaderCount()) {
return new StaticViewHolder(mHeaderViews.get(viewType - HEADERS_START));
} else if (viewType < FOOTERS_START + getFooterCount()) {
return new StaticViewHolder(mFooterViews.get(viewType - FOOTERS_START));
} else {
return mWrappedAdapter.onCreateViewHolder(viewGroup, viewType - getAdapterTypeOffset());
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
int hCount = getHeaderCount();
if (position >= hCount && position < hCount + mWrappedAdapter.getItemCount()) {
mWrappedAdapter.onBindViewHolder(viewHolder, position - hCount);
}
}
public void addHeaderView(View view) {
mHeaderViews.add(view);
}
public void addFooterView(View view) {
mFooterViews.add(view);
}
public void removeHeadView() {
mHeaderViews.clear();
}
public void removeFootView() {
mFooterViews.clear();
}
@Override
public int getItemCount() {
return getHeaderCount() + getFooterCount() + getWrappedItemCount();
}
private int getWrappedItemCount() {
return mWrappedAdapter.getItemCount();
}
private int getHeaderCount() {
return mHeaderViews.size();
}
private int getFooterCount() {
return mFooterViews.size();
}
private void setWrappedAdapter(RecyclerView.Adapter adapter) {
if (mWrappedAdapter != null) mWrappedAdapter.unregisterAdapterDataObserver(mDataObserver);
mWrappedAdapter = adapter;
Class adapterClass = mWrappedAdapter.getClass();
if (!mItemTypesOffset.containsKey(adapterClass)) putAdapterTypeOffset(adapterClass);
mWrappedAdapter.registerAdapterDataObserver(mDataObserver);
}
private void putAdapterTypeOffset(Class adapterClass) {
mItemTypesOffset.put(adapterClass, ITEMS_START + mItemTypesOffset.size() * ADAPTER_MAX_TYPES);
}
private int getAdapterTypeOffset() {
return mItemTypesOffset.get(mWrappedAdapter.getClass());
}
private RecyclerView.AdapterDataObserver mDataObserver = new RecyclerView.AdapterDataObserver() {
@Override
public void onChanged() {
super.onChanged();
notifyDataSetChanged();
}
@Override
public void onItemRangeChanged(int positionStart, int itemCount) {
super.onItemRangeChanged(positionStart, itemCount);
notifyItemRangeChanged(positionStart + getHeaderCount(), itemCount);
}
@Override
public void onItemRangeInserted(int positionStart, int itemCount) {
super.onItemRangeInserted(positionStart, itemCount);
notifyItemRangeInserted(positionStart + getHeaderCount(), itemCount);
}
@Override
public void onItemRangeRemoved(int positionStart, int itemCount) {
super.onItemRangeRemoved(positionStart, itemCount);
notifyItemRangeRemoved(positionStart + getHeaderCount(), itemCount);
}
@Override
public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
super.onItemRangeMoved(fromPosition, toPosition, itemCount);
int hCount = getHeaderCount();
// TODO: No notifyItemRangeMoved method?
notifyItemRangeChanged(fromPosition + hCount, toPosition + hCount + itemCount);
}
};
private static class StaticViewHolder extends RecyclerView.ViewHolder {
StaticViewHolder(View itemView) {
super(itemView);
}
}
}
package com.easefun.polyv.commonui.adapter.itemview;
import android.content.Context;
import android.content.res.Resources;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.widget.FrameLayout;
/**
* @author df
* @create 2019/1/16
* @Describe
*/
public abstract class IPolyvCustomMessageBaseItemView<T> extends FrameLayout {
public IPolyvCustomMessageBaseItemView(@NonNull Context context) {
this(context,null);
}
public IPolyvCustomMessageBaseItemView(@NonNull Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public IPolyvCustomMessageBaseItemView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
//处理对应的数据信息,展示内容
public abstract void processMessage(T data, int pos);
//初始化view
public abstract void initView();
/**
* 根据图片的名称获取对应的资源id
* @param resourceName
* @return
*/
public int getDrawResourceID(String resourceName) {
Resources res=getResources();
int picid = res.getIdentifier(resourceName,"drawable",getContext().getPackageName());
return picid;
}
}
package com.easefun.polyv.commonui.adapter.viewholder;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.support.annotation.IdRes;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ProgressBar;
import com.blankj.utilcode.util.ConvertUtils;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.load.engine.GlideException;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.Target;
import com.easefun.polyv.cloudclass.chat.send.custom.PolyvCustomEvent;
import com.easefun.polyv.commonui.R;
import com.easefun.polyv.commonui.adapter.PolyvBaseRecyclerViewAdapter;
import com.easefun.polyv.commonui.adapter.itemview.IPolyvCustomMessageBaseItemView;
import com.easefun.polyv.commonui.utils.glide.progress.PolyvMyProgressManager;
import com.easefun.polyv.commonui.utils.glide.progress.PolyvOnProgressListener;
import com.easefun.polyv.foundationsdk.log.PolyvCommonLog;
import java.util.ArrayList;
import java.util.List;
/**
* @author df
* @create 2019/1/16
* @Describe viewhodler的基类
*/
public abstract class ClickableViewHolder<M, Q extends PolyvBaseRecyclerViewAdapter> extends RecyclerView.ViewHolder {
private static final String TAG = "ClickableViewHolder";
public ImageView resendMessageButton;
public FrameLayout contentContainer;
protected View parentView;
protected Q adapter;
protected Context context;
public ClickableViewHolder(View itemView, Q adapter) {
super(itemView);
this.parentView = itemView;
this.contentContainer = parentView.findViewById(R.id.message_container);
resendMessageButton = $(com.easefun.polyv.commonui.R.id.resend_message_button);
this.adapter = adapter;
this.context = parentView.getContext();
}
public View getParentView() {
return parentView;
}
@SuppressWarnings("unchecked")
public <T extends View> T $(@IdRes int id) {
return parentView.findViewById(id);
}
// <editor-fold defaultstate="collapsed" desc=""抽象方法>
//处理普通接收到的消息
public abstract void processNormalMessage(M item, int position);
//处理自定义消息
public abstract void processCustomMessage(PolyvCustomEvent item, int position);
//创建itemview
public abstract <T> IPolyvCustomMessageBaseItemView createItemView(PolyvCustomEvent<T> baseCustomEvent) ;
// </editor-fold>
//是否需要复用container里的childview
public int findReuseChildIndex(String type){
int childIndex = -1;
int count = contentContainer.getChildCount();
for (int i = 0; i < count; i++) {
View child = contentContainer.getChildAt(i);
if(type.equals(child.getTag())){
PolyvCommonLog.d(TAG,"findReuseChildIndex");
if(child.getVisibility() != View.VISIBLE){
child.setVisibility(View.VISIBLE);
}
childIndex = i;
}else {
if(child.getVisibility() != View.GONE){