VionTv init

This commit is contained in:
guozhen 2025-04-14 13:39:46 +08:00
commit 376abae4e5
163 changed files with 8891 additions and 0 deletions

15
.gitignore vendored Normal file
View File

@ -0,0 +1,15 @@
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties

3
.idea/.gitignore generated vendored Normal file
View File

@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

6
.idea/AndroidProjectSystem.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AndroidProjectSystem">
<option name="providerId" value="com.android.tools.idea.GradleProjectSystem" />
</component>
</project>

6
.idea/compiler.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="21" />
</component>
</project>

26
.idea/deploymentTargetSelector.xml generated Normal file
View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetSelector">
<selectionStates>
<SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" />
<DropdownSelection timestamp="2025-04-11T01:18:04.350074500Z">
<Target type="DEFAULT_BOOT">
<handle>
<DeviceId pluginId="LocalEmulator" identifier="path=C:\Users\Administrator\.android\avd\Pixel_9.avd" />
</handle>
</Target>
</DropdownSelection>
<DialogSelection>
<targets>
<Target type="DEFAULT_BOOT">
<handle>
<DeviceId pluginId="LocalEmulator" identifier="path=C:\Users\Administrator\.android\avd\Pixel_9.avd" />
</handle>
</Target>
</targets>
</DialogSelection>
</SelectionState>
</selectionStates>
</component>
</project>

19
.idea/gradle.xml generated Normal file
View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="CHOOSE_PER_TEST" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
</GradleProjectSettings>
</option>
</component>
</project>

10
.idea/migrations.xml generated Normal file
View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectMigrations">
<option name="MigrateToGradleLocalJavaHome">
<set>
<option value="$PROJECT_DIR$" />
</set>
</option>
</component>
</project>

5
.idea/misc.xml generated Normal file
View File

@ -0,0 +1,5 @@
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

17
.idea/runConfigurations.xml generated Normal file
View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="com.intellij.execution.junit.AbstractAllInDirectoryConfigurationProducer" />
<option value="com.intellij.execution.junit.AllInPackageConfigurationProducer" />
<option value="com.intellij.execution.junit.PatternConfigurationProducer" />
<option value="com.intellij.execution.junit.TestInClassConfigurationProducer" />
<option value="com.intellij.execution.junit.UniqueIdConfigurationProducer" />
<option value="com.intellij.execution.junit.testDiscovery.JUnitTestDiscoveryConfigurationProducer" />
<option value="org.jetbrains.kotlin.idea.junit.KotlinJUnitRunConfigurationProducer" />
<option value="org.jetbrains.kotlin.idea.junit.KotlinPatternConfigurationProducer" />
</set>
</option>
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

1
app/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

91
app/build.gradle Normal file
View File

@ -0,0 +1,91 @@
plugins {
alias(libs.plugins.android.application)
}
android {
namespace 'com.viontv.app'
compileSdk 35
defaultConfig {
applicationId "com.viontv.app"
minSdk 24
targetSdk 35
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
// signingConfigs {
// debug {
// storeFile file('viontv.jks')
// storePassword "android123456"
// keyAlias 'key0'
// keyPassword "android123456"
// v1SigningEnabled true
// v2SigningEnabled true
// }
// release {
// storeFile file('viontv.jks')
// storePassword "android123456"
// keyAlias 'key0'
// keyPassword "android123456"
// v1SigningEnabled true
// v2SigningEnabled true
// }
// }
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
viewBinding {
enabled true
}
dataBinding {
enabled true
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
}
dependencies {
implementation libs.appcompat
implementation libs.material
implementation libs.constraintlayout
implementation libs.lifecycle.livedata.ktx
implementation libs.lifecycle.viewmodel.ktx
testImplementation libs.junit
androidTestImplementation libs.ext.junit
androidTestImplementation libs.espresso.core
//implementation libs.lifecycle
implementation libs.retrofit
implementation libs.okhttplog
implementation libs.converter.scalars
implementation libs.converter.gson
implementation libs.adapter.rxjava2
implementation libs.rxjava
implementation libs.rxandroid
implementation libs.refreshlayout
implementation libs.refreshheader
implementation libs.refreshfooter
implementation libs.banner
implementation libs.recyclerview
implementation libs.glide
implementation libs.avloadingView
implementation libs.media3exoplayer
implementation libs.media3exoplayerdash
implementation libs.media3ui
implementation libs.media3exoplayerhls
implementation libs.eventbut
implementation libs.baseRecyclerAdapter
}

21
app/proguard-rules.pro vendored Normal file
View File

@ -0,0 +1,21 @@
# 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

View File

@ -0,0 +1,26 @@
package com.qinjiu.viontv;
import android.content.Context;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.ext.junit.runners.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.getInstrumentation().getTargetContext();
assertEquals("com.qinjiu.viontv", appContext.getPackageName());
}
}

View File

@ -0,0 +1,40 @@
<?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.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="com.google.android.gms.permission.AD_ID" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:name=".VTApplication"
android:theme="@style/Theme.VionTV"
tools:targetApi="31">
<activity
android:name=".ui.activity.VTMainActivity"
android:exported="true"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".ui.activity.play.VTVideoPlayerActivity"/>
</application>
</manifest>

View File

@ -0,0 +1,61 @@
package com.viontv.app;
import android.app.Application;
import android.text.TextUtils;
import android.util.Log;
import com.viontv.app.api.VTApi;
import com.viontv.app.api.VTApiService;
import com.viontv.app.api.VTBaseObserver;
import com.viontv.app.api.VTResult;
import com.viontv.app.model.RegisteredBean;
import com.viontv.app.utils.SharePreferenceUtils;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import retrofit2.adapter.rxjava2.Result;
public class VTApplication extends Application {
public static VTApplication AppContext;
public static VTApplication getAppContext() {
return AppContext;
}
@Override
public void onCreate() {
super.onCreate();
AppContext = this;
regist();
}
/**
* 获取token
*/
public void regist() {
String authkey = SharePreferenceUtils.getString(SharePreferenceUtils.auth, "");
if (TextUtils.isEmpty(authkey)) {
VTApi.getInstance().register()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new VTBaseObserver<VTResult<RegisteredBean>>() {
@Override
public void onSuccess(VTResult<RegisteredBean> feedbackResp) {
SharePreferenceUtils.saveString(SharePreferenceUtils.auth, feedbackResp.data.getToken());
}
@Override
public void onError(int code, String msg) {
}
});
}
}
}

View File

@ -0,0 +1,72 @@
package com.viontv.app.api;
import android.text.TextUtils;
import android.util.Log;
import java.io.UnsupportedEncodingException;
import java.net.Proxy;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
public class VTApi extends VTBaseApi {
private static final long CONNECT_TIMEOUT = 10;
private static final long READ_TIMEOUT = 10;
private static final long WRITE_TIMEOUT = 10;
/**
* 静态内部类单例
*/
private static class ApiHolder {
private static VTApi api = new VTApi();
private final static VTApiService apiService = api.initRetrofit(VTApiService.URL)
.create(VTApiService.class);
}
public static VTApiService getInstance() {
return ApiHolder.apiService;
}
/**
* 做自己需要的操作
*/
@Override
protected OkHttpClient setClient() {
OkHttpClient.Builder builder;
builder = new OkHttpClient()
.newBuilder();
//禁止使用代理抓取数据
builder.proxy(Proxy.NO_PROXY);
//设置超时
builder.connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS);
builder.readTimeout(READ_TIMEOUT, TimeUnit.SECONDS);
builder.writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS);
//错误重连
builder.retryOnConnectionFailure(true);
builder.addInterceptor(new VTHeaderInterceptor());
// if(Config.IS_DEBUG) {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(message -> {
try {
String text = URLDecoder.decode(message, "utf-8");
Log.i("OKHttp111111-----", text);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
Log.i("OKHttp1111111-----", e.getMessage());
}
});
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
builder.addInterceptor(interceptor);
// }
return builder.build();
}
}

View File

@ -0,0 +1,109 @@
package com.viontv.app.api;
import com.viontv.app.model.HomeBottomListBean;
import com.viontv.app.model.HomeTopBannerBean;
import com.viontv.app.model.HomeTopBean;
import com.viontv.app.model.RegisteredBean;
import com.viontv.app.model.TabItemBean;
import com.viontv.app.model.VTVideoDetailsBean;
import java.util.List;
import java.util.Map;
import io.reactivex.Observable;
import retrofit2.http.Body;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.Path;
import retrofit2.http.Query;
public interface VTApiService {
/**
* 正式测试服
*/
boolean isProduce = false;
String URL = isProduce ? "https://admin-viontv.guyantv.com" : "https://test1-api.guyantv.com";
public static final String rankTop10Type="most_trending";
/**
* 注册
*
* @return
*/
@POST("/customer/register")
Observable<VTResult<RegisteredBean>> register();
/**
* 首页顶部
*
* @return
*/
@POST("/homeTop")
Observable<VTResult<HomeTopBean>> homeTop();
/**
* 首页9宫格和banner
*
* @return
*/
@POST("/homeBannerAndNineSquare")
Observable<VTResult<HomeTopBannerBean>> bannersquare();
/**
* 首页底部列表
*
* @return
*/
@FormUrlEncoded
@POST("/newShortPlay")
Observable<VTResult<HomeBottomListBean>> newShortPlay(@Field("current_page") int currentpage,@Field("page_size") int pagesize);
/**
* Top10
*
* @return
*/
@FormUrlEncoded
@POST("/homeRanking")
Observable<VTResult<HomeBottomListBean>> homeTop10(@Field("type") String type);
/**
* 获取视频详情
*
* @return
*/
@GET("/getVideoDetails")
Observable<VTResult<VTVideoDetailsBean>> getVideoDetails(@Query("short_play_id") int short_play_id, @Query("video_id") int video_id);
/**
* 首页TabItem Banner
*
* @return
*/
@FormUrlEncoded
@POST("/revenge")
Observable<VTResult<TabItemBean>> getTabItemBanner(@Field("category_id") String category_id);
/**
* 首页TabItem List
*
* @return
*/
@GET("/videoList")
Observable<VTResult<HomeBottomListBean>> getVideoList(@Query("category_id") String category_id,@Query("current_page") int current,@Query("page_size") int pageSize,@Query("search") String search);
}

View File

@ -0,0 +1,37 @@
package com.viontv.app.api;
import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.converter.scalars.ScalarsConverterFactory;
public abstract class VTBaseApi {
/**
* 初始化Retrofit
*/
public Retrofit initRetrofit(String baseUrl) {
Retrofit.Builder builder = new Retrofit.Builder();
//支持返回Call<String>
builder.addConverterFactory(ScalarsConverterFactory.create());
//支持直接格式化json返回Bean对象
builder.addConverterFactory(GsonConverterFactory.create());
//支持RxJava
builder.addCallAdapterFactory(RxJava2CallAdapterFactory.create());
builder.baseUrl(baseUrl);
OkHttpClient client = setClient();
if (client != null) {
builder.client(client);
}
return builder.build();
}
/**
* 设置OkHttpClient添加拦截器等
*
* @return 可以返回为null
*/
protected abstract OkHttpClient setClient();
}

View File

@ -0,0 +1,110 @@
package com.viontv.app.api;
import com.google.gson.JsonParseException;
import org.json.JSONException;
import java.io.InterruptedIOException;
import java.net.ConnectException;
import java.net.UnknownHostException;
import java.text.ParseException;
import io.reactivex.observers.DisposableObserver;
import retrofit2.HttpException;
public abstract class VTBaseObserver<T> extends DisposableObserver<T> {
/**
* 解析数据失败
*/
public static final int PARSE_ERROR = 1001;
/**
* 网络问题
*/
public static final int BAD_NETWORK = 1002;
/**
* 连接错误
*/
public static final int CONNECT_ERROR = 1003;
/**
* 连接超时
*/
public static final int CONNECT_TIMEOUT = 1004;
@Override
public void onNext(T o) {
try {
VTResult model = (VTResult) o;
if (model.code == 200) {
onSuccess(o);
} else {
onError(model.code,model.msg);
}
} catch (Exception e) {
e.printStackTrace();
onError(407,e.toString());
}
}
@Override
public void onError(Throwable e) {
if (e instanceof HttpException) {
// HTTP错误
onException(BAD_NETWORK);
} else if (e instanceof ConnectException
|| e instanceof UnknownHostException) {
// 连接错误
onException(CONNECT_ERROR);
} else if (e instanceof InterruptedIOException) {
// 连接超时
onException(CONNECT_TIMEOUT);
} else if (e instanceof JsonParseException
|| e instanceof JSONException
|| e instanceof ParseException) {
// 解析错误
onException(PARSE_ERROR);
} else {
if (e != null) {
onError(409,e.toString());
} else {
onError(407,"未知错误");
}
}
}
private void onException(int unknownError) {
switch (unknownError) {
case CONNECT_ERROR:
onError(CONNECT_ERROR,"连接错误");
break;
case CONNECT_TIMEOUT:
onError(CONNECT_TIMEOUT,"连接超时");
break;
case BAD_NETWORK:
onError(BAD_NETWORK,"网络问题");
break;
case PARSE_ERROR:
onError(PARSE_ERROR,"宇宙也是有尽头的");
break;
default:
break;
}
}
@Override
public void onComplete() {
}
public abstract void onSuccess(T o);
public abstract void onError(int code,String msg);
}

View File

@ -0,0 +1,99 @@
package com.viontv.app.api;
import com.google.gson.JsonParseException;
import org.json.JSONException;
import java.io.InterruptedIOException;
import java.net.ConnectException;
import java.net.UnknownHostException;
import java.text.ParseException;
import io.reactivex.observers.DisposableObserver;
import retrofit2.HttpException;
public abstract class VTBaseObserver1<T> extends DisposableObserver<T> {
/**
* 解析数据失败
*/
public static final int PARSE_ERROR = 1001;
/**
* 网络问题
*/
public static final int BAD_NETWORK = 1002;
/**
* 连接错误
*/
public static final int CONNECT_ERROR = 1003;
/**
* 连接超时
*/
public static final int CONNECT_TIMEOUT = 1004;
@Override
public void onNext(T o) {
VTResult1 model = (VTResult1) o;
if (model.code == 0) {
onSuccess(o);
} else {
onError(model.code, model.msg);
}
}
@Override
public void onError(Throwable e) {
if (e instanceof HttpException) {
// HTTP错误
onException(BAD_NETWORK);
} else if (e instanceof ConnectException
|| e instanceof UnknownHostException) {
// 连接错误
onException(CONNECT_ERROR);
} else if (e instanceof InterruptedIOException) {
// 连接超时
onException(CONNECT_TIMEOUT);
} else if (e instanceof JsonParseException
|| e instanceof JSONException
|| e instanceof ParseException) {
// 解析错误
onException(PARSE_ERROR);
} else {
if (e != null) {
onError(409, e.toString());
} else {
onError(407, "未知错误");
}
}
}
private void onException(int unknownError) {
switch (unknownError) {
case CONNECT_ERROR:
onError(CONNECT_ERROR, "连接错误");
break;
case CONNECT_TIMEOUT:
onError(CONNECT_TIMEOUT, "连接超时");
break;
case BAD_NETWORK:
onError(BAD_NETWORK, "网络问题");
break;
case PARSE_ERROR:
onError(PARSE_ERROR, "宇宙也是有尽头的");
break;
default:
break;
}
}
@Override
public void onComplete() {
}
public abstract void onSuccess(T o);
public abstract void onError(int code, String msg);
}

View File

@ -0,0 +1,101 @@
package com.viontv.app.api;
import com.google.gson.JsonParseException;
import org.json.JSONException;
import java.io.InterruptedIOException;
import java.net.ConnectException;
import java.net.UnknownHostException;
import java.text.ParseException;
import io.reactivex.observers.DisposableObserver;
import retrofit2.HttpException;
public abstract class VTBaseObserverPrize<T> extends DisposableObserver<T> {
/**
* 解析数据失败
*/
public static final int PARSE_ERROR = 1001;
/**
* 网络问题
*/
public static final int BAD_NETWORK = 1002;
/**
* 连接错误
*/
public static final int CONNECT_ERROR = 1003;
/**
* 连接超时
*/
public static final int CONNECT_TIMEOUT = 1004;
@Override
public void onNext(T o) {
VTResultPrize model = (VTResultPrize) o;
if (model.code == 0) {
onSuccess(o);
} else {
onError(model.code, model.msg);
}
}
@Override
public void onError(Throwable e) {
if (e instanceof HttpException) {
// HTTP错误
onException(BAD_NETWORK);
} else if (e instanceof ConnectException
|| e instanceof UnknownHostException) {
// 连接错误
onException(CONNECT_ERROR);
} else if (e instanceof InterruptedIOException) {
// 连接超时
onException(CONNECT_TIMEOUT);
} else if (e instanceof JsonParseException
|| e instanceof JSONException
|| e instanceof ParseException) {
// 解析错误
onException(PARSE_ERROR);
} else {
if (e != null) {
onError(409, e.toString());
} else {
onError(407, "未知错误");
}
}
}
private void onException(int unknownError) {
switch (unknownError) {
case CONNECT_ERROR:
onError(CONNECT_ERROR, "连接错误");
break;
case CONNECT_TIMEOUT:
onError(CONNECT_TIMEOUT, "连接超时");
break;
case BAD_NETWORK:
onError(BAD_NETWORK, "网络问题");
break;
case PARSE_ERROR:
onError(PARSE_ERROR, "宇宙也是有尽头的");
break;
default:
break;
}
}
@Override
public void onComplete() {
}
public abstract void onSuccess(T o);
public abstract void onError(int code, String msg);
}

View File

@ -0,0 +1,35 @@
package com.viontv.app.api;
import java.io.IOException;
import com.viontv.app.VTApplication;
import com.viontv.app.utils.GetAndroidUniqueMark;
import com.viontv.app.utils.SharePreferenceUtils;
import com.viontv.app.utils.TimeUtils;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
public class VTHeaderInterceptor implements Interceptor {
public VTHeaderInterceptor() {
}
@Override
public Response intercept(Chain chain) throws IOException {
//封装headers
Request request = chain.request().newBuilder()
.addHeader("Content-Type", "application/json")
.addHeader("authorization", SharePreferenceUtils.getString(SharePreferenceUtils.auth,""))
.addHeader("security","false")
.addHeader("lang-key","en")
.addHeader("device-id",GetAndroidUniqueMark.getUniqueId(VTApplication.getAppContext()))
.addHeader("system-type","android")
.addHeader("time_zone", TimeUtils.getCurrentTimeZone())
.build();
return chain.proceed(request);
}
}

View File

@ -0,0 +1,32 @@
package com.viontv.app.api;
import com.viontv.app.utils.VTGsonUtils;
import java.io.Serializable;
import java.util.List;
/**
* created by wmm on 2020/9/8
*/
public class VTResult<T> implements Serializable {
public String msg;
public int code;
public T data;
public boolean isSuccessful() {
return code == 200;
}
@Override
public String toString() {
return "Result{" +
"message='" + msg + '\'' +
", code=" + code +
", data=" + VTGsonUtils.beanToJSONString(data) +
'}';
}
}

View File

@ -0,0 +1,24 @@
package com.viontv.app.api;
import java.io.Serializable;
/**
* created by wmm on 2020/9/8
*/
public class VTResult1 implements Serializable {
public String msg;
public int code;
public boolean isSuccessful() {
return code == 0;
}
@Override
public String toString() {
return "Result{" +
"message='" + msg + '\'' +
", code=" + code +
'}';
}
}

View File

@ -0,0 +1,34 @@
package com.viontv.app.api;
import com.viontv.app.utils.VTGsonUtils;
import java.io.Serializable;
import java.util.List;
/**
* created by wmm on 2020/9/8
*/
public class VTResultPrize<T> implements Serializable {
public String msg;
public int code;
public T data;
public List<String> debug;
public boolean isSuccessful() {
return code == 0;
}
@Override
public String toString() {
return "Result{" +
"message='" + msg + '\'' +
", code=" + code +
", data=" + VTGsonUtils.beanToJSONString(data) +
", debug=" + VTGsonUtils.beanToJSONString(debug) +
'}';
}
}

View File

@ -0,0 +1,23 @@
package com.viontv.app.model;
public class CateGoryItemBean {
private String category_name;
private int category_id;
public String getCategory_name() {
return category_name;
}
public void setCategory_name(String category_name) {
this.category_name = category_name;
}
public int getCategory_id() {
return category_id;
}
public void setCategory_id(int category_id) {
this.category_id = category_id;
}
}

View File

@ -0,0 +1,26 @@
package com.viontv.app.model;
import java.util.List;
public class HomeBottomListBean {
private List<ItemBean> short_play_list;
private List<ItemBean> list;
public List<ItemBean> getShort_play_list() {
return short_play_list;
}
public void setShort_play_list(List<ItemBean> short_play_list) {
this.short_play_list = short_play_list;
}
public List<ItemBean> getList() {
return list;
}
public void setList(List<ItemBean> list) {
this.list = list;
}
}

View File

@ -0,0 +1,26 @@
package com.viontv.app.model;
import java.util.List;
public class HomeNineSquareBean {
private List<ItemBean> list;
private String title;
public List<ItemBean> getList() {
return list;
}
public void setList(List<ItemBean> list) {
this.list = list;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}

View File

@ -0,0 +1,26 @@
package com.viontv.app.model;
import java.util.List;
public class HomeTopBannerBean {
private List<ItemBean> bannerData;
private HomeNineSquareBean nineSquare;
public List<ItemBean> getBannerData() {
return bannerData;
}
public void setBannerData(List<ItemBean> bannerData) {
this.bannerData = bannerData;
}
public HomeNineSquareBean getNineSquare() {
return nineSquare;
}
public void setNineSquare(HomeNineSquareBean nineSquare) {
this.nineSquare = nineSquare;
}
}

View File

@ -0,0 +1,30 @@
package com.viontv.app.model;
import java.util.List;
/**
* 首页顶部
*/
public class HomeTopBean {
private List<ItemBean> hotData;
private List<CateGoryItemBean> category;
public List<ItemBean> getHotData() {
return hotData;
}
public void setHotData(List<ItemBean> hotData) {
this.hotData = hotData;
}
public List<CateGoryItemBean> getCategory() {
return category;
}
public void setCategory(List<CateGoryItemBean> category) {
this.category = category;
}
}

View File

@ -0,0 +1,171 @@
package com.viontv.app.model;
import java.util.List;
public class ItemBean {
private int id;
private int short_id;
private int short_play_id;
private String name;
private String description;
private int process;
private String image_url;
private String horizontally_img;
private int buy_type;
private String tag_type;
private int all_coins;
private int collect_total;
private int watch_total;
private int episode_total;
private int search_click_total;
private List<String> category;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getShort_id() {
return short_id;
}
public void setShort_id(int short_id) {
this.short_id = short_id;
}
public int getShort_play_id() {
return short_play_id;
}
public void setShort_play_id(int short_play_id) {
this.short_play_id = short_play_id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getProcess() {
return process;
}
public void setProcess(int process) {
this.process = process;
}
public String getImage_url() {
return image_url;
}
public void setImage_url(String image_url) {
this.image_url = image_url;
}
public String getHorizontally_img() {
return horizontally_img;
}
public void setHorizontally_img(String horizontally_img) {
this.horizontally_img = horizontally_img;
}
public int getBuy_type() {
return buy_type;
}
public void setBuy_type(int buy_type) {
this.buy_type = buy_type;
}
public String getTag_type() {
return tag_type;
}
public void setTag_type(String tag_type) {
this.tag_type = tag_type;
}
public int getAll_coins() {
return all_coins;
}
public void setAll_coins(int all_coins) {
this.all_coins = all_coins;
}
public int getCollect_total() {
return collect_total;
}
public void setCollect_total(int collect_total) {
this.collect_total = collect_total;
}
public int getWatch_total() {
return watch_total;
}
public void setWatch_total(int watch_total) {
this.watch_total = watch_total;
}
public int getEpisode_total() {
return episode_total;
}
public void setEpisode_total(int episode_total) {
this.episode_total = episode_total;
}
public int getSearch_click_total() {
return search_click_total;
}
public void setSearch_click_total(int search_click_total) {
this.search_click_total = search_click_total;
}
public List<String> getCategory() {
return category;
}
public void setCategory(List<String> category) {
this.category = category;
}
}

View File

@ -0,0 +1,23 @@
package com.viontv.app.model;
public class RegisteredBean {
private String token;
private String customer_id;
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public String getCustomer_id() {
return customer_id;
}
public void setCustomer_id(String customer_id) {
this.customer_id = customer_id;
}
}

View File

@ -0,0 +1,16 @@
package com.viontv.app.model;
import java.util.List;
public class TabItemBean {
public List<ItemBean> banners;
public List<ItemBean> getBanners() {
return banners;
}
public void setBanners(List<ItemBean> banners) {
this.banners = banners;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,86 @@
package com.viontv.app.model;
public class VTAccountInfoBean {
public String avator;
public int coin_left_total;
public String customer_id;
public String family_name;
public String giving_name;
public int vip_end_time;
public boolean is_tourist;
public boolean is_vip;
public int send_coin_left_total;
public String getAvator() {
return avator;
}
public void setAvator(String avator) {
this.avator = avator;
}
public int getCoin_left_total() {
return coin_left_total;
}
public void setCoin_left_total(int coin_left_total) {
this.coin_left_total = coin_left_total;
}
public String getCustomer_id() {
return customer_id;
}
public void setCustomer_id(String customer_id) {
this.customer_id = customer_id;
}
public String getFamily_name() {
return family_name;
}
public void setFamily_name(String family_name) {
this.family_name = family_name;
}
public String getGiving_name() {
return giving_name;
}
public void setGiving_name(String giving_name) {
this.giving_name = giving_name;
}
public int getVip_end_time() {
return vip_end_time;
}
public void setVip_end_time(int vip_end_time) {
this.vip_end_time = vip_end_time;
}
public boolean isIs_tourist() {
return is_tourist;
}
public void setIs_tourist(boolean is_tourist) {
this.is_tourist = is_tourist;
}
public boolean isIs_vip() {
return is_vip;
}
public void setIs_vip(boolean is_vip) {
this.is_vip = is_vip;
}
public int getSend_coin_left_total() {
return send_coin_left_total;
}
public void setSend_coin_left_total(int send_coin_left_total) {
this.send_coin_left_total = send_coin_left_total;
}
}

View File

@ -0,0 +1,32 @@
package com.viontv.app.model;
public class VTBaseData<T> {
int code;
String msg;
T data;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}

View File

@ -0,0 +1,425 @@
package com.viontv.app.model;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.NonNull;
import java.util.List;
public class VTVideoDetailsBean {
public List<Episode> episodeList;
public boolean is_collect;
public ShortPlayInfo shortPlayInfo;
public VideoInfo video_info;
public static class Episode implements Parcelable {
int coins;
int episode;
int id;
boolean is_lock;
int is_vip;
int short_play_id;
String video_url;
int vip_coins;
public int getVip_coins() {
return vip_coins;
}
public void setVip_coins(int vip_coins) {
this.vip_coins = vip_coins;
}
public String getVideo_url() {
return video_url;
}
public void setVideo_url(String video_url) {
this.video_url = video_url;
}
public int getShort_play_id() {
return short_play_id;
}
public void setShort_play_id(int short_play_id) {
this.short_play_id = short_play_id;
}
public int getIs_vip() {
return is_vip;
}
public void setIs_vip(int is_vip) {
this.is_vip = is_vip;
}
public boolean isIs_lock() {
return is_lock;
}
public void setIs_lock(boolean is_lock) {
this.is_lock = is_lock;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getEpisode() {
return episode;
}
public void setEpisode(int episode) {
this.episode = episode;
}
public int getCoins() {
return coins;
}
public void setCoins(int coins) {
this.coins = coins;
}
protected Episode(Parcel in) {
coins = in.readInt();
episode = in.readInt();
id = in.readInt();
is_lock = in.readByte() != 0;
is_vip = in.readInt();
short_play_id = in.readInt();
video_url = in.readString();
vip_coins = in.readInt();
}
public final Creator<Episode> CREATOR = new Creator<Episode>() {
@Override
public Episode createFromParcel(Parcel in) {
return new Episode(in);
}
@Override
public Episode[] newArray(int size) {
return new Episode[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(coins);
dest.writeInt(episode);
dest.writeInt(id);
dest.writeByte((byte) (is_lock ? 1 : 0));
dest.writeInt(is_vip);
dest.writeInt(short_play_id);
dest.writeString(video_url);
dest.writeInt(vip_coins);
}
}
public static class ShortPlayInfo implements Parcelable {
int all_coins;
int buy_type;
int collect_total;
String description;
int episode_total;
int id;
String image_url;
boolean is_collect;
String name;
int process;
int short_id;
int watch_total;
public int getAll_coins() {
return all_coins;
}
public void setAll_coins(int all_coins) {
this.all_coins = all_coins;
}
public int getBuy_type() {
return buy_type;
}
public void setBuy_type(int buy_type) {
this.buy_type = buy_type;
}
public int getCollect_total() {
return collect_total;
}
public void setCollect_total(int collect_total) {
this.collect_total = collect_total;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getEpisode_total() {
return episode_total;
}
public void setEpisode_total(int episode_total) {
this.episode_total = episode_total;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getImage_url() {
return image_url;
}
public void setImage_url(String image_url) {
this.image_url = image_url;
}
public boolean isIs_collect() {
return is_collect;
}
public void setIs_collect(boolean is_collect) {
this.is_collect = is_collect;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getProcess() {
return process;
}
public void setProcess(int process) {
this.process = process;
}
public int getShort_id() {
return short_id;
}
public void setShort_id(int short_id) {
this.short_id = short_id;
}
public int getWatch_total() {
return watch_total;
}
public void setWatch_total(int watch_total) {
this.watch_total = watch_total;
}
protected ShortPlayInfo(Parcel in) {
all_coins = in.readInt();
buy_type = in.readInt();
collect_total = in.readInt();
description = in.readString();
episode_total = in.readInt();
id = in.readInt();
image_url = in.readString();
is_collect = in.readByte() != 0;
name = in.readString();
process = in.readInt();
short_id = in.readInt();
watch_total = in.readInt();
}
public static final Creator<ShortPlayInfo> CREATOR = new Creator<ShortPlayInfo>() {
@Override
public ShortPlayInfo createFromParcel(Parcel in) {
return new ShortPlayInfo(in);
}
@Override
public ShortPlayInfo[] newArray(int size) {
return new ShortPlayInfo[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(all_coins);
dest.writeInt(buy_type);
dest.writeInt(collect_total);
dest.writeString(description);
dest.writeInt(episode_total);
dest.writeInt(id);
dest.writeString(image_url);
dest.writeByte((byte) (is_collect ? 1 : 0));
dest.writeString(name);
dest.writeInt(process);
dest.writeInt(short_id);
dest.writeInt(watch_total);
}
}
public static class VideoInfo implements Parcelable{
int coins;
int episode;
int id;
int is_vip;
int short_id;
int short_play_id;
int short_play_video_id;
String video_url;
int vip_coins;
public int getCoins() {
return coins;
}
public void setCoins(int coins) {
this.coins = coins;
}
public int getEpisode() {
return episode;
}
public void setEpisode(int episode) {
this.episode = episode;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getIs_vip() {
return is_vip;
}
public void setIs_vip(int is_vip) {
this.is_vip = is_vip;
}
public int getShort_id() {
return short_id;
}
public void setShort_id(int short_id) {
this.short_id = short_id;
}
public int getShort_play_id() {
return short_play_id;
}
public void setShort_play_id(int short_play_id) {
this.short_play_id = short_play_id;
}
public int getShort_play_video_id() {
return short_play_video_id;
}
public void setShort_play_video_id(int short_play_video_id) {
this.short_play_video_id = short_play_video_id;
}
public String getVideo_url() {
return video_url;
}
public void setVideo_url(String video_url) {
this.video_url = video_url;
}
public int getVip_coins() {
return vip_coins;
}
public void setVip_coins(int vip_coins) {
this.vip_coins = vip_coins;
}
protected VideoInfo(Parcel in) {
coins = in.readInt();
episode = in.readInt();
id = in.readInt();
is_vip = in.readInt();
short_id = in.readInt();
short_play_id = in.readInt();
short_play_video_id = in.readInt();
video_url = in.readString();
vip_coins = in.readInt();
}
public static final Creator<VideoInfo> CREATOR = new Creator<VideoInfo>() {
@Override
public VideoInfo createFromParcel(Parcel in) {
return new VideoInfo(in);
}
@Override
public VideoInfo[] newArray(int size) {
return new VideoInfo[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(coins);
dest.writeInt(episode);
dest.writeInt(id);
dest.writeInt(is_vip);
dest.writeInt(short_id);
dest.writeInt(short_play_id);
dest.writeInt(short_play_video_id);
dest.writeString(video_url);
dest.writeInt(vip_coins);
}
}
}

View File

@ -0,0 +1,138 @@
package com.viontv.app.ui.activity;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.AppCompatTextView;
import androidx.fragment.app.Fragment;
import android.os.Bundle;
import android.view.View;
import com.viontv.app.R;
import com.viontv.app.databinding.ActivityMainVtBinding;
import com.viontv.app.ui.activity.basic.VTCommonActivity;
import com.viontv.app.ui.activity.explore.VTExploreFragment;
import com.viontv.app.ui.activity.home.VTHomeFragment;
import com.viontv.app.ui.activity.me.VTMeFragment;
import com.viontv.app.ui.activity.mylist.VTMyListFragment;
import com.viontv.app.ui.adapter.FragmentAdapter;
import java.util.ArrayList;
import java.util.List;
public class VTMainActivity extends VTCommonActivity<ActivityMainVtBinding> implements View.OnClickListener {
private static final int START_INDEX = 0;
private View mCurrentTab;
private VTHomeFragment VTHomeFragment;
private VTExploreFragment VTExploreFragment;
private VTMyListFragment VTMyListFragment;
private VTMeFragment VTMeFragment;
ActivityMainVtBinding binding;
private FragmentAdapter fragmentAdapter;
@Override
public void init() {
getWindow().setNavigationBarColor(getResources().getColor(android.R.color.black));
binding = ActivityMainVtBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
}
@Override
public void initView() {
List<Fragment> fragments = new ArrayList<>();
VTHomeFragment = VTHomeFragment.newInstance();
VTExploreFragment = VTExploreFragment.newInstance();
VTMyListFragment = VTMyListFragment.newInstance();
VTMeFragment = VTMeFragment.newInstance();
fragments.add(VTHomeFragment);
fragments.add(VTExploreFragment);
fragments.add(VTMyListFragment);
fragments.add(VTMeFragment);
fragmentAdapter = new FragmentAdapter(this);
fragmentAdapter.setFragmentList(fragments);
binding.container.setUserInputEnabled(false);
binding.container.setAdapter(fragmentAdapter);
binding.container.setCurrentItem(START_INDEX, false);
binding.container.setOffscreenPageLimit(fragments.size());
binding.tvVtMainHome.setOnClickListener(this);
binding.tvVtMainExplore.setOnClickListener(this);
binding.tvVtMainMylist.setOnClickListener(this);
binding.tvVtMainMe.setOnClickListener(this);
mCurrentTab = binding.tvVtMainHome;
resetTabCurrent();
}
@Override
public void logic() {
}
private void resetTabStyle() {
binding.tvVtMainHome.setTextColor(
getResources().getColor(R.color.color_d2d2d2));
binding.tvVtMainHome.setCompoundDrawablesWithIntrinsicBounds(
null, getResources().getDrawable(R.mipmap.iv_main_tab_home_default), null, null);
binding.tvVtMainExplore.setTextColor(getResources().getColor(R.color.color_d2d2d2));
binding.tvVtMainExplore.setCompoundDrawablesWithIntrinsicBounds(
null, getResources().getDrawable(R.mipmap.iv_main_tab_explore_default), null, null);
binding.tvVtMainMylist.setTextColor(getResources().getColor(R.color.color_d2d2d2));
binding.tvVtMainMylist.setCompoundDrawablesWithIntrinsicBounds(
null, getResources().getDrawable(R.mipmap.iv_main_tab_mylist_default), null, null);
binding.tvVtMainMe.setTextColor(getResources().getColor(R.color.color_d2d2d2));
binding.tvVtMainMe.setCompoundDrawablesWithIntrinsicBounds(
null, getResources().getDrawable(R.mipmap.iv_main_tab_me_default), null, null);
}
private void resetTabCurrent() {
if (mCurrentTab == binding.tvVtMainHome) {
setClickItem(0, binding.tvVtMainHome, R.mipmap.iv_main_tab_home_click);
}
if (mCurrentTab == binding.tvVtMainExplore) {
setClickItem(1, binding.tvVtMainExplore, R.mipmap.iv_main_tab_explore_click);
}
if (mCurrentTab == binding.tvVtMainMylist) {
setClickItem(2, binding.tvVtMainMylist, R.mipmap.iv_main_tab_mylist_click);
}
if (mCurrentTab == binding.tvVtMainMe) {
setClickItem(3, binding.tvVtMainMe, R.mipmap.iv_main_tab_me_click);
}
}
public void setClickItem(int index, AppCompatTextView textView, int resource) {
binding.container.setCurrentItem(index, false);
textView.setTextColor(
getResources().getColor(R.color.color_f564b6));
textView.setCompoundDrawablesWithIntrinsicBounds(
null, getResources().getDrawable(resource), null, null);
}
@Override
public void onClick(View v) {
if (mCurrentTab != null && mCurrentTab == v) {
return;
}
resetTabStyle();
mCurrentTab = v;
resetTabCurrent();
}
}

View File

@ -0,0 +1,43 @@
package com.viontv.app.ui.activity.basic;
public class VTBaseEventBus<T> {
private final String code;
private final T data;
public VTBaseEventBus(String code, T data) {
this.code = code;
this.data = data;
}
public String getCode() {
return code;
}
public T getData() {
return data;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
VTBaseEventBus<?> that = (VTBaseEventBus<?>) o;
if (code != null ? !code.equals(that.code) : that.code != null) return false;
return data != null ? data.equals(that.data) : that.data == null;
}
@Override
public int hashCode() {
int result = code != null ? code.hashCode() : 0;
result = 31 * result + (data != null ? data.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "BaseEventBus{" +
"code='" + code + '\'' +
", data=" + data +
'}';
}
}

View File

@ -0,0 +1,67 @@
package com.viontv.app.ui.activity.basic;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.view.WindowManager;
import android.widget.EditText;
import android.view.inputmethod.InputMethodManager;
import com.viontv.app.utils.VTStatusBarUtils;
public abstract class VTCommonActivity<T> extends AppCompatActivity {
// 定义一个泛型类型的成员变量 _viewBinding初始值为 null
public T viewBinding;
// 定义一个受保护的 getter 方法 viewBinding用于获取 _viewBinding 的值
public T getViewBinding() {
return viewBinding;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 调用 HibitStatusBarTools 类的 pageDarkMode 方法设置页面为深色模式
VTStatusBarUtils.pageDarkMode(this, true);
// 设置窗口标志防止屏幕内容被截屏或录制
getWindow().setFlags(
WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE
);
// 设置活动的屏幕方向为竖屏
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
// 调用抽象方法 initinitView logic
init();
initView();
logic();
}
// 定义抽象方法 init具体实现由子类完成
public abstract void init();
// 定义抽象方法 initView具体实现由子类完成
public abstract void initView();
// 定义抽象方法 logic具体实现由子类完成
public abstract void logic();
// 定义方法 showKeyBord用于显示软键盘
public void showKeyBord(EditText mEditText, Context mContext) {
// 获取输入法管理器
InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
// 显示软键盘
imm.showSoftInput(mEditText, InputMethodManager.SHOW_FORCED);
// 切换软键盘的显示状态
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);
}
// 定义方法 hideKeyBord用于隐藏软键盘
public void hideKeyBord(EditText mEditText, Context mContext) {
// 获取输入法管理器
InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
// 隐藏软键盘
imm.hideSoftInputFromWindow(mEditText.getWindowToken(), 0);
}
}

View File

@ -0,0 +1,51 @@
package com.viontv.app.ui.activity.basic;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import androidx.fragment.app.Fragment;
// 定义一个抽象泛型类 HibitCommonFragment继承自 Fragment
public abstract class VTCommonFragment<T> extends Fragment {
// 定义一个泛型类型的成员变量 _viewBinding初始值为 null
private T _viewBinding;
// 定义一个受保护的 getter 方法 viewBinding用于获取 _viewBinding 的值
protected T getViewBinding() {
return _viewBinding;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// 调用抽象方法 initView logic
initView();
logic();
}
// 定义抽象方法 initView具体实现由子类完成
public abstract void initView();
// 定义抽象方法 logic具体实现由子类完成
public abstract void logic();
// 定义方法 showKeyBord用于显示软键盘
public void showKeyBord(EditText mEditText, Context mContext) {
// 获取输入法管理器
InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
// 显示软键盘
imm.showSoftInput(mEditText, InputMethodManager.SHOW_FORCED);
// 切换软键盘的显示状态
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);
}
// 定义方法 hideKeyBord用于隐藏软键盘
public void hideKeyBord(EditText mEditText, Context mContext) {
// 获取输入法管理器
InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
// 隐藏软键盘
imm.hideSoftInputFromWindow(mEditText.getWindowToken(), 0);
}
}

View File

@ -0,0 +1,41 @@
package com.viontv.app.ui.activity.explore;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import com.viontv.app.databinding.FragmentMainVtBinding;
import com.viontv.app.ui.activity.home.MainViewModel;
public class VTExploreFragment extends Fragment {
private MainViewModel mViewModel;
private FragmentMainVtBinding binding;
public static VTExploreFragment newInstance() {
return new VTExploreFragment();
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mViewModel = new ViewModelProvider(this).get(MainViewModel.class);
// TODO: Use the ViewModel
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
binding = FragmentMainVtBinding.inflate(inflater);
return binding.getRoot();
}
}

View File

@ -0,0 +1,7 @@
package com.viontv.app.ui.activity.home;
import androidx.lifecycle.ViewModel;
public class MainViewModel extends ViewModel {
// TODO: Implement the ViewModel
}

View File

@ -0,0 +1,131 @@
package com.viontv.app.ui.activity.home;
import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.ViewModelProvider;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.google.android.material.tabs.TabLayoutMediator;
import com.viontv.app.R;
import com.viontv.app.api.VTApi;
import com.viontv.app.api.VTBaseObserver;
import com.viontv.app.api.VTResult;
import com.viontv.app.databinding.FragmentMainVtBinding;
import com.viontv.app.model.CateGoryItemBean;
import com.viontv.app.model.HomeTopBean;
import java.util.ArrayList;
import java.util.List;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
public class VTHomeFragment extends Fragment {
private com.viontv.app.ui.activity.home.MainViewModel mViewModel;
private FragmentMainVtBinding binding;
private ArrayList<String> titles;
private List<Fragment> listFragment;
public static VTHomeFragment newInstance() {
return new VTHomeFragment();
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mViewModel = new ViewModelProvider(this).get(com.viontv.app.ui.activity.home.MainViewModel.class);
// TODO: Use the ViewModel
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
binding = FragmentMainVtBinding.inflate(inflater);
return binding.getRoot();
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
getTopTitles();
}
private void getTopTitles() {
VTApi.getInstance().homeTop()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new VTBaseObserver<VTResult<HomeTopBean>>() {
@Override
public void onSuccess(VTResult<HomeTopBean> feedbackResp) {
List<CateGoryItemBean> itemBeans = feedbackResp.data.getCategory();
tabShow(itemBeans);
binding.tvHomeSearch.setHint(feedbackResp.data.getHotData().get(0).getName());
}
@Override
public void onError(int code, String msg) {
}
});
}
private void tabShow(List<CateGoryItemBean> itemBeans) {
titles = new ArrayList<>(itemBeans.size() + 2);
titles.add(getString(R.string.tab_home_hot));
titles.add(getString(R.string.tab_home_top10));
listFragment = new ArrayList<>();
listFragment.add(VTHotFragment.newInstance());
listFragment.add(VTTopFragment.newInstance());
for (CateGoryItemBean itemBean:itemBeans){
titles.add(itemBean.getCategory_name());
listFragment.add(VTTabItemFragment.newInstance(itemBean.getCategory_id()));
}
CommunityAdapter adapter = new CommunityAdapter(getActivity(), titles, listFragment);
binding.viewpager.setAdapter(adapter);
//把TabLayout选项卡布局和ViewPager2绑定在一起特别说明一下下面这行代码是官方给的特别好使
new TabLayoutMediator(binding.tablayout, binding.viewpager, (tab, position) -> tab.setText(titles.get(position))).attach();
}
public class CommunityAdapter extends FragmentStateAdapter {
private ArrayList<String> listTitle;
private List<Fragment> listFragment;
public CommunityAdapter(@NonNull FragmentActivity fragmentActivity, ArrayList<String> listTitle, List<Fragment> listFragment) {
super(fragmentActivity);
this.listTitle = listTitle;
this.listFragment = listFragment;
}
@NonNull
@Override
public Fragment createFragment(int position) {
return listFragment.get(position);
}
@Override
public int getItemCount() {
return listFragment.size();
}
}
}

View File

@ -0,0 +1,223 @@
package com.viontv.app.ui.activity.home;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.viontv.app.api.VTApi;
import com.viontv.app.api.VTBaseObserver;
import com.viontv.app.api.VTResult;
import com.viontv.app.databinding.FragmentHotVtBinding;
import com.viontv.app.databinding.ItemHomeExploreVtBinding;
import com.viontv.app.databinding.ItemHotSquareVtBinding;
import com.viontv.app.model.HomeBottomListBean;
import com.viontv.app.model.HomeNineSquareBean;
import com.viontv.app.model.HomeTopBannerBean;
import com.viontv.app.model.ItemBean;
import com.viontv.app.ui.adapter.BannerHomeAdapter;
import com.viontv.app.ui.adapter.CommonAdapter;
import com.viontv.app.ui.adapter.HotBottomListAdapter;
import com.viontv.app.ui.adapter.NineSquareAdapter;
import com.viontv.app.utils.IntentUtils;
import com.youth.banner.listener.OnBannerListener;
import java.util.List;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
public class VTHotFragment extends Fragment {
private MainViewModel mViewModel;
private FragmentHotVtBinding binding;
private int currentPage = 1;
HotBottomListAdapter adapter;
LinearLayoutManager layoutManager;
public static VTHotFragment newInstance() {
return new VTHotFragment();
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mViewModel = new ViewModelProvider(this).get(MainViewModel.class);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
binding = FragmentHotVtBinding.inflate(inflater);
return binding.getRoot();
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
initShow();
}
public void initShow() {
binding.banner.addBannerLifecycleObserver(this);
initBannerAndSquare();
initHomeBottom();
binding.recyclerviewGenres.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
}
});
}
public void initBannerAndSquare() {
VTApi.getInstance().bannersquare()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new VTBaseObserver<VTResult<HomeTopBannerBean>>() {
@Override
public void onSuccess(VTResult<HomeTopBannerBean> feedbackResp) {
initBanner(feedbackResp.data.getBannerData());
initSquareTop(feedbackResp.data.getNineSquare());
}
@Override
public void onError(int code, String msg) {
}
});
}
private final int LOAD_MORE_DIFF = 9;
public void initHomeBottom() {
layoutManager = new LinearLayoutManager(getActivity());
binding.recyclerviewGenres.setLayoutManager(layoutManager);
adapter = new HotBottomListAdapter(getActivity(), ItemHomeExploreVtBinding.class);
adapter.setItemClickListener((data, holder) -> {
IntentUtils.startPlayerDetails(getActivity(), data.getShort_play_id(), 0);
});
binding.recyclerviewGenres.setAdapter(adapter);
binding.recyclerviewGenres.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
int position = layoutManager.findLastCompletelyVisibleItemPosition();
int position2 = layoutManager.findLastVisibleItemPosition();
Log.i("Home+++++++++++++++", "position==" + position);
Log.i("Home+++++++++++++++", "position2==" + position2);
if (position == adapter.getItemCount() - 1) {
Log.i("Home+++++++++++++++", "page++++");
currentPage++;
getBottomData();
}
// if (adapter.getItemCount() < position + LOAD_MORE_DIFF
// && adapter.getItemCount() > 0) {
// Log.i("Home+++++++++++++++", "page++++");
// currentPage++;
// getBottomData();
// }
}
}
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
}
});
currentPage = 1;
getBottomData();
}
public void getBottomData() {
VTApi.getInstance().newShortPlay(currentPage, 10)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new VTBaseObserver<VTResult<HomeBottomListBean>>() {
@Override
public void onSuccess(VTResult<HomeBottomListBean> feedbackResp) {
if (currentPage == 1) {
adapter.addDataList(feedbackResp.data.getShort_play_list(), true);
} else {
adapter.addDataList(feedbackResp.data.getShort_play_list(), false);
}
}
@Override
public void onError(int code, String msg) {
}
});
}
public void initBanner(List<ItemBean> itemBeans) {
binding.banner.setAdapter(new BannerHomeAdapter(itemBeans)).
setCurrentItem(0, true)
.addBannerLifecycleObserver(this)
.setOnBannerListener((data, position) -> IntentUtils.startPlayerDetails(getActivity(), itemBeans.get(position).getShort_play_id(), 0))
.isAutoLoop(true);
binding.banner.start();
}
/**
* 顶部九宫格
*/
public void initSquareTop(HomeNineSquareBean homeNineSquareBean) {
binding.trendingTv.setText(homeNineSquareBean.getTitle());
binding.recyclerviewTrending.setLayoutManager(new GridLayoutManager(getActivity(), 3));
NineSquareAdapter adapter = new NineSquareAdapter(getActivity(), ItemHotSquareVtBinding.class);
adapter.setItemClickListener((data, holder) -> {
IntentUtils.startPlayerDetails(getActivity(), data.getShort_play_id(), 0);
});
adapter.addDataList(homeNineSquareBean.getList(), true);
binding.recyclerviewTrending.setAdapter(adapter);
}
@Override
public void onStop() {
super.onStop();
binding.banner.stop();
}
@Override
public void onDestroy() {
super.onDestroy();
binding.banner.destroy();
}
}

View File

@ -0,0 +1,214 @@
package com.viontv.app.ui.activity.home;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.viontv.app.api.VTApi;
import com.viontv.app.api.VTBaseObserver;
import com.viontv.app.api.VTResult;
import com.viontv.app.databinding.FragmentCategoryItemBinding;
import com.viontv.app.databinding.FragmentHotVtBinding;
import com.viontv.app.databinding.FragmentTopVtBinding;
import com.viontv.app.databinding.ItemHomeExploreVtBinding;
import com.viontv.app.databinding.ItemHomeTablistVtBinding;
import com.viontv.app.databinding.ItemHotSquareVtBinding;
import com.viontv.app.model.HomeBottomListBean;
import com.viontv.app.model.HomeNineSquareBean;
import com.viontv.app.model.HomeTopBannerBean;
import com.viontv.app.model.ItemBean;
import com.viontv.app.model.TabItemBean;
import com.viontv.app.ui.adapter.BannerHomeAdapter;
import com.viontv.app.ui.adapter.HotBottomListAdapter;
import com.viontv.app.ui.adapter.NineSquareAdapter;
import com.viontv.app.ui.adapter.TabItemListAdapter;
import com.viontv.app.utils.IntentUtils;
import java.util.List;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
public class VTTabItemFragment extends Fragment {
private MainViewModel mViewModel;
private FragmentCategoryItemBinding binding;
private int currentPage = 1;
TabItemListAdapter adapter;
LinearLayoutManager layoutManager;
private int categoryId;
public static VTTabItemFragment newInstance(int categoryId) {
Bundle bundle = new Bundle();
bundle.putInt("categoryId", categoryId);
VTTabItemFragment view = new VTTabItemFragment();
view.setArguments(bundle);
return view;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mViewModel = new ViewModelProvider(this).get(MainViewModel.class);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
binding = FragmentCategoryItemBinding.inflate(inflater);
categoryId = getArguments().getInt("categoryId");
return binding.getRoot();
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
initShow();
}
public void initShow() {
binding.banner.addBannerLifecycleObserver(this);
initBannerData();
initGridList();
binding.recyclerviewGrid.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
}
});
}
public void initBannerData() {
VTApi.getInstance().getTabItemBanner(String.valueOf(categoryId))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new VTBaseObserver<VTResult<TabItemBean>>() {
@Override
public void onSuccess(VTResult<TabItemBean> feedbackResp) {
initBanner(feedbackResp.data.getBanners());
}
@Override
public void onError(int code, String msg) {
}
});
}
private final int LOAD_MORE_DIFF = 9;
public void initGridList() {
layoutManager = new GridLayoutManager(getActivity(), 2);
binding.recyclerviewGrid.setLayoutManager(layoutManager);
adapter = new TabItemListAdapter(getActivity(), ItemHomeTablistVtBinding.class);
adapter.setItemClickListener((data, holder) -> {
IntentUtils.startPlayerDetails(getActivity(), data.getShort_play_id(), 0);
});
binding.recyclerviewGrid.setAdapter(adapter);
binding.recyclerviewGrid.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
int position = layoutManager.findLastCompletelyVisibleItemPosition();
int position2 = layoutManager.findLastVisibleItemPosition();
Log.i("Home+++++++++++++++", "position==" + position);
Log.i("Home+++++++++++++++", "position2==" + position2);
if (position == adapter.getItemCount() - 1) {
Log.i("Home+++++++++++++++", "page++++");
currentPage++;
getBottomData();
}
// if (adapter.getItemCount() < position + LOAD_MORE_DIFF
// && adapter.getItemCount() > 0) {
// Log.i("Home+++++++++++++++", "page++++");
// currentPage++;
// getBottomData();
// }
}
}
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
}
});
currentPage = 1;
getBottomData();
}
public void getBottomData() {
VTApi.getInstance().getVideoList(String.valueOf(categoryId), currentPage, 10, "")
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new VTBaseObserver<VTResult<HomeBottomListBean>>() {
@Override
public void onSuccess(VTResult<HomeBottomListBean> feedbackResp) {
if (currentPage == 1) {
adapter.addDataList(feedbackResp.data.getList(), true);
} else {
adapter.addDataList(feedbackResp.data.getList(), false);
}
}
@Override
public void onError(int code, String msg) {
}
});
}
public void initBanner(List<ItemBean> itemBeans) {
binding.banner.setAdapter(new BannerHomeAdapter(itemBeans)).
setCurrentItem(0, true)
.addBannerLifecycleObserver(this)
.setOnBannerListener((data, position) -> IntentUtils.startPlayerDetails(getActivity(), itemBeans.get(position).getShort_play_id(), 0))
.isAutoLoop(true);
binding.banner.start();
}
@Override
public void onStop() {
super.onStop();
binding.banner.stop();
}
@Override
public void onDestroy() {
super.onDestroy();
binding.banner.destroy();
}
}

View File

@ -0,0 +1,93 @@
package com.viontv.app.ui.activity.home;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
import com.viontv.app.api.VTApi;
import com.viontv.app.api.VTApiService;
import com.viontv.app.api.VTBaseObserver;
import com.viontv.app.api.VTResult;
import com.viontv.app.databinding.FragmentTopVtBinding;
import com.viontv.app.databinding.ItemHomeExploreVtBinding;
import com.viontv.app.model.HomeBottomListBean;
import com.viontv.app.ui.adapter.Top10ListAdapter;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
public class VTTopFragment extends Fragment {
private MainViewModel mViewModel;
private FragmentTopVtBinding binding;
Top10ListAdapter adapter;
LinearLayoutManager layoutManager;
public static VTTopFragment newInstance() {
return new VTTopFragment();
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mViewModel = new ViewModelProvider(this).get(MainViewModel.class);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
binding = FragmentTopVtBinding.inflate(inflater);
return binding.getRoot();
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
initList();
}
public void initList() {
layoutManager = new LinearLayoutManager(getActivity());
binding.rvFragmentHometop.setLayoutManager(layoutManager);
layoutManager = new LinearLayoutManager(getActivity());
binding.rvFragmentHometop.setLayoutManager(layoutManager);
adapter = new Top10ListAdapter(getActivity(), ItemHomeExploreVtBinding.class);
binding.rvFragmentHometop.setAdapter(adapter);
getTop10Data();
}
public void getTop10Data() {
VTApi.getInstance().homeTop10(VTApiService.rankTop10Type)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new VTBaseObserver<VTResult<HomeBottomListBean>>() {
@Override
public void onSuccess(VTResult<HomeBottomListBean> feedbackResp) {
adapter.addDataList(feedbackResp.data.getList(), true);
}
@Override
public void onError(int code, String msg) {
}
});
}
}

View File

@ -0,0 +1,41 @@
package com.viontv.app.ui.activity.me;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import com.viontv.app.databinding.FragmentMainVtBinding;
import com.viontv.app.ui.activity.home.MainViewModel;
public class VTMeFragment extends Fragment {
private MainViewModel mViewModel;
private FragmentMainVtBinding binding;
public static VTMeFragment newInstance() {
return new VTMeFragment();
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mViewModel = new ViewModelProvider(this).get(MainViewModel.class);
// TODO: Use the ViewModel
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
binding = FragmentMainVtBinding.inflate(inflater);
return binding.getRoot();
}
}

View File

@ -0,0 +1,41 @@
package com.viontv.app.ui.activity.mylist;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import com.viontv.app.databinding.FragmentMainVtBinding;
import com.viontv.app.ui.activity.home.MainViewModel;
public class VTMyListFragment extends Fragment {
private MainViewModel mViewModel;
private FragmentMainVtBinding binding;
public static VTMyListFragment newInstance() {
return new VTMyListFragment();
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mViewModel = new ViewModelProvider(this).get(MainViewModel.class);
// TODO: Use the ViewModel
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
binding = FragmentMainVtBinding.inflate(inflater);
return binding.getRoot();
}
}

View File

@ -0,0 +1,91 @@
package com.viontv.app.ui.activity.play;
import android.app.Dialog;
import android.os.Bundle;
import android.view.Gravity;
import android.view.WindowManager;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment;
import androidx.recyclerview.widget.GridLayoutManager;
import com.viontv.app.R;
import com.viontv.app.databinding.DialogPageEpisodesSelectVtBinding;
import com.viontv.app.model.VTVideoDetailsBean;
import com.viontv.app.ui.adapter.VTEpisodesSeriesAdapter;
import com.viontv.app.utils.ToastUtils;
import com.viontv.app.utils.TranslatesUtils;
import com.viontv.app.utils.VTAppConstants;
import java.util.List;
public class VTEpisodesSelectDialogFragment extends DialogFragment {
private PageEpisodesSeriesCallBack pageEpisodesSeriesCallBack;
public void setPageEpisodesSeriesCallBack(PageEpisodesSeriesCallBack pageEpisodesSeriesCallBack) {
this.pageEpisodesSeriesCallBack = pageEpisodesSeriesCallBack;
}
public interface PageEpisodesSeriesCallBack {
void chooseEpisodesSeries(VTVideoDetailsBean.Episode bean);
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(requireActivity());
android.view.LayoutInflater inflater = requireActivity().getLayoutInflater();
android.view.View view = inflater.inflate(R.layout.dialog_page_episodes_select_vt, null);
DialogPageEpisodesSelectVtBinding bind = DialogPageEpisodesSelectVtBinding.bind(view);
VTVideoDetailsBean.ShortPlayInfo readData = getArguments().getParcelable(VTAppConstants.Constants_Page_Episodes_Series_Data_VT);
List<VTVideoDetailsBean.Episode> list = getArguments().getParcelableArrayList(VTAppConstants.Constants_Page_Episodes_Series_Data_List);
Integer currentPosition = getArguments().getInt(VTAppConstants.Constants_Page_Episodes_Series_Data_currentPosition, 0);
if (list != null && !list.isEmpty()) {
VTEpisodesSeriesAdapter hibitEpisodesSeriesAdapter = new VTEpisodesSeriesAdapter();
GridLayoutManager layoutManager = new GridLayoutManager(getContext(), 5);
bind.rvDataEpisodesSeries.setLayoutManager(layoutManager);
bind.rvDataEpisodesSeries.setAdapter(hibitEpisodesSeriesAdapter);
hibitEpisodesSeriesAdapter.submitList(list);
if (currentPosition != null) {
hibitEpisodesSeriesAdapter.setCurrentPosition(currentPosition);
}
hibitEpisodesSeriesAdapter.setOnItemClickListener((adapter, view1, position) -> {
VTVideoDetailsBean.Episode item = (VTVideoDetailsBean.Episode) adapter.getItem(position);
if (position > 0) {
VTVideoDetailsBean.Episode item1 = (VTVideoDetailsBean.Episode) adapter.getItem(position - 1);
if (item1.isIs_lock()) {
String errorMessage = TranslatesUtils.translates() != null ?
TranslatesUtils.translates().getJump_unlock_error() :
"The prequel to this series is not unlocked. Please unlock the prequel before unlocking this series";
ToastUtils.revealToast(errorMessage, 0);
dismiss();
return;
}
}
pageEpisodesSeriesCallBack.chooseEpisodesSeries(item);
dismiss();
});
}
bind.ivCloseEpisodesSeries.setOnClickListener(view12 -> dismiss());
bind.tvContentEpisodesSeries.setText(readData != null ? readData.getName() : "");
builder.setView(bind.getRoot());
Dialog dialog = builder.create();
dialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent);
android.view.Window window = dialog.getWindow();
if (window != null) {
window.getDecorView().setPadding(0, 0, 0, 0);
window.setGravity(Gravity.BOTTOM);
WindowManager.LayoutParams layoutParams = window.getAttributes();
layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
window.setAttributes(layoutParams);
}
return dialog;
}
}

View File

@ -0,0 +1,408 @@
package com.viontv.app.ui.activity.play;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import androidx.appcompat.widget.AppCompatImageView;
import androidx.appcompat.widget.AppCompatTextView;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager2.widget.ViewPager2;
import com.viontv.app.R;
import com.viontv.app.api.VTResult;
import com.viontv.app.databinding.ActivityVideoDetailsVtBinding;
import com.viontv.app.model.VTVideoDetailsBean;
import com.viontv.app.ui.activity.basic.VTBaseEventBus;
import com.viontv.app.ui.activity.basic.VTCommonActivity;
import com.viontv.app.ui.adapter.VTGooglePlayerAdapter;
import com.viontv.app.ui.view.VTGoogleExoPlayerView;
import com.viontv.app.utils.SharePreferenceUtils;
import com.viontv.app.utils.SingleClickUtils;
import com.viontv.app.utils.TimeUtils;
import com.viontv.app.utils.ToastUtils;
import com.viontv.app.utils.TranslatesUtils;
import com.viontv.app.utils.VTAppConstants;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.util.ArrayList;
public class VTVideoPlayerActivity extends VTCommonActivity<ActivityVideoDetailsVtBinding> implements
VTGooglePlayerAdapter.PlayerDetailCollection, VTEpisodesSelectDialogFragment.PageEpisodesSeriesCallBack {
private VTVideoViewModel vtViewModel;
private int episodeDetailId = 0;
private int episodevideo_id = 0;
private VTVideoDetailsBean.ShortPlayInfo shortVideoInfo = null;
private VTGooglePlayerAdapter vtGooglePlayerAdapter = null;
private int currentPosition = 0;
@Override
public void init() {
vtViewModel = new ViewModelProvider(this).get(VTVideoViewModel.class);
EventBus.getDefault().register(this);
viewBinding = ActivityVideoDetailsVtBinding.inflate(getLayoutInflater());
setContentView(viewBinding.getRoot());
episodeDetailId = getIntent().getIntExtra(VTAppConstants.Constants_Page_DetailId, 0);
episodevideo_id = getIntent().getIntExtra(VTAppConstants.Constants_Page_video_id, 0);
}
@Override
public void initView() {
viewBinding.avi.smoothToShow();
vtViewModel.getVideoDetails(episodeDetailId, episodevideo_id);
viewBinding.viewPagerHibitEpisode.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@SuppressLint("NotifyDataSetChanged")
@Override
public void onPageSelected(int position) {
super.onPageSelected(position);
currentPosition = position;
int previousPosition = vtGooglePlayerAdapter != null ? vtGooglePlayerAdapter.getCurrentEpisodePlayingPosition() : 0;
if (previousPosition != position) {
if (vtGooglePlayerAdapter.getRecyclerView() != null) {
vtGooglePlayerAdapter.getRecyclerView().post(() -> vtGooglePlayerAdapter.notifyDataSetChanged());
}
}
if (vtGooglePlayerAdapter != null) {
vtGooglePlayerAdapter.setCurrentEpisodePlayingPosition(position);
VTVideoDetailsBean.Episode item = vtGooglePlayerAdapter.getItems().get(position);
//条件判断是否弹窗
// if (item != null && item.isIs_lock() && !SharePreferenceUtils.is_Vip()) {
// VTAppConstants.isLock = true;
// viewBinding.viewLock.root.setVisibility(View.VISIBLE);
// if (TranslatesUtils.translates() != null) {
// viewBinding.viewLock.exampleTvContent.setText(
// TranslatesUtils.translates().unlocking_coins_notice.replace("##", String.valueOf(item.coins))
// );
// viewBinding.viewLock.exampleTvYes.setText(TranslatesUtils.translates().common_unlock);
// } else {
// viewBinding.viewLock.exampleTvContent.setText("Unlocking costs " + item.coins + " coins");
// }
//
// viewBinding.viewLock.exampleTvYes.setOnClickListener(v -> {
// if (HibitMMKVUtils.isTourist()) {
// startActivity(new Intent(HibitVideoEpisodeActivity.this, HibitLoginActivity.class));
// return;
// }
// if (currentPosition > 0) {
// HibitVideoDetailsBean.EpisodeItem previousItem = vtGooglePlayerAdapter.getItems().get(currentPosition - 1);
// if (previousItem != null && previousItem.is_lock) {
// if (TranslatesUtils.translates() != null) {
// HibitToastTools.revealToast(TranslatesUtils.translates().jump_unlock_error);
// } else {
// HibitToastTools.revealToast("The prequel to this series is not unlocked. Please unlock the prequel before unlocking this series");
// }
// return;
// }
// }
// int allCoin = HibitMMKVUtils.getAllCoin();
// if (allCoin >= item.coins) {
// HibitGoldShortageDialog exampleGoldShortageDialog = new HibitGoldShortageDialog(HibitVideoEpisodeActivity.this);
// AppCompatTextView tvThinkAgain = exampleGoldShortageDialog.findViewById(R.id.example_tv_think_again);
// AppCompatTextView tvYes = exampleGoldShortageDialog.findViewById(R.id.example_tv_yes);
// AppCompatTextView tvGoldCoins = exampleGoldShortageDialog.findViewById(R.id.example_tv_gold_coins);
// AppCompatTextView tv_content = exampleGoldShortageDialog.findViewById(R.id.example_tv_content);
// AppCompatTextView tvTitle = exampleGoldShortageDialog.findViewById(R.id.example_tv_title);
// tvGoldCoins.setText(String.valueOf(item.coins));
// tvThinkAgain.setOnClickListener(v1 -> exampleGoldShortageDialog.dismiss());
// if (TranslatesUtils.translates() != null) {
// tvThinkAgain.setText(TranslatesUtils.translates().try_again);
// tvYes.setText(TranslatesUtils.translates().yes);
// tvTitle.setText(TranslatesUtils.translates().tips);
// tv_content.setText(TranslatesUtils.translates().not_unlock_episodes);
// }
// tvYes.setOnClickListener(v1 -> {
// hibitHomeViewModel.buy_video(item.short_play_id, item.id);
// exampleGoldShortageDialog.dismiss();
// });
// exampleGoldShortageDialog.show();
// } else {
// HibitGoldShortageDialog exampleGoldShortageDialog = new HibitGoldShortageDialog(HibitVideoEpisodeActivity.this);
// AppCompatTextView tvThinkAgain = exampleGoldShortageDialog.findViewById(R.id.example_tv_think_again);
// AppCompatTextView tvYes = exampleGoldShortageDialog.findViewById(R.id.example_tv_yes);
// AppCompatTextView tv_content = exampleGoldShortageDialog.findViewById(R.id.example_tv_content);
// AppCompatTextView tvGoldCoins = exampleGoldShortageDialog.findViewById(R.id.example_tv_gold_coins);
// AppCompatTextView tvTitle = exampleGoldShortageDialog.findViewById(R.id.example_tv_title);
// tvGoldCoins.setText(String.valueOf(item.coins));
// if (TranslatesUtils.translates() != null) {
// tvThinkAgain.setText(TranslatesUtils.translates().try_again);
// tvYes.setText(TranslatesUtils.translates().top_up_now);
// tvTitle.setText(TranslatesUtils.translates().tips);
// tv_content.setText(TranslatesUtils.translates().coins_insufficient_and_recharge);
// } else {
// tvYes.setText("Top Up Now");
// tv_content.setText("Insufficient gold coins, please recharge to continue watching");
// }
// tvGoldCoins.setTextColor(Color.parseColor("#FF0049"));
// tvThinkAgain.setOnClickListener(v1 -> exampleGoldShortageDialog.dismiss());
// tvYes.setOnClickListener(v1 -> {
// Intent intent = new Intent(HibitVideoEpisodeActivity.this, HibitRechargeGoldActivity.class);
// intent.putExtra(VTAppConstants.Constants_Page_DetailId, item.short_play_id);
// intent.putExtra(VTAppConstants.Constants_Page_video_id, item.id);
// startActivity(intent);
// exampleGoldShortageDialog.dismiss();
// });
// exampleGoldShortageDialog.show();
// }
// });
// if (viewBinding.viewLock.root != null) {
// viewBinding.viewLock.root.post(() -> {
// if (pageGoogleExoPlayerView() != null) {
// pageGoogleExoPlayerView().suspend();
// }
// });
// }
// } else {
VTAppConstants.isLock = false;
// viewBinding.viewLock.root.setVisibility(View.INVISIBLE);
// if (vtGooglePlayerAdapter.getItems() != null && vtGooglePlayerAdapter.getItems().get(position) != null) {
// vtViewModel.createHistory(
// vtGooglePlayerAdapter.getItems().get(position).getShort_play_id(),
// vtGooglePlayerAdapter.getItems().get(position).getId()
// );
// }
// }
}
}
});
}
@Override
public void logic() {
vtViewModel.getVideoDetailsData().observe(this, new Observer<VTResult<VTVideoDetailsBean>>() {
@Override
public void onChanged(VTResult<VTVideoDetailsBean> it) {
if (it != null) {
if (it.data != null && it.data.episodeList != null && !it.data.episodeList.isEmpty()) {
vtGooglePlayerAdapter = new VTGooglePlayerAdapter();
vtGooglePlayerAdapter.setShortVideoInfo(it.data.shortPlayInfo);
vtGooglePlayerAdapter.setPlayerDetailCollection(VTVideoPlayerActivity.this);
shortVideoInfo = it.data.shortPlayInfo;
viewBinding.viewPagerHibitEpisode.setAdapter(vtGooglePlayerAdapter);
vtGooglePlayerAdapter.submitList(it.data.episodeList);
if (it.data.video_info.getEpisode() > 1) {
viewBinding.viewPagerHibitEpisode.setCurrentItem(it.data.video_info.getEpisode() - 1, false);
}
}
} else {
if (TranslatesUtils.translates() != null) {
ToastUtils.revealToast(TranslatesUtils.translates().getNetwork_error(), 0);
} else {
ToastUtils.revealToast(getString(R.string.vt_network_error_please_check_the_network), 0);
}
}
viewBinding.avi.smoothToHide();
}
});
// vtViewModel.getBuyVideoData().observe(this, it -> {
// if (it != null) {
// switch (it.data != null ? it.data.status : "") {
// case "no_play":
// ToastUtils.revealToast("No skits found",0);
// finish();
// break;
// case "not_enough":
// // startActivity(new Intent(VTVideoPlayerActivity.this, HibitRechargeGoldActivity.class));
// break;
// case "success":
// if (TranslatesUtils.translates() != null) {
// ToastUtils.revealToast(TranslatesUtils.translates().getSuccess(),0);
// }
// vtViewModel.accountDetails();
// VTAppConstants.isLock = false;
// // viewBinding.viewLock.root.setVisibility(View.INVISIBLE);
// if (vtGooglePlayerAdapter.getItems() != null && vtGooglePlayerAdapter.getItems().get(currentPosition) != null) {
// VTVideoDetailsBean.Episode get = vtGooglePlayerAdapter.getItems().get(currentPosition);
// get.setIs_lock(false);
// vtGooglePlayerAdapter.notifyItemChanged(currentPosition);
// vtViewModel.createHistory(get.getShort_play_id(), get.getId());
// }
// break;
// }
// } else {
// if (TranslatesUtils.translates() != null) {
// ToastUtils.revealToast(TranslatesUtils.translates().getNetwork_error(),0);
// } else {
// ToastUtils.revealToast(getString(R.string.vt_network_error_please_check_the_network),0);
// }
// }
// });
//
// vtViewModel.getGetVideoDetailsData().observe(this, it -> {
// if (it != null) {
// if (it.data != null && it.data.episodeList != null && !it.data.episodeList.isEmpty()) {
// vtGooglePlayerAdapter = new VTGooglePlayerAdapter();
// vtGooglePlayerAdapter.setShortVideoInfo(it.data.shortPlayInfo);
// vtGooglePlayerAdapter.setPlayerDetailCollection(this);
// shortVideoInfo = it.data.shortPlayInfo;
// viewBinding.viewPagerHibitEpisode.setAdapter(vtGooglePlayerAdapter);
// vtGooglePlayerAdapter.submitList(it.data.episodeList);
// if (it.data.video_info.episode > 1) {
// viewBinding.viewPagerHibitEpisode.setCurrentItem(it.data.video_info.episode - 1, false);
// }
// }
// } else {
// if (TranslatesUtils.translates() != null) {
// ToastUtils.revealToast(TranslatesUtils.translates().getNetwork_error(),0);
// } else {
// ToastUtils.revealToast(getString(R.string.vt_network_error_please_check_the_network),0);
// }
// }
// viewBinding.avi.smoothToHide();
// });
// vtViewModel.getCollectData().observe(this, it -> {
// if (it != null) {
// AppCompatImageView imageView = pageGoogleExoPlayerView() != null ? pageGoogleExoPlayerView().findViewById(R.id.iv_collection_controller) : null;
// AppCompatTextView textview = pageGoogleExoPlayerView() != null ? pageGoogleExoPlayerView().findViewById(R.id.tv_collection_num_controller) : null;
// if (shortVideoInfo != null) {
// shortVideoInfo.setIs_collect(true);
// shortVideoInfo.setCollect_total(shortVideoInfo.getCollect_total()+1);
// }
// if (imageView != null) {
// imageView.setImageResource(R.mipmap.iv_vt_collect_h);
// }
// if (textview != null && shortVideoInfo != null) {
// textview.setText(TimeUtils.formatNumber(shortVideoInfo.getCollect_total()));
// }
// if (vtGooglePlayerAdapter != null) {
// vtGooglePlayerAdapter.setShortVideoInfo(shortVideoInfo);
// }
// EventBus.getDefault().post(new VTBaseEventBus<>(VTAppConstants.Constants_Episodes_Series_DataExample, shortVideoInfo));
// if (TranslatesUtils.translates() != null) {
// ToastUtils.revealToast(TranslatesUtils.translates().getSuccess(),0);
// }
// } else {
// if (TranslatesUtils.translates() != null) {
// ToastUtils.revealToast(TranslatesUtils.translates().getNetwork_error(),0);
// } else {
// ToastUtils.revealToast(getString(R.string.vt_network_error_please_check_the_network),0);
// }
// }
// });
//
// vtViewModel.getCancelCollectData().observe(this, it -> {
// if (it != null) {
// AppCompatImageView imageView = pageGoogleExoPlayerView() != null ? pageGoogleExoPlayerView().findViewById(R.id.iv_collection_controller) : null;
// AppCompatTextView textview = pageGoogleExoPlayerView() != null ? pageGoogleExoPlayerView().findViewById(R.id.tv_collection_num_controller) : null;
// if (shortVideoInfo != null) {
// shortVideoInfo.setIs_collect(false);
// shortVideoInfo.setCollect_total(shortVideoInfo.getCollect_total()-1);
// }
// if (imageView != null) {
// imageView.setImageResource(R.mipmap.iv_vt_collect_n);
// }
// if (textview != null && shortVideoInfo != null) {
// textview.setText(TimeUtils.formatNumber(shortVideoInfo.getCollect_total()));
// }
// } else {
// if (TranslatesUtils.translates() != null) {
// ToastUtils.revealToast(TranslatesUtils.translates().getNetwork_error(),0);
// } else {
// ToastUtils.revealToast(getString(R.string.vt_network_error_please_check_the_network),0);
// }
// }
// });
}
// 假设 pageGoogleExoPlayerView 方法在父类或者其他地方有定义
private VTGoogleExoPlayerView pageGoogleExoPlayerView() {
RecyclerView recyclerView = (RecyclerView) viewBinding.viewPagerHibitEpisode.getChildAt(0);
VTGoogleExoPlayerView googleExoPlayerView = (VTGoogleExoPlayerView) recyclerView.getLayoutManager().findViewByPosition(currentPosition);
return googleExoPlayerView;
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEvent(String event) {
// 处理事件
if (VTAppConstants.Constants_PlayerView_MoreItemEvent == event) {
if (shortVideoInfo == null) {
return;
}
VTEpisodesSelectDialogFragment hibitEpisodesSeriesDialogFragment = new VTEpisodesSelectDialogFragment();
Bundle bundle = new Bundle();
bundle.putInt(VTAppConstants.Constants_Page_Episodes_Series_Data_currentPosition, currentPosition);
bundle.putParcelable(VTAppConstants.Constants_Page_Episodes_Series_Data_VT, shortVideoInfo);
if (vtGooglePlayerAdapter != null && vtGooglePlayerAdapter.getItems() != null) {
bundle.putParcelableArrayList(VTAppConstants.Constants_Page_Episodes_Series_Data_List, new ArrayList<>(vtGooglePlayerAdapter.getItems()));
}
hibitEpisodesSeriesDialogFragment.setPageEpisodesSeriesCallBack(this);
hibitEpisodesSeriesDialogFragment.setArguments(bundle);
hibitEpisodesSeriesDialogFragment.show(getSupportFragmentManager(), "HibitEpisodesSeriesDialog");
}
if (VTAppConstants.Constants_Google_PLAYER_STATUS_FINISH_DETAIL == event) {
if (vtGooglePlayerAdapter != null && vtGooglePlayerAdapter.getCurrentEpisodePlayingPosition()>=0 ) {
int nextPosition = vtGooglePlayerAdapter.getCurrentEpisodePlayingPosition() + 1;
vtGooglePlayerAdapter.getItems();
if (nextPosition < vtGooglePlayerAdapter.getItems().size()) {
VTVideoDetailsBean.Episode episode = vtGooglePlayerAdapter.getItems().get(nextPosition);
VTAppConstants.isLock = episode.isIs_lock();
}
if (pageGoogleExoPlayerView() != null) {
pageGoogleExoPlayerView().stop();
}
viewBinding.viewPagerHibitEpisode.setCurrentItem(nextPosition);
}
}
// if (VTAppConstants.CONSTANTS_user_refresh == event) {
// vtViewModel.accountDetails();
// }
if (VTAppConstants.Constants_RecommendPlayerView_CLOSEExample == event) {
finish();
}
}
@Override
protected void onDestroy() {
VTAppConstants.isCanPlay = false;
if(pageGoogleExoPlayerView()!=null) pageGoogleExoPlayerView().stop();
if(pageGoogleExoPlayerView()!=null) pageGoogleExoPlayerView().release();
super.onDestroy();
EventBus.getDefault().unregister(this);
}
//收藏按钮逻辑
@Override
public void collection(VTVideoDetailsBean.Episode episode) {
SingleClickUtils.singleClick(new Runnable() {
@Override
public void run() {
if (shortVideoInfo != null) {
if (shortVideoInfo.isIs_collect()) {
}
}
}
});
}
@Override
public void chooseEpisodesSeries(VTVideoDetailsBean.Episode bean) {
VTAppConstants.isLock = bean.isIs_lock();
if (pageGoogleExoPlayerView() != null) {
pageGoogleExoPlayerView().stop();
}
viewBinding.viewPagerHibitEpisode.setCurrentItem(bean.getEpisode() - 1);
}
}

View File

@ -0,0 +1,45 @@
package com.viontv.app.ui.activity.play;
import android.util.Log;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import com.viontv.app.api.VTApi;
import com.viontv.app.api.VTBaseObserver;
import com.viontv.app.api.VTResult;
import com.viontv.app.model.VTBaseData;
import com.viontv.app.model.VTVideoDetailsBean;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
public class VTVideoViewModel extends ViewModel {
private final MutableLiveData<VTResult<VTVideoDetailsBean>> getVideoDetailsLiveData = new MutableLiveData<>();
public MutableLiveData<VTResult<VTVideoDetailsBean>> getVideoDetailsData() {
return getVideoDetailsLiveData;
}
public void getVideoDetails(int short_play_id, int video_id) {
VTApi.getInstance().getVideoDetails(short_play_id, video_id)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new VTBaseObserver<VTResult<VTVideoDetailsBean>>() {
@Override
public void onSuccess(VTResult<VTVideoDetailsBean> feedbackResp) {
Log.i("tag===", feedbackResp.data.shortPlayInfo.getShort_id() + "");
getVideoDetailsLiveData.setValue(feedbackResp);
}
@Override
public void onError(int code, String msg) {
Log.i("tag===", msg + "");
}
});
}
}

View File

@ -0,0 +1,56 @@
package com.viontv.app.ui.adapter;
import android.media.Image;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewbinding.ViewBinding;
import com.bumptech.glide.Glide;
import com.bumptech.glide.RequestBuilder;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.bumptech.glide.request.RequestOptions;
import com.viontv.app.databinding.ItemBannerVtBinding;
import com.viontv.app.model.ItemBean;
import com.youth.banner.adapter.BannerAdapter;
import java.util.List;
public class BannerHomeAdapter extends BannerAdapter<ItemBean, BannerHomeAdapter.BannerHomeViewHolder> {
public BannerHomeAdapter(List<ItemBean> mData) {
super(mData);
}
@Override
public BannerHomeViewHolder onCreateHolder(ViewGroup parent, int viewType) {
ImageView imageView = new ImageView(parent.getContext());
//注意必须设置为match_parent这个是viewpager2强制要求的
imageView.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
return new BannerHomeViewHolder(imageView);
}
@Override
public void onBindView(BannerHomeViewHolder holder, ItemBean data, int position, int size) {
Glide.with(holder.itemView.getContext()).load(data.getHorizontally_img()).apply(RequestOptions.bitmapTransform(new RoundedCorners(30))).into(holder.imageView);
}
class BannerHomeViewHolder extends RecyclerView.ViewHolder {
ImageView imageView;
public BannerHomeViewHolder(@NonNull ImageView view) {
super(view);
this.imageView = view;
}
}
}

View File

@ -0,0 +1,117 @@
// Copyright (c) 2022 NetEase, Inc. All rights reserved.
// Use of this source code is governed by a MIT license that can be
// found in the LICENSE file.
package com.viontv.app.ui.adapter;
import android.annotation.SuppressLint;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewbinding.ViewBinding;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class CommonAdapter<T, R extends ViewBinding>
extends RecyclerView.Adapter<CommonAdapter.ItemViewHolder<R>> {
private static final String TAG = "QChatCommonAdapter";
private static final String NAME_METHOD_INFLATE = "inflate";
protected final List<T> dataSource = new ArrayList<>();
protected final Context context;
protected OnClickListener<T, R> clickListener;
protected Method inflateMethod;
public CommonAdapter(Context context, Class<R> viewBinding) {
this.context = context;
try {
inflateMethod =
viewBinding.getMethod(
NAME_METHOD_INFLATE, LayoutInflater.class, ViewGroup.class, boolean.class);
} catch (NoSuchMethodException e) {
throw new IllegalStateException("create adapter error", e);
}
}
@SuppressLint("NotifyDataSetChanged")
public void addDataList(List<T> data, boolean clearOld) {
if (clearOld) {
dataSource.clear();
}
if (data == null) {
return;
}
dataSource.addAll(data);
notifyDataSetChanged();
}
public void setItemClickListener(OnClickListener<T, R> listener) {
this.clickListener = listener;
}
@NonNull
@Override
@SuppressWarnings("unchecked")
public ItemViewHolder<R> onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
R binding;
try {
binding = (R) inflateMethod.invoke(null, LayoutInflater.from(context), parent, false);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new IllegalStateException("create view holder error", e);
}
return new ItemViewHolder<>(Objects.requireNonNull(binding));
}
@Override
public void onBindViewHolder(@NonNull ItemViewHolder<R> holder, int position) {
T item = getItemData(position);
holder.itemView.setOnClickListener(
v -> {
if (clickListener != null) {
clickListener.onClick(item, holder);
}
});
if (item == null) {
return;
}
onBindViewHolder(holder, position, item);
}
public void onBindViewHolder(@NonNull ItemViewHolder<R> holder, int position, T data) {
onBindViewHolder(holder.binding, position, data, holder.getBindingAdapterPosition());
}
public void onBindViewHolder(R binding, int position, T data, int bingingAdapterPosition) {}
@Override
public int getItemCount() {
return dataSource.size();
}
public T getItemData(int position) {
if (position < 0 || position >= dataSource.size()) {
return null;
}
return dataSource.get(position);
}
public static class ItemViewHolder<T extends ViewBinding> extends RecyclerView.ViewHolder {
public final T binding;
public ItemViewHolder(T binding) {
super(binding.getRoot());
this.binding = binding;
}
}
public interface OnClickListener<T, R extends ViewBinding> {
void onClick(T data, ItemViewHolder<R> holder);
}
}

View File

@ -0,0 +1,61 @@
// Copyright (c) 2022 NetEase, Inc. All rights reserved.
// Use of this source code is governed by a MIT license that can be
// found in the LICENSE file.
package com.viontv.app.ui.adapter;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.Lifecycle;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import java.util.List;
/** Fragment Adapter used in MainActivity */
public class FragmentAdapter extends FragmentStateAdapter {
private static final String TAG = FragmentAdapter.class.getSimpleName();
private List<Fragment> fragmentList;
public FragmentAdapter(@NonNull FragmentActivity fragmentActivity) {
super(fragmentActivity);
}
public FragmentAdapter(@NonNull Fragment fragment) {
super(fragment);
}
public FragmentAdapter(@NonNull FragmentManager fragmentManager, @NonNull Lifecycle lifecycle) {
super(fragmentManager, lifecycle);
}
public void setFragmentList(List<Fragment> fragmentList) {
this.fragmentList = fragmentList;
}
@NonNull
@Override
public Fragment createFragment(int position) {
// if (fragmentList == null || fragmentList.size() <= position) {
// return new Fragment();
// }
return fragmentList.get(position);
}
@Override
public int getItemCount() {
return fragmentList == null ? 0 : fragmentList.size();
}
@Override
public long getItemId(int position) {
return super.getItemId(position);
}
@Override
public int getItemViewType(int position) {
return super.getItemViewType(position);
}
}

View File

@ -0,0 +1,57 @@
// Copyright (c) 2022 NetEase, Inc. All rights reserved.
// Use of this source code is governed by a MIT license that can be
// found in the LICENSE file.
package com.viontv.app.ui.adapter;
import android.content.Context;
import android.view.View;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.request.RequestOptions;
import com.viontv.app.databinding.ItemHomeExploreVtBinding;
import com.viontv.app.databinding.ItemHotSquareVtBinding;
import com.viontv.app.model.ItemBean;
public class HotBottomListAdapter
extends CommonAdapter<ItemBean, ItemHomeExploreVtBinding> {
private Context mcontext;
public HotBottomListAdapter(
Context context, Class<ItemHomeExploreVtBinding> viewBinding) {
super(context, viewBinding);
this.mcontext = context;
}
@Override
public void onBindViewHolder(
ItemHomeExploreVtBinding binding,
int position,
ItemBean data,
int bingingAdapterPosition) {
if (data != null) {
Glide.with(mcontext)
.load(data.getImage_url())
.apply(new RequestOptions().diskCacheStrategy(DiskCacheStrategy.RESOURCE))
.into(binding.ivHotExploreItem);
binding.tvHomeExploretitleItem.setText(data.getName());
binding.tvHomeExplorecontentItem.setText(data.getDescription());
binding.tvHomeExplorecateItem1.setVisibility(View.GONE);
binding.tvHomeExplorecateItem2.setVisibility(View.GONE);
if (data.getCategory() != null && !data.getCategory().isEmpty()) {
binding.tvHomeExplorecateItem1.setVisibility(View.VISIBLE);
binding.tvHomeExplorecateItem1.setText(data.getCategory().get(0));
if(data.getCategory().size()>=2){
binding.tvHomeExplorecateItem2.setVisibility(View.VISIBLE);
binding.tvHomeExplorecateItem2.setText(data.getCategory().get(1));
}
}
}
}
}

View File

@ -0,0 +1,44 @@
// Copyright (c) 2022 NetEase, Inc. All rights reserved.
// Use of this source code is governed by a MIT license that can be
// found in the LICENSE file.
package com.viontv.app.ui.adapter;
import android.content.Context;
import android.text.TextUtils;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.request.RequestOptions;
import com.viontv.app.databinding.ItemHotSquareVtBinding;
import com.viontv.app.model.ItemBean;
import com.viontv.app.utils.IntentUtils;
public class NineSquareAdapter
extends CommonAdapter<ItemBean, ItemHotSquareVtBinding> {
private Context mcontext;
public NineSquareAdapter(
Context context, Class<ItemHotSquareVtBinding> viewBinding) {
super(context, viewBinding);
this.mcontext = context;
}
@Override
public void onBindViewHolder(
ItemHotSquareVtBinding binding,
int position,
ItemBean data,
int bingingAdapterPosition) {
if (data != null) {
Glide.with(mcontext)
.load(data.getImage_url())
.apply(new RequestOptions().diskCacheStrategy(DiskCacheStrategy.NONE))
.into(binding.ivHotSquareItem);
binding.tvHotSquareDesc.setText(data.getName());
}
}
}

View File

@ -0,0 +1,47 @@
// Copyright (c) 2022 NetEase, Inc. All rights reserved.
// Use of this source code is governed by a MIT license that can be
// found in the LICENSE file.
package com.viontv.app.ui.adapter;
import android.content.Context;
import android.view.View;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.request.RequestOptions;
import com.viontv.app.R;
import com.viontv.app.databinding.ItemHomeExploreVtBinding;
import com.viontv.app.databinding.ItemHomeTablistVtBinding;
import com.viontv.app.model.ItemBean;
public class TabItemListAdapter
extends CommonAdapter<ItemBean, ItemHomeTablistVtBinding> {
private Context mcontext;
public TabItemListAdapter(
Context context, Class<ItemHomeTablistVtBinding> viewBinding) {
super(context, viewBinding);
this.mcontext = context;
}
@Override
public void onBindViewHolder(
ItemHomeTablistVtBinding binding,
int position,
ItemBean data,
int bingingAdapterPosition) {
if (data != null) {
Glide.with(mcontext)
.load(data.getHorizontally_img())
.apply(new RequestOptions().diskCacheStrategy(DiskCacheStrategy.RESOURCE))
.into(binding.ivHometabItem);
binding.tvHometabTitleItem.setText(data.getName());
binding.tvHometabContentItem.setText(data.getDescription());
}
}
}

View File

@ -0,0 +1,74 @@
// Copyright (c) 2022 NetEase, Inc. All rights reserved.
// Use of this source code is governed by a MIT license that can be
// found in the LICENSE file.
package com.viontv.app.ui.adapter;
import android.annotation.SuppressLint;
import android.content.Context;
import android.view.View;
import androidx.constraintlayout.widget.ConstraintLayout;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.request.RequestOptions;
import com.viontv.app.databinding.ItemHomeExploreVtBinding;
import com.viontv.app.model.ItemBean;
import com.viontv.app.utils.TimeUtils;
public class Top10ListAdapter
extends CommonAdapter<ItemBean, ItemHomeExploreVtBinding> {
private Context mcontext;
public Top10ListAdapter(
Context context, Class<ItemHomeExploreVtBinding> viewBinding) {
super(context, viewBinding);
this.mcontext = context;
}
@Override
public void onBindViewHolder(
ItemHomeExploreVtBinding binding,
int position,
ItemBean data,
int bingingAdapterPosition) {
if (data != null) {
// ConstraintLayout.LayoutParams params = (ConstraintLayout.LayoutParams) binding.ivHotExploreItem.getLayoutParams();
// params.dimensionRatio ="71:100";
// binding.ivHotExploreItem.setLayoutParams(params);
// binding.ivHotExploreItem.requestLayout();
//
Glide.with(mcontext)
.load(data.getImage_url())
.apply(new RequestOptions().diskCacheStrategy(DiskCacheStrategy.RESOURCE))
.into(binding.ivHotExploreItem);
binding.layoutHomeHotcontent.setVisibility(View.VISIBLE);
binding.tvHomeExplorecontentItem.setVisibility(View.GONE);
binding.tvHomeExploretitleItem.setText(data.getName());
binding.tvHomeHotcontentItem.setText(TimeUtils.formatNumber(data.getWatch_total()));
binding.tvHomeExplorecateItem1.setVisibility(View.GONE);
binding.tvHomeExplorecateItem2.setVisibility(View.GONE);
binding.tvHotTopnumber.setVisibility(View.GONE);
if (bingingAdapterPosition < 10) {
binding.tvHotTopnumber.setVisibility(View.VISIBLE);
binding.tvHotTopnumber.setText(String.valueOf(bingingAdapterPosition + 1));
}
if (data.getCategory() != null && !data.getCategory().isEmpty()) {
binding.tvHomeExplorecateItem1.setVisibility(View.VISIBLE);
binding.tvHomeExplorecateItem1.setText(data.getCategory().get(0));
if (data.getCategory().size() >= 2) {
binding.tvHomeExplorecateItem2.setVisibility(View.VISIBLE);
binding.tvHomeExplorecateItem2.setText(data.getCategory().get(1));
}
}
}
}
}

View File

@ -0,0 +1,45 @@
package com.viontv.app.ui.adapter;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Color;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import androidx.appcompat.widget.AppCompatTextView;
import com.chad.library.adapter4.BaseQuickAdapter;
import com.chad.library.adapter4.viewholder.QuickViewHolder;
import com.viontv.app.R;
import com.viontv.app.model.VTVideoDetailsBean;
public class VTEpisodesSeriesAdapter extends BaseQuickAdapter<VTVideoDetailsBean.Episode, QuickViewHolder> {
private int currentPosition = -1;
@SuppressLint("UseCompatLoadingForDrawables")
@Override
protected void onBindViewHolder(QuickViewHolder holder, int position, VTVideoDetailsBean.Episode item) {
AppCompatTextView tvEpisodesSeries = holder.getView(R.id.tv_episodes_series);
RelativeLayout episodeBg = holder.getView(R.id.episode_bg);
tvEpisodesSeries.setText(String.valueOf(item != null ? item.getEpisode() : ""));
if (currentPosition == holder.getAdapterPosition()) {
tvEpisodesSeries.setTextColor(Color.parseColor("#FF0049"));
episodeBg.setBackground(holder.itemView.getContext().getDrawable(R.drawable.bg_vt_episodes_h));
} else {
tvEpisodesSeries.setTextColor(Color.parseColor("#999999"));
episodeBg.setBackground(holder.itemView.getContext().getDrawable(R.drawable.bg_vt_episodes));
}
holder.setVisible(R.id.iv_lock_show, item != null && item.isIs_lock());
}
@Override
public QuickViewHolder onCreateViewHolder(Context context, ViewGroup parent, int viewType) {
return new QuickViewHolder(R.layout.item_page_episodes_series_vt, parent);
}
public void setCurrentPosition(int position) {
this.currentPosition = position;
}
}

View File

@ -0,0 +1,83 @@
// Copyright (c) 2022 NetEase, Inc. All rights reserved.
// Use of this source code is governed by a MIT license that can be
// found in the LICENSE file.
package com.viontv.app.ui.adapter;
import android.content.Context;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatImageView;
import androidx.media3.ui.PlayerView;
import com.chad.library.adapter4.BaseQuickAdapter;
import com.chad.library.adapter4.viewholder.QuickViewHolder;
import com.viontv.app.R;
import com.viontv.app.databinding.ItemGoogleExoPlayerVtBinding;
import com.viontv.app.model.VTVideoDetailsBean;
import com.viontv.app.ui.view.VTGoogleExoPlayerView;
public class VTGooglePlayerAdapter
extends BaseQuickAdapter<VTVideoDetailsBean.Episode, QuickViewHolder> {
public interface PlayerDetailCollection {
void collection(VTVideoDetailsBean.Episode episode);
}
public PlayerDetailCollection playerDetailCollection;
public void setPlayerDetailCollection(PlayerDetailCollection playerDetailCollection) {
this.playerDetailCollection = playerDetailCollection;
}
public int currentEpisodePlayingPosition = 0;
public VTVideoDetailsBean.ShortPlayInfo shortVideoInfo;
public int getCurrentEpisodePlayingPosition() {
return currentEpisodePlayingPosition;
}
public void setCurrentEpisodePlayingPosition(int currentEpisodePlayingPosition) {
this.currentEpisodePlayingPosition = currentEpisodePlayingPosition;
}
public VTVideoDetailsBean.ShortPlayInfo getShortVideoInfo() {
return shortVideoInfo;
}
public void setShortVideoInfo(VTVideoDetailsBean.ShortPlayInfo shortVideoInfo) {
this.shortVideoInfo = shortVideoInfo;
}
@NonNull
@Override
protected QuickViewHolder onCreateViewHolder(@NonNull Context context, @NonNull ViewGroup viewGroup, int i) {
return new QuickViewHolder(R.layout.item_google_exo_player_vt,viewGroup);
}
@Override
protected void onBindViewHolder(@NonNull QuickViewHolder holder, int position, @Nullable VTVideoDetailsBean.Episode episode) {
VTGoogleExoPlayerView exampleDetailPlayerView = (VTGoogleExoPlayerView) holder.getView(R.id.page_google_exo_player);
PlayerView playerView = exampleDetailPlayerView.findViewById(R.id.player_view);
AppCompatImageView imageView = playerView.findViewById(R.id.iv_collection_controller);
imageView.setOnClickListener(v -> {
if (playerDetailCollection != null) {
playerDetailCollection.collection(episode);
}
});
if (position == currentEpisodePlayingPosition) {
exampleDetailPlayerView.setMedia(episode, shortVideoInfo);
} else {
exampleDetailPlayerView.stop();
}
}
}

View File

@ -0,0 +1,61 @@
package com.viontv.app.ui.view;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.ScaleAnimation;
import android.widget.FrameLayout;
import androidx.annotation.Nullable;
import com.viontv.app.R;
public class ProgressLineView extends FrameLayout {
private View loadView;
public ProgressLineView(Context context) {
super(context);
initView(context);
}
public ProgressLineView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initView(context);
}
public ProgressLineView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(context);
}
private void initView(Context mContext) {
View view = LayoutInflater.from(mContext).inflate(R.layout.layout_player_progress_line_vt, null);
loadView = view.findViewById(R.id.loadingView);
this.addView(view);
}
public void startAnimation() {
ScaleAnimation scale = new ScaleAnimation(
0.3f, 1f, 1f, 1f,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f
);
AlphaAnimation alpha = new AlphaAnimation(1f, 0.2f);
scale.setRepeatCount(-1);
alpha.setRepeatCount(-1);
AnimationSet set = new AnimationSet(true);
set.addAnimation(scale);
set.addAnimation(alpha);
set.setDuration(500);
loadView.startAnimation(set);
}
public void endAnimation() {
loadView.clearAnimation();
}
}

View File

@ -0,0 +1,362 @@
package com.viontv.app.ui.view;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.core.graphics.ColorUtils;
import com.scwang.smart.refresh.layout.api.RefreshHeader;
import com.scwang.smart.refresh.layout.api.RefreshKernel;
import com.scwang.smart.refresh.layout.api.RefreshLayout;
import com.scwang.smart.refresh.layout.constant.SpinnerStyle;
import com.scwang.smart.refresh.layout.simple.SimpleComponent;
import com.scwang.smart.refresh.layout.util.SmartUtil;
/**
* CircleRefresh
*/
public class VTBezierCircleHeader extends SimpleComponent implements RefreshHeader {
//<editor-fold desc="Field">
protected Path mPath;
protected Paint mBackPaint;
protected Paint mFrontPaint;
protected Paint mOuterPaint;
protected int mHeight;
protected float mWaveHeight;
protected float mHeadHeight;
protected float mSpringRatio;
protected float mFinishRatio;
protected float mBollY;//弹出球体的Y坐标
protected float mBollRadius;//球体半径
protected boolean mShowOuter;
protected boolean mShowBoll;//是否显示中心球体
protected boolean mShowBollTail;//是否显示球体拖拽的尾巴
protected int mRefreshStop = 90;
protected int mRefreshStart = 90;
protected boolean mOuterIsStart = true;
protected static final int TARGET_DEGREE = 270;
protected boolean mWavePulling = false;
protected RefreshKernel mKernel;
//</editor-fold>
//<editor-fold desc="View">
public VTBezierCircleHeader(Context context) {
this(context, null);
}
public VTBezierCircleHeader(Context context, AttributeSet attrs) {
super(context, attrs, 0);
mSpinnerStyle = SpinnerStyle.FixedBehind;
final View thisView = this;
thisView.setMinimumHeight(SmartUtil.dp2px(100));
mBackPaint = new Paint();
mBackPaint.setColor(0xff11bbff);
mBackPaint.setAntiAlias(true);
mFrontPaint = new Paint();
mFrontPaint.setColor(0xffffffff);
mFrontPaint.setAntiAlias(true);
mOuterPaint = new Paint();
mOuterPaint.setAntiAlias(true);
mOuterPaint.setColor(0xffffffff);
mOuterPaint.setStyle(Paint.Style.STROKE);
mOuterPaint.setStrokeWidth(SmartUtil.dp2px(2f));
mPath = new Path();
}
//</editor-fold>
//<editor-fold desc="Draw">
@Override
protected void dispatchDraw(Canvas canvas) {
final View thisView = this;
final int viewWidth = thisView.getWidth();
final int viewHeight = mHeight;//thisView.getHeight();
//noinspection EqualsBetweenInconvertibleTypes
final boolean footer = mKernel != null && (this.equals(mKernel.getRefreshLayout().getRefreshFooter()));
if (footer) {
canvas.save();
canvas.translate(0, thisView.getHeight());
canvas.scale(1, -1);
}
if (thisView.isInEditMode()) {
mShowBoll = true;
mShowOuter = true;
mHeadHeight = viewHeight;
mRefreshStop = 270;
mBollY = mHeadHeight / 2;
mBollRadius = mHeadHeight / 6;
}
drawWave(canvas, viewWidth, viewHeight);
drawSpringUp(canvas, viewWidth);
drawBoll(canvas, viewWidth);
drawOuter(canvas, viewWidth);
drawFinish(canvas, viewWidth);
if (footer) {
canvas.restore();
}
super.dispatchDraw(canvas);
}
protected void drawWave(Canvas canvas, int viewWidth, int viewHeight) {
float baseHeight = Math.min(mHeadHeight, viewHeight);
if (mWaveHeight != 0) {
mPath.reset();
mPath.lineTo(viewWidth, 0);
mPath.lineTo(viewWidth, baseHeight);
mPath.quadTo(viewWidth / 2f, baseHeight + mWaveHeight * 2, 0, baseHeight);
mPath.close();
canvas.drawPath(mPath, mBackPaint);
} else {
canvas.drawRect(0, 0, viewWidth, baseHeight, mBackPaint);
}
}
protected void drawSpringUp(Canvas canvas, int viewWidth) {
if (mSpringRatio > 0) {
float leftX = (viewWidth / 2f - 4 * mBollRadius + mSpringRatio * 3 * mBollRadius);
if (mSpringRatio < 0.9) {
mPath.reset();
mPath.moveTo(leftX, mBollY);
mPath.quadTo(viewWidth / 2f, mBollY - mBollRadius * mSpringRatio * 2,
viewWidth - leftX, mBollY);
canvas.drawPath(mPath, mFrontPaint);
} else {
canvas.drawCircle(viewWidth / 2f, mBollY, mBollRadius, mFrontPaint);
}
}
}
protected void drawBoll(Canvas canvas, int viewWidth) {
if (mShowBoll) {
canvas.drawCircle(viewWidth / 2f, mBollY, mBollRadius, mFrontPaint);
drawBollTail(canvas, viewWidth, (mHeadHeight + mWaveHeight) / mHeadHeight);
}
}
protected void drawBollTail(Canvas canvas, int viewWidth, float fraction) {
if (mShowBollTail) {
final float bottom = mHeadHeight + mWaveHeight;
final float startY = mBollY + mBollRadius * fraction / 2;
final float startX = viewWidth / 2f + (float) Math.sqrt(mBollRadius * mBollRadius * (1 - fraction * fraction / 4));
final float bezier1x = (viewWidth / 2f + (mBollRadius * 3 / 4) * (1 - fraction));
final float bezier2x = bezier1x + mBollRadius;
mPath.reset();
mPath.moveTo(startX, startY);
mPath.quadTo(bezier1x, bottom, bezier2x, bottom);
mPath.lineTo(viewWidth - bezier2x, bottom);
mPath.quadTo(viewWidth - bezier1x, bottom, viewWidth - startX, startY);
canvas.drawPath(mPath, mFrontPaint);
}
}
protected void drawOuter(Canvas canvas, int viewWidth) {
if (mShowOuter) {
float outerR = mBollRadius + mOuterPaint.getStrokeWidth() * 2;
mRefreshStart += mOuterIsStart ? 3 : 10;
mRefreshStop += mOuterIsStart ? 10 : 3;
mRefreshStart = mRefreshStart % 360;
mRefreshStop = mRefreshStop % 360;
int swipe = mRefreshStop - mRefreshStart;
swipe = swipe < 0 ? swipe + 360 : swipe;
canvas.drawArc(new RectF(viewWidth / 2f - outerR, mBollY - outerR, viewWidth / 2f + outerR, mBollY + outerR),
mRefreshStart, swipe, false, mOuterPaint);
if (swipe >= TARGET_DEGREE) {
mOuterIsStart = false;
} else if (swipe <= 10) {
mOuterIsStart = true;
}
final View thisView = this;
thisView.invalidate();
}
}
protected void drawFinish(Canvas canvas, int viewWidth) {
if (mFinishRatio > 0) {
int beforeColor = mOuterPaint.getColor();
if (mFinishRatio < 0.3) {
canvas.drawCircle(viewWidth / 2f, mBollY, mBollRadius, mFrontPaint);
int outerR = (int) (mBollRadius + mOuterPaint.getStrokeWidth() * 2 * (1+mFinishRatio / 0.3f));
int afterColor = ColorUtils.setAlphaComponent(beforeColor, (int) (0xff * (1 - mFinishRatio / 0.3f)));
mOuterPaint.setColor(afterColor);
canvas.drawArc(new RectF(viewWidth / 2f - outerR, mBollY - outerR, viewWidth / 2f + outerR, mBollY + outerR),
0, 360, false, mOuterPaint);
}
mOuterPaint.setColor(beforeColor);
if (mFinishRatio >= 0.3 && mFinishRatio < 0.7) {
float fraction = (mFinishRatio - 0.3f) / 0.4f;
mBollY = (int) (mHeadHeight / 2 + (mHeadHeight - mHeadHeight / 2) * fraction);
canvas.drawCircle(viewWidth / 2f, mBollY, mBollRadius, mFrontPaint);
if (mBollY >= mHeadHeight - mBollRadius * 2) {
mShowBollTail = true;
drawBollTail(canvas, viewWidth, fraction);
}
mShowBollTail = false;
}
if (mFinishRatio >= 0.7 && mFinishRatio <= 1) {
float fraction = (mFinishRatio - 0.7f) / 0.3f;
int leftX = (int) (viewWidth / 2f - mBollRadius - 2 * mBollRadius * fraction);
mPath.reset();
mPath.moveTo(leftX, mHeadHeight);
mPath.quadTo(viewWidth / 2f, mHeadHeight - (mBollRadius * (1 - fraction)),
viewWidth - leftX, mHeadHeight);
canvas.drawPath(mPath, mFrontPaint);
}
}
}
//</editor-fold>
//<editor-fold desc="RefreshHeader">
@Override
public void onInitialized(@NonNull RefreshKernel kernel, int height, int maxDragHeight) {
mKernel = kernel;
}
@Override
public void onMoving(boolean isDragging, float percent, int offset, int height, int maxDragHeight) {
mHeight = offset;
if (isDragging || mWavePulling) {
mWavePulling = true;
mHeadHeight = height;
mWaveHeight = Math.max(offset - height, 0) * .8f;
}
this.invalidate();
}
@Override
public void onReleased(@NonNull RefreshLayout refreshLayout, int height, int maxDragHeight) {
mWavePulling = false;
mHeadHeight = height;
mBollRadius = height / 6f;
DecelerateInterpolator interpolator = new DecelerateInterpolator();
final float reboundHeight = Math.min(mWaveHeight * 0.8f, mHeadHeight / 2);
ValueAnimator waveAnimator = ValueAnimator.ofFloat(
mWaveHeight, 0,
-(reboundHeight*1.0f),0,
-(reboundHeight*0.4f),0
);
waveAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
float speed = 0;
float springBollY;
float springRatio = 0;
int status = 0;//0 还没开始弹起 1 向上弹起 2 在弹起的最高点停住
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float curValue = (float) animation.getAnimatedValue();
if (status == 0 && curValue <= 0) {
status = 1;
speed = Math.abs(curValue - mWaveHeight);
}
if (status == 1) {
springRatio = -curValue / reboundHeight;
if (springRatio >= mSpringRatio) {
mSpringRatio = springRatio;
mBollY = mHeadHeight + curValue;
speed = Math.abs(curValue - mWaveHeight);
} else {
status = 2;
mSpringRatio = 0;
mShowBoll = true;
mShowBollTail = true;
springBollY = mBollY;
}
}
if (status == 2) {
if (mBollY > mHeadHeight / 2) {
mBollY = Math.max(mHeadHeight / 2, mBollY - speed);
float bally = animation.getAnimatedFraction() * (mHeadHeight / 2 - springBollY) + springBollY;
if (mBollY > bally) {
mBollY = bally;
}
}
}
if (mShowBollTail && curValue < mWaveHeight) {
mShowOuter = true;
mShowBollTail = false;
mOuterIsStart = true;
mRefreshStart = 90;
mRefreshStop = 90;
}
if (!mWavePulling) {
mWaveHeight = curValue;
final View thisView = VTBezierCircleHeader.this;
thisView.invalidate();
}
}
});
waveAnimator.setInterpolator(interpolator);
waveAnimator.setDuration(1000);
waveAnimator.start();
}
@Override
public int onFinish(@NonNull RefreshLayout layout, boolean success) {
mShowBoll = false;
mShowOuter = false;
final int DURATION_FINISH = 800; //动画时长
ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
final View thisView = VTBezierCircleHeader.this;
mFinishRatio = (float) animation.getAnimatedValue();
thisView.invalidate();
}
});
animator.setInterpolator(new AccelerateInterpolator());
animator.setDuration(DURATION_FINISH);
animator.start();
return DURATION_FINISH;
}
/**
* @param colors 对应Xml中配置的 srlPrimaryColor srlAccentColor
* @deprecated 只由框架调用
* 使用者使用 {@link RefreshLayout#setPrimaryColorsId(int...)}
*/
@Override
@Deprecated
public void setPrimaryColors(@ColorInt int ... colors) {
if (colors.length > 0) {
mBackPaint.setColor(colors[0]);
if (colors.length > 1) {
mFrontPaint.setColor(colors[1]);
mOuterPaint.setColor(colors[1]);
}
}
}
// @NonNull
// @Override
// public SpinnerStyle getSpinnerStyle() {
// return SpinnerStyle.Scale;
// }
//</editor-fold>
}

View File

@ -0,0 +1,247 @@
package com.viontv.app.ui.view;
import android.content.Context;
import android.net.Uri;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import androidx.appcompat.widget.AppCompatImageView;
import androidx.appcompat.widget.AppCompatSeekBar;
import androidx.appcompat.widget.AppCompatTextView;
import androidx.media3.common.C;
import androidx.media3.common.MediaItem;
import androidx.media3.common.PlaybackException;
import androidx.media3.common.Player;
import androidx.media3.exoplayer.ExoPlayer;
import com.bumptech.glide.Glide;
import com.viontv.app.R;
import com.viontv.app.databinding.LayoutVideoplayVtBinding;
import com.viontv.app.model.VTVideoDetailsBean;
import com.viontv.app.utils.ToastUtils;
import com.viontv.app.utils.TranslatesUtils;
import com.viontv.app.utils.VTAppConstants;
import org.greenrobot.eventbus.EventBus;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
public class VTGoogleExoPlayerView extends FrameLayout {
private ExoPlayer player;
// private Job progressJob; //任务调度器
private ScheduledFuture<?> progressJob;
private boolean isDragging = false;
private AppCompatSeekBar seekBar;
private AppCompatImageView ivCoverPlayerDetail;
private AppCompatImageView ivPagePlay;
private AppCompatImageView iv_collection_controller;
private AppCompatImageView iv_back_hibit_episode;
private AppCompatTextView tv_des_player;
private AppCompatTextView tv_episode_player;
private AppCompatTextView tv_title_player;
private AppCompatTextView tv_collection_num_controller;
private AppCompatTextView tv_title_hibit_episode;
private ProgressLineView load_line;
private RelativeLayout rl_ep;
private boolean isEpisodePlaying = false;
public VTGoogleExoPlayerView(Context context, AttributeSet attrs) {
super(context, attrs);
player = new ExoPlayer.Builder(context).build();
LayoutInflater inflater = LayoutInflater.from(context);
View inflate = inflater.inflate(R.layout.layout_videoplay_vt, this, true);
LayoutVideoplayVtBinding bind = LayoutVideoplayVtBinding.bind(inflate);
bind.playerView.setPlayer(player);
seekBar = bind.playerView.findViewById(R.id.seekBar_player_detail);
ivCoverPlayerDetail = bind.playerView.findViewById(R.id.iv_cover_player_detail);
ivPagePlay = bind.playerView.findViewById(R.id.iv_hibit_play);
iv_collection_controller = bind.playerView.findViewById(R.id.iv_collection_controller);
iv_back_hibit_episode = bind.playerView.findViewById(R.id.iv_back_hibit_episode);
tv_des_player = bind.playerView.findViewById(R.id.tv_des_player);
tv_episode_player = bind.playerView.findViewById(R.id.tv_episode_player);
tv_title_player = bind.playerView.findViewById(R.id.tv_title_player);
load_line = bind.playerView.findViewById(R.id.load_line);
rl_ep = bind.playerView.findViewById(R.id.rl_ep);
iv_back_hibit_episode.setOnClickListener(v ->
EventBus.getDefault().post(VTAppConstants.Constants_RecommendPlayerView_CLOSEExample)
);
tv_collection_num_controller = bind.playerView.findViewById(R.id.tv_collection_num_controller);
tv_title_hibit_episode = bind.playerView.findViewById(R.id.tv_title_hibit_episode);
player.addListener(new Player.Listener() {
@Override
public void onPlaybackStateChanged(int playbackState) {
Player.Listener.super.onPlaybackStateChanged(playbackState);
switch (playbackState) {
case Player.STATE_BUFFERING:
load_line.setVisibility(VISIBLE);
load_line.startAnimation();
break;
case Player.STATE_READY:
bind.playerView.setEnabled(true);
if (VTAppConstants.isCanPlay && !VTAppConstants.isLock) {
start();
setProgress();
}
ivCoverPlayerDetail.setVisibility(View.INVISIBLE);
load_line.endAnimation();
load_line.setVisibility(INVISIBLE);
break;
case Player.STATE_ENDED:
EventBus.getDefault().post(VTAppConstants.Constants_Google_PLAYER_STATUS_FINISH_DETAIL);
break;
case Player.STATE_IDLE:
bind.playerView.setEnabled(false);
break;
}
}
@Override
public void onPlayerError(PlaybackException error) {
Player.Listener.super.onPlayerError(error);
ivCoverPlayerDetail.setVisibility(View.INVISIBLE);
load_line.setVisibility(INVISIBLE);
if (TranslatesUtils.translates() != null) {
ToastUtils.revealToast(TranslatesUtils.translates().getNetwork_error(), 0);
} else {
ToastUtils.revealToast(context.getString(R.string.vt_network_error_please_check_the_network), 0);
}
}
});
bind.playerView.setOnClickListener(v -> {
if (!VTAppConstants.isLock) {
if (isEpisodePlaying) {
ivPagePlay.setImageResource(R.mipmap.iv_play_vt);
suspendPlayer();
} else {
ivPagePlay.setImageResource(R.mipmap.iv_stop_vt);
start();
}
}
});
}
private void setProgress() {
if (progressJob != null) {
progressJob.cancel(true);
}
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
progressJob = executor.scheduleWithFixedDelay(() -> {
if (!isDragging) {
long duration = player.getDuration();
long position = player.getCurrentPosition();
int progress = (int) (position * 100 / (duration == C.TIME_UNSET ? 1 : duration));
if (seekBar != null) {
seekBar.setMax(100);
seekBar.setProgress(progress + 1);
}
}
}, 0, 1, TimeUnit.SECONDS);
// if (progressJob != null) {
// progressJob.cancel(null);
// }
// progressJob = launchKt.launch(Dispatchers.getMain(), null, null, coroutineScope -> {
// while (isActive(coroutineScope)) {
// if (!isDragging.get()) {
// long duration = player.getDuration();
// long position = player.getCurrentPosition();
// int progress = (int) (position * 100 / (duration == C.TIME_UNSET ? 1 : duration));
// seekBar.setMax(100);
// seekBar.setProgress(progress + 1);
// }
// delayKt.delay(1000);
// }
// return null;
// });
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
seekTo(progress);
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
isDragging = true;
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
isDragging = false;
}
});
}
private void start() {
player.play();
ivPagePlay.setImageResource(R.mipmap.iv_stop_vt);
isEpisodePlaying = true;
isDragging = false;
}
public void suspendPlayer() {
player.pause();
ivPagePlay.setImageResource(R.mipmap.iv_play_vt);
isEpisodePlaying = false;
isDragging = true;
}
private void seekTo(int progress) {
long duration = player.getDuration();
player.seekTo(duration * progress / 100);
}
public void setMedia(VTVideoDetailsBean.Episode bean, VTVideoDetailsBean.ShortPlayInfo shortVideoInfo) {
VTAppConstants.isCanPlay = true;
tv_title_player.setText(shortVideoInfo.getName());
if (TranslatesUtils.translates() != null) {
tv_title_hibit_episode.setText(TranslatesUtils.replace(
TranslatesUtils.translates().getEpisode_set(),
String.valueOf(bean.getEpisode())
));
tv_episode_player.setText(TranslatesUtils.replace(
TranslatesUtils.translates().getComplete_episode(),
String.valueOf(shortVideoInfo.getEpisode_total())
));
} else {
tv_title_hibit_episode.setText("Episode ".concat(String.valueOf(bean.getEpisode())));
tv_episode_player.setText("Complete set : ".concat(String.valueOf(shortVideoInfo.getEpisode_total())));
}
tv_des_player.setText(shortVideoInfo.getDescription());
Glide.with(getContext()).load(shortVideoInfo.getImage_url()).into(ivCoverPlayerDetail);
ivCoverPlayerDetail.setVisibility(View.VISIBLE);
// iv_collection_controller.setImageResource(shortVideoInfo.isIs_collect() ? R.drawable.iv_hibit_like_h : R.drawable.iv_hibit_like_n);
// tv_collection_num_controller.setText(Timestamp.formatNumber(shortVideoInfo.getCollect_total()));
rl_ep.setOnClickListener(v ->
EventBus.getDefault().post(VTAppConstants.Constants_PlayerView_MoreItemEvent)
);
player.setMediaItem(MediaItem.fromUri(Uri.parse(bean.getVideo_url())));
player.prepare();
}
public void stop() {
player.stop();
if (progressJob != null) {
progressJob.cancel(true);
progressJob = null;
}
}
public void release() {
player.release();
}
}

View File

@ -0,0 +1,23 @@
package com.viontv.app.utils;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Build;
import android.provider.Settings;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* 设备ID
*/
public class GetAndroidUniqueMark {
@SuppressLint("HardwareIds")
public static String getUniqueId(Context context) {
return Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
}
}

View File

@ -0,0 +1,18 @@
package com.viontv.app.utils;
import android.app.Activity;
import android.content.Intent;
import com.viontv.app.VTApplication;
import com.viontv.app.ui.activity.play.VTVideoPlayerActivity;
public class IntentUtils {
public static void startPlayerDetails(Activity currentActivity,int details_id, int video_id){
Intent intent = new Intent(currentActivity.getApplicationContext(),VTVideoPlayerActivity.class);
intent.putExtra(VTAppConstants.Constants_Page_DetailId,details_id);
intent.putExtra(VTAppConstants.Constants_Page_video_id,video_id);
currentActivity.startActivity(intent);
}
}

View File

@ -0,0 +1,91 @@
package com.viontv.app.utils;
import static com.viontv.app.VTApplication.AppContext;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import com.viontv.app.VTApplication;
public class SharePreferenceUtils {
public static final String auth="auth";
public static void saveInt(String key, int value) {
SharedPreferences sp = AppContext.getSharedPreferences("InitApp", Activity.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.putInt(key, value);
editor.apply();
}
public static void saveFloat(String key, float value) {
SharedPreferences sp = AppContext.getSharedPreferences("InitApp", Activity.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.putFloat(key, value);
editor.apply();
}
public static void saveLong(String key, long value) {
SharedPreferences sp = AppContext.getSharedPreferences("InitApp", Activity.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.putLong(key, value);
editor.apply();
}
public static void saveString(String key, String value) {
SharedPreferences sp = AppContext.getSharedPreferences("VionTV", Activity.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.putString(key, value);
editor.apply();
}
public static void deleteKey(String key) {
SharedPreferences sp = AppContext.getSharedPreferences("VionTV", Activity.MODE_PRIVATE);
if (!sp.contains(key)) return;
SharedPreferences.Editor editor = sp.edit();
editor.remove(key);
editor.apply();
}
public static void saveBoolean(String key, boolean value) {
SharedPreferences sp = AppContext.getSharedPreferences("VionTV", Activity.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.putBoolean(key, value);
editor.apply();
}
public static int getInt(String key, int defValue) {
SharedPreferences sp = AppContext.getSharedPreferences("VionTV", Activity.MODE_PRIVATE);
return sp.getInt(key, defValue);
}
public static float getFloat(String key, float defValue) {
SharedPreferences sp = AppContext.getSharedPreferences("VionTV", Activity.MODE_PRIVATE);
return sp.getFloat(key, defValue);
}
public static long getLong(String key, long defValue) {
SharedPreferences sp = AppContext.getSharedPreferences("VionTV", Activity.MODE_PRIVATE);
return sp.getLong(key, defValue);
}
public static boolean getBoolean(String key, boolean defValue) {
SharedPreferences sp = AppContext.getSharedPreferences("VionTV", Activity.MODE_PRIVATE);
return sp.getBoolean(key, defValue);
}
public static String getString(String key, String defValue) {
Context context = AppContext;
if (context == null) {
return defValue;
}
SharedPreferences sp = context.getSharedPreferences("VionTV", Activity.MODE_PRIVATE);
return sp.getString(key, defValue);
}
public static boolean is_Vip(){
return true;
}
}

View File

@ -0,0 +1,25 @@
package com.viontv.app.utils;
import java.util.Date;
import java.util.TimeZone;
public class SingleClickUtils {
private static long lastClickTime = 0L;
public static void singleClick(long during, Runnable callBack) {
long now = new Date().getTime();
if (now - lastClickTime > during) {
callBack.run();
}
lastClickTime = now;
}
public static void singleClick(Runnable callBack) {
singleClick(500L, callBack);
}
public static String getCurrentTimeZone() {
TimeZone tz = TimeZone.getDefault();
return tz.getDisplayName(false, TimeZone.SHORT);
}
}

View File

@ -0,0 +1,66 @@
package com.viontv.app.utils;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
public class TimeUtils {
public static String getCurrentTimeZone() {
return createGmtOffsetString(true, true, TimeZone.getDefault().getRawOffset());
}
public static String createGmtOffsetString(boolean includeGmt, boolean includeMinuteSeparatori, int offsetMillis) {
int offsetMinutes = offsetMillis / 60000;
char sign = '+';
if (offsetMinutes < 0) {
sign = '-';
offsetMinutes = -offsetMinutes;
}
StringBuilder builder = new StringBuilder(9);
if (includeGmt) {
builder.append("GMT");
}
builder.append(sign);
appendNumber(builder, 2, offsetMinutes / 60);
return builder.toString();
}
public static void appendNumber(StringBuilder builder, int count, int value) {
String string = Integer.toString(value);
int diff = count - string.length();
for (int i = 0; i < diff; i++) {
builder.append('0');
}
builder.append(string);
}
public static String transToString(Long time) {
Date date = new Date(time * 1000);
return new SimpleDateFormat("yyyy-MM-dd").format(date);
}
public static String formatNumber(int num) {
if (num >= 1000000) {
return formatDouble(num / 1000000, 1) + "m";
}
if (num >= 1000) {
return formatDouble(num / 1000, 1) + "k";
}
return String.valueOf(num);
}
private static String formatDouble(double value, int digits) {
StringBuilder pattern = new StringBuilder("#.");
for (int i = 0; i < digits; i++) {
pattern.append("#");
}
DecimalFormat df = new DecimalFormat(pattern.toString());
return df.format(value);
}
}

View File

@ -0,0 +1,32 @@
package com.viontv.app.utils;
import android.os.Handler;
import android.os.Looper;
import android.widget.Toast;
import com.viontv.app.VTApplication;
public class ToastUtils {
private static Toast toast;
private static final Handler handler = new Handler(Looper.getMainLooper());
public static void revealToast(String message, int duration) {
if (duration == 0) {
duration = Toast.LENGTH_SHORT;
}
hideToast();
int finalDuration = duration;
handler.post(() -> {
toast = Toast.makeText(VTApplication.getAppContext(), message, finalDuration);
if (toast != null) {
toast.show();
}
});
}
private static void hideToast() {
if (toast != null) {
toast.cancel();
toast = null;
}
}
}

View File

@ -0,0 +1,28 @@
package com.viontv.app.utils;
import com.viontv.app.model.TranslatesResBean;
public class TranslatesUtils {
public static void saveTranslates(TranslatesResBean.Translates infoRes) {
SharePreferenceUtils.saveString(VTAppConstants.CONSTANTS_Translates_STRING,VTGsonUtils.beanToJSONString(infoRes));
}
public static TranslatesResBean.Translates translates(){
String vaule = SharePreferenceUtils.getString(VTAppConstants.CONSTANTS_Translates_STRING,"");
return VTGsonUtils.getObjFromJSON(vaule, TranslatesResBean.Translates.class);
}
public static String replace(String value,String result){
return value.replace("##",result);
}
public static String replaces(String old,String new1,String new2){
String replace = old.replace("#1#", new1);
return replace.replace("#2#",new2);
}
}

View File

@ -0,0 +1,53 @@
package com.viontv.app.utils;
public class VTAppConstants {
public static final int page_size = 10;
public static final String Constants_last_update_time = "Constants_last_update_time";
public static final String Constants_language_refresh = "Constants_language_refresh";
public static final String CONSTANTS_Translates_STRING = "CONSTANTS_Translates_STRING";
public static final String Constants_BASE_URL = "https://api.hibitplay.com";
// public static final String Constants_BASE_URL = "https://test-api.guyantv.com";
public static final String Constants_HTTP_TOKEN = "Authorization";
public static final String Constants_Page_DetailId = "constants_page_detail_id";
public static final String Constants_Page_video_id = "Constants_Page_video_id";
public static final String Constants_Page_Episodes_Series_Data_VT = "constants_page_episodes_series_data";
public static final String Constants_Page_Episodes_Series_Data_List = "Constants_Page_Episodes_Series_Data_List";
public static final String Constants_PlayerView_MoreItemEvent =
"Constants_PlayerView_MoreItem";
public static final String Constants_RecommendPlayerView_CLOSEExample =
"Constants_RecommendPlayerView_CLOSEExample";
public static final String Constants_Page_Episodes_Series_Data_currentPosition =
"Constants_Page_Episodes_Series_Data_currentPosition";
public static final String Constants_Google_PLAYER_STATUS_FINISH = "constants_google_player_status_finish";
public static final String Constants_Google_PLAYER_STATUS_FINISH_DETAIL =
"constants_google_player_status_finish_detail";
public static final String CONSTANTS_refresh_auth = "CONSTANTS_refresh_auth";
public static final String CONSTANTS_out_login = "CONSTANTS_out_login";
public static final String CONSTANTS_user_refresh = "CONSTANTS_user_refresh";
public static final String LogEvent_af_app_recharge = "af_app_recharge";
public static final String CONSTANTS_AppsFlyer = "axv4xFtouhau4js4GxqBX9";
public static final String Constants_Episodes_Series_DataExample = "Constants_Episodes_Series_DataExample";
public static final String Constants_Episodes_Series_DataFavorites = "Constants_Episodes_Series_DataFavorites";
public static final String CONSTANTS_GOOGLE_LOGIN =
"996139080527-njj3ehigooauk800e0o6hm785jofi2l5.apps.googleusercontent.com";
public static final String CONSTANTS_device_id = "device-id";
public static final String CONSTANTS_system_type = "system-type";
public static final String CONSTANTS_model = "model";
public static final String CONSTANTS_app_version = "app-version";
public static final String CONSTANTS_app_name = "app-name";
public static final String CONSTANTS_lang_key = "lang-key";
public static final String CONSTANTS_time_zone = "time-zone";
public static final String CONSTANTS_SEARCH_STRINGExample = "CONSTANTS_SEARCH_STRINGExample";
public static final String CONSTANTS_User_STRING = "CONSTANTS_User_STRING";
public static final int requestCodeByGoogleLogin = 666;
public static boolean isCanPlay = true;
public static boolean isLock = false;
public static final String Constants_member_ship_agreement =
"https://www.hibitplay.com/member_ship_agreement_android.html";
public static final String Constants_user_agreement = "https://www.hibitplay.com/user_policy_android.html";
public static final String Constants_privacy_policy = "https://www.hibitplay.com/private_android.html";
public static final String Constants_Web_Url = "Constants_Web_Url";
public static final String CLIENT_KEY = "awp5nm8lwpyebwgv";
public static final String REDIRECT_URL = "hibitapp://oauthresponse";
}

View File

@ -0,0 +1,87 @@
package com.viontv.app.utils;
import android.text.TextUtils;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
public class VTGsonUtils {
public static Gson gson = new Gson();
/**
* 返回List对象
* @param str
* @param type new TypeToken<ArrayList<T>>(){}.getType()
* @param <T>
* @return
*/
public static <T> T getListFromJSON(String str, Type type) {
if (!TextUtils.isEmpty(str)) {
return gson.fromJson(str, type);
}
return null;
}
/**
* 返回List对象
* @param str
* @param cls
* @param <T>
* @return
*/
public static <T> List<T> getListFromJSON(String str, Class<T> cls)
{
Type type = new TypeToken<ArrayList<JsonObject>>()
{}.getType();
ArrayList<JsonObject> jsonObjects = gson.fromJson(str, type);
ArrayList<T> arrayList = new ArrayList<>();
for (JsonObject jsonObject : jsonObjects)
{
arrayList.add(gson.fromJson(jsonObject, cls));
}
return arrayList;
}
/**
* 返回对象
* @param str
* @param cls
* @param <T>
* @return
*/
public static <T> T getObjFromJSON(String str, Class<T> cls) {
// try {
if (!TextUtils.isEmpty(str)) {
return gson.fromJson(str, cls);
}
return null;
// }catch (Exception e) {
// return null;
// }
}
/**
* 返回JsonString
* @return
*/
public static String beanToJSONString(Object bean) {
return new Gson().toJson(bean);
}
public static String JSONTokener(String in) {
// consume an optional byte order mark (BOM) if it exists
if (in != null && in.startsWith("\ufeff")) {
in = in.substring(1);
}
return in;
}
}

View File

@ -0,0 +1,126 @@
package com.viontv.app.utils;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.util.TypedValue;
import android.os.Build;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
public class VTStatusBarUtils {
private static int DEFAULT_COLOR = 0;
private static float DEFAULT_ALPHA = 0f;
private static final int MIN_API = 19;
public static void pageImmersive(Window window, int color) {
pageImmersive(window, color, 1f);
}
public static void pageImmersive(Window window, int color, float alpha) {
if (Build.VERSION.SDK_INT >= 21) {
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(pageMixtureColor(color, alpha));
int systemUiVisibility = window.getDecorView().getSystemUiVisibility();
systemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
systemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
window.getDecorView().setSystemUiVisibility(systemUiVisibility);
} else if (Build.VERSION.SDK_INT >= MIN_API) {
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
pageSetTranslucentView((ViewGroup) window.getDecorView(), color, alpha);
} else {
int systemUiVisibility = window.getDecorView().getSystemUiVisibility();
systemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
systemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
window.getDecorView().setSystemUiVisibility(systemUiVisibility);
}
}
public static void pageDarkMode(Activity activity, boolean dark) {
pageDarkMode(activity.getWindow(), DEFAULT_COLOR, DEFAULT_ALPHA, dark);
}
@TargetApi(Build.VERSION_CODES.M)
public static void pageDarkMode(Window window, int color, float alpha, boolean dark) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
pageDarkModeForM(window, dark);
pageImmersive(window, color, alpha);
} else if (Build.VERSION.SDK_INT >= MIN_API) {
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
pageSetTranslucentView((ViewGroup) window.getDecorView(), color, alpha);
} else {
pageImmersive(window, color, alpha);
}
}
@TargetApi(Build.VERSION_CODES.M)
public static void pageDarkModeForM(Window window, boolean dark) {
int systemUiVisibility = window.getDecorView().getSystemUiVisibility();
if (dark) {
systemUiVisibility |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
} else {
systemUiVisibility &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
}
window.getDecorView().setSystemUiVisibility(systemUiVisibility);
}
public static void pageSetPaddingSmart(Context context, View view) {
if (Build.VERSION.SDK_INT >= MIN_API) {
ViewGroup.LayoutParams lp = view.getLayoutParams();
if (lp != null && lp.height > 0) {
lp.height += pageGetStatusBarHeight(context);
}
view.setPadding(
view.getPaddingLeft(),
view.getPaddingTop() + pageGetStatusBarHeight(context),
view.getPaddingRight(),
view.getPaddingBottom()
);
}
}
private static void pageSetTranslucentView(ViewGroup container, int color, float alpha) {
if (Build.VERSION.SDK_INT >= MIN_API) {
int mixtureColor = pageMixtureColor(color, alpha);
View translucentView = container.findViewById(android.R.id.custom);
if (translucentView == null && mixtureColor != 0) {
translucentView = new View(container.getContext());
translucentView.setId(android.R.id.custom);
ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
pageGetStatusBarHeight(container.getContext())
);
container.addView(translucentView, lp);
}
if (translucentView != null) {
translucentView.setBackgroundColor(mixtureColor);
}
}
}
private static int pageMixtureColor(int color, float alpha) {
int a = (color & 0xff000000) == 0 ? 0xff : color >>> 24;
return (color & 0x00ffffff) | ((int) (a * alpha) << 24);
}
private static int pageGetStatusBarHeight(Context context) {
int result = 24;
int resId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resId > 0) {
result = context.getResources().getDimensionPixelSize(resId);
} else {
result = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
result,
Resources.getSystem().getDisplayMetrics()
);
}
return result;
}
}

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
>
<item android:width="375dp" android:height="388dp">
<shape android:shape="rectangle">
<solid android:color="#ffffffff" />
<corners android:topLeftRadius="8dp" android:topRightRadius="8dp" android:bottomLeftRadius="0dp" android:bottomRightRadius="0dp" />
</shape>
</item>
</selector>

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
<shape>
<solid android:color="#9E9696" />
</shape>
</item>
<item android:id="@android:id/progress">
<clip>
<shape>
<solid android:color="#FF0049" />
</shape>
</clip>
</item>
</layer-list>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="#FF0049"/>
</shape>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:width="58dp" android:height="58dp">
<shape android:shape="rectangle">
<solid android:color="#fff9f9f9" />
<corners android:topLeftRadius="8dp" android:topRightRadius="8dp" android:bottomLeftRadius="8dp" android:bottomRightRadius="8dp" />
</shape>
</item>
</selector>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
>
<item android:width="58dp" android:height="58dp">
<shape android:shape="rectangle">
<stroke android:width="1dp" android:color="#ffff0049" />
<corners android:topLeftRadius="8dp" android:topRightRadius="8dp" android:bottomLeftRadius="8dp" android:bottomRightRadius="8dp" />
</shape>
</item>
</selector>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/white">
<!-- 默认显⽰效果-->
<item>
<shape android:shape="rectangle">
<solid android:color="#1affffff" />
<corners android:radius="@dimen/dp_4" />
</shape>
</item>
</ripple>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/white">
<!-- 默认显⽰效果-->
<item>
<shape android:shape="rectangle">
<gradient
android:angle="90"
android:startColor="#BF6BFF"
android:endColor="#F56490"
android:type="linear"
android:useLevel="true" />
<corners android:topLeftRadius="@dimen/dp_6"
android:bottomRightRadius="@dimen/dp_6"/>
</shape>
</item>
</ripple>

View File

@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>

View File

@ -0,0 +1,30 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@mipmap/iv_main_tab_explore_default" android:state_selected="false"/>
<item android:drawable="@mipmap/iv_main_tab_explore_click" android:state_selected="true"/>
</selector>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@mipmap/iv_main_tab_home_default" android:state_selected="false"/>
<item android:drawable="@mipmap/iv_main_tab_home_click" android:state_selected="true"/>
</selector>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@mipmap/iv_main_tab_me_default" android:state_selected="false"/>
<item android:drawable="@mipmap/iv_main_tab_me_click" android:state_selected="true"/>
</selector>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@mipmap/iv_main_tab_mylist_default" android:state_selected="false"/>
<item android:drawable="@mipmap/iv_main_tab_mylist_click" android:state_selected="true"/>
</selector>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@mipmap/iv_main_tab_rewards_default" android:state_selected="false"/>
<item android:drawable="@mipmap/iv_main_tab_rewards_click" android:state_selected="true"/>
</selector>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="@dimen/dp_19" />
<solid android:color="#1affffff" />
</shape>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:gravity="center" android:width="23dp" android:height="@dimen/dp_8">
<bitmap
android:gravity="top|center_horizontal"
android:src="@mipmap/iv_tab_indicator"/></item>
</layer-list>

View File

@ -0,0 +1,83 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".ui.activity.VTMainActivity">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
tools:ignore="MissingConstraints" />
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/layout_main_tab"
android:layout_width="match_parent"
android:layout_height="49dp"
android:layout_alignParentBottom="true"
android:background="@android:color/black"
android:elevation="5dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_vt_main_home"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:drawableTop="@drawable/main_tab_home"
android:drawablePadding="3dp"
android:gravity="center"
android:text="@string/tab_main_home"
android:textIsSelectable="true"
android:textColor="#D2D2D2"
android:textSize="8sp"
android:textStyle="normal" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_vt_main_explore"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:drawableTop="@drawable/main_tab_explore"
android:drawablePadding="3dp"
android:gravity="center"
android:text="@string/tab_main_explore"
android:textColor="#D2D2D2"
android:textSize="8sp"
android:textStyle="normal" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_vt_main_mylist"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:drawableTop="@drawable/main_tab_mylist"
android:drawablePadding="3dp"
android:gravity="center"
android:text="@string/tab_main_mylist"
android:textColor="#D2D2D2"
android:textSize="8sp"
android:textStyle="normal" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_vt_main_me"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:drawableTop="@drawable/main_tab_me"
android:drawablePadding="3dp"
android:gravity="center"
android:text="@string/tab_main_me"
android:textColor="#D2D2D2"
android:textSize="8sp"
android:textStyle="normal" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>

View File

@ -0,0 +1,23 @@
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black"
android:orientation="vertical"
android:fitsSystemWindows="false"
tools:ignore="MissingDefaultResource">
<include layout="@layout/layout_videoplay_vt"
android:id="@+id/tiktok"/>
<ImageView
android:layout_width="@dimen/dp_40"
android:layout_height="@dimen/dp_40"
android:scaleType="centerInside"
android:id="@+id/back_iv"
android:layout_marginTop="@dimen/dp_30"
android:src="@mipmap/iv_back_vt"/>
</RelativeLayout>

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="#272A30"
android:layout_height="match_parent">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager_hibit_episode"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" />
<com.wang.avi.AVLoadingIndicatorView
android:id="@+id/avi"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:indicatorName="BallSpinFadeLoaderIndicator"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_dialog_recharge_no_bottom_vt"
android:orientation="vertical"
android:paddingTop="19dp"
android:paddingBottom="15dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_content_episodes_series"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_marginLeft="17dp"
android:layout_toLeftOf="@id/iv_close_episodes_series"
android:textColor="@color/color_333333"
android:textSize="16dp" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_close_episodes_series"
android:layout_width="22dp"
android:layout_height="22dp"
android:layout_alignParentRight="true"
android:layout_marginRight="17dp"
android:src="@mipmap/iv_close_episodes_select_vt" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_data_episodes_series"
android:layout_width="match_parent"
android:layout_height="320dp"
android:layout_below="@id/tv_content_episodes_series"
android:layout_marginTop="20dp"
android:layout_marginRight="15dp" />
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.activity.home.VTHomeFragment">
<!-- <com.scwang.smart.refresh.layout.SmartRefreshLayout-->
<!-- android:id="@+id/refreshLayout"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="match_parent"-->
<!-- android:visibility="visible"-->
<!-- app:srlAccentColor="@android:color/transparent">-->
<!-- <com.viontv.app.ui.view.VTBezierCircleHeader-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content" />-->
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/dp_15"
android:orientation="vertical">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_15"
android:layout_marginTop="@dimen/dp_15"
android:gravity="center_vertical"
android:orientation="horizontal"
tools:ignore="MissingDefaultResource">
<com.youth.banner.Banner
android:id="@+id/banner"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintDimensionRatio="345:183"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerview_grid"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_15"
android:layout_marginTop="@dimen/dp_20" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
<!-- </com.scwang.smart.refresh.layout.SmartRefreshLayout>-->
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,97 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.activity.home.VTHomeFragment">
<!-- <com.scwang.smart.refresh.layout.SmartRefreshLayout-->
<!-- android:id="@+id/refreshLayout"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="match_parent"-->
<!-- android:visibility="visible"-->
<!-- app:srlAccentColor="@android:color/transparent">-->
<!-- <com.viontv.app.ui.view.VTBezierCircleHeader-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content" />-->
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/dp_15"
android:orientation="vertical">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_15"
android:layout_marginTop="@dimen/dp_15"
android:gravity="center_vertical"
android:orientation="horizontal"
tools:ignore="MissingDefaultResource">
<com.youth.banner.Banner
android:id="@+id/banner"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintDimensionRatio="345:183"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<TextView
android:id="@+id/trending_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_15"
android:layout_marginTop="@dimen/dp_25"
android:drawablePadding="@dimen/dp_10"
android:gravity="center"
android:text="@string/home_trending"
android:textColor="@android:color/white"
android:textSize="@dimen/sp_15"
android:textStyle="bold" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerview_trending"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_3" />
<TextView
android:id="@+id/genres_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_15"
android:layout_marginTop="@dimen/dp_25"
android:drawablePadding="@dimen/dp_10"
android:gravity="center"
android:text="@string/home_genres"
android:textColor="@android:color/white"
android:textSize="@dimen/sp_15"
android:textStyle="bold" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerview_genres"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_3" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
<!-- </com.scwang.smart.refresh.layout.SmartRefreshLayout>-->
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@mipmap/iv_homefragment_bg"
tools:context=".ui.activity.home.VTHomeFragment">
<FrameLayout
android:id="@+id/layout_search"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_40"
android:layout_marginStart="@dimen/dp_14"
android:layout_marginTop="@dimen/dp_55"
android:layout_marginEnd="@dimen/dp_14"
android:background="@drawable/shape_serarch_home"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/tv_home_search"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/dp_15"
android:layout_marginEnd="@dimen/dp_15"
android:textColorHint="#38ffffff"
android:gravity="center_vertical"
android:drawablePadding="@dimen/dp_7"
android:drawableStart="@mipmap/iv_homefragment_search"
android:textColor="#38ffffff"
android:textSize="@dimen/sp_12" />
</FrameLayout>
<com.google.android.material.tabs.TabLayout
android:id="@+id/tablayout"
android:layout_width="match_parent"
android:layout_marginTop="@dimen/dp_15"
android:layout_height="@dimen/dp_40"
android:layout_centerVertical="true"
android:background="@android:color/transparent"
app:layout_constraintTop_toBottomOf="@+id/layout_search"
app:tabBackground="@android:color/transparent"
app:tabIndicator="@drawable/tabindicator_item"
app:tabIndicatorColor="@color/color_f564b6"
app:tabIndicatorGravity="bottom"
app:tabIndicatorFullWidth="false"
app:tabInlineLabel="false"
app:tabIndicatorHeight="@dimen/dp_8"
app:tabMinWidth="@dimen/dp_40"
app:tabIndicatorAnimationMode="fade"
app:tabMode="scrollable"
app:tabPaddingBottom="@dimen/dp_3"
app:tabPaddingEnd="5dp"
app:tabPaddingStart="5dp"
app:tabRippleColor="@null"
app:tabSelectedTextColor="#F564B6"
app:tabTextAppearance="@style/MyBgTablayoutstyle"
app:tabTextColor="#D2D2D2" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginBottom="@dimen/dp_10"
app:layout_constraintTop_toBottomOf="@+id/tablayout"
app:layout_constraintBottom_toBottomOf="parent"
android:overScrollMode="never" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_fragment_hometop"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="15dp"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.appcompat.widget.LinearLayoutCompat>

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_183">
<ImageView
android:id="@+id/iv_banner_img"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY" />
<ImageView
android:id="@+id/iv_banner_collect"
android:layout_width="@dimen/dp_24"
android:layout_height="@dimen/dp_24"
android:layout_marginTop="@dimen/dp_10"
android:layout_marginEnd="@dimen/dp_10"
android:background="@mipmap/iv_banner_collect"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

Some files were not shown because too many files have changed in this diff Show More