Commit c60cf038 by mReturn

V2.5.7

parent 111203fe
Showing with 1155 additions and 0 deletions
apply plugin: 'com.android.library'
android {
compileSdkVersion compile_sdk_version
buildToolsVersion build_tools_version
defaultConfig {
minSdkVersion min_sdk_version
targetSdkVersion target_sdk_version
versionCode version_code
versionName verson_name
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation "com.android.support:appcompat-v7:27.1.1"
implementation "com.android.support:recyclerview-v7:27.1.1"
}
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tencent.liteav.demo.beauty">
</manifest>
\ No newline at end of file
package com.tencent.liteav.demo.beauty;
public class BeautyData {
public int icon;
public String text;
public BeautyData(int icon, String text) {
this.icon = icon;
this.text = text;
}
}
package com.tencent.liteav.demo.beauty;
import android.graphics.Bitmap;
/**
* 美颜参数
*/
public class BeautyParams {
// 美颜类型
public int mBeautyStyle = 0;
// 美颜
public int mBeautyLevel = 4;
// 美白
public int mWhiteLevel = 1;
// 红润
public int mRuddyLevel = 0;
// 滤镜LUT图
public Bitmap mFilterBmp;
// 滑动滤镜索引
public int mFilterIndex;
// 滤镜程度
public int mFilterStrength = 0;
// 大眼
public int mBigEyeLevel;
// 瘦脸
public int mFaceSlimLevel;
// 瘦鼻
public int mNoseSlimLevel;
// 缩下巴
public int mChinSlimLevel;
// V脸
public int mFaceVLevel;
// 短脸
public int mFaceShortLevel;
// 亮眼
public int mEyeLightenLevel = 0;
// 白牙
public int mToothWhitenLevel = 0;
// 祛皱
public int mWrinkleRemoveLevel = 0;
// 祛眼袋
public int mPounchRemoveLevel = 0;
// 祛法令纹
public int mSmileLinesRemoveLevel = 0;
// 发际线
public int mForeheadLevel = 0;
// 眼距
public int mEyeDistanceLevel = 0;
// 眼角
public int mEyeAngleLevel = 0;
// 嘴型
public int mMouthShapeLevel = 0;
// 鼻翼
public int mNoseWingLevel = 0;
// 鼻子位置
public int mNosePositionLevel = 0;
// 嘴唇厚度
public int mLipsThicknessLevel = 0;
// 脸型
public int mFaceBeautyLevel = 0;
// 长腿
public int mLongLegLevel = 0;
// 瘦腰
public int mThinWaistLevel = 0;
// 瘦体
public int mThinBodyLevel = 0;
// 瘦肩
public int mThinShoulderLevel = 0;
// 动效文件路径
public String mMotionTmplPath;
// 绿幕
public String mGreenFile;
}
package com.tencent.liteav.demo.beauty;
import android.app.Dialog;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
public class CustomProgressDialog {
private Dialog mDialog;
private TextView tvMsg;
public void createLoadingDialog(Context context) {
LayoutInflater inflater = LayoutInflater.from(context);
View v = inflater.inflate(R.layout.layout_loading_progress, null);
LinearLayout layout = (LinearLayout) v.findViewById(R.id.layout_progress);
ImageView spaceshipImage = (ImageView) v.findViewById(R.id.progress_img);
tvMsg = (TextView) v.findViewById(R.id.msg_tv);
Animation hyperspaceJumpAnimation = AnimationUtils.loadAnimation(context, R.anim.load_progress_animation);
spaceshipImage.startAnimation(hyperspaceJumpAnimation);
mDialog = new Dialog(context, R.style.loading_dialog);
mDialog.setCancelable(false);
mDialog.setContentView(layout, new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.MATCH_PARENT));// 设置布局
}
public void setCancelable(boolean cancelable) {
if (mDialog != null) {
mDialog.setCancelable(cancelable);
}
}
public void setCanceledOnTouchOutside(boolean canceledOnTouchOutside) {
if (mDialog != null) {
mDialog.setCanceledOnTouchOutside(canceledOnTouchOutside);
}
}
public void show() {
if (mDialog != null) {
mDialog.show();
}
}
public void dismiss() {
if (mDialog != null) {
mDialog.dismiss();
}
}
public void setMsg(String msg) {
if (tvMsg == null) {
return;
}
if (tvMsg.getVisibility() == View.GONE) {
tvMsg.setVisibility(View.VISIBLE);
}
tvMsg.setText(msg);
}
}
package com.tencent.liteav.demo.beauty;
public interface Downloadlistener {
void onDownloadFail(String errorMsg);
void onDownloadProgress(final int progress);
void onDownloadSuccess(String filePath);
}
package com.tencent.liteav.demo.beauty;
import java.io.File;
public interface HttpFileListener {
void onProgressUpdate(int progress);
void onSaveSuccess(File file);
void onSaveFailed(File file, Exception e);
void onProcessEnd();
}
package com.tencent.liteav.demo.beauty;
import android.content.Context;
import android.text.TextUtils;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class HttpFileUtil implements Runnable {
public static final int BUFFERED_READER_SIZE = 8192;
public static final int TIMEOUT = 30000;
private Context mContext;
private String mUrl;
private String mFolder;
private String mFilename;
private HttpFileListener mListener;
private long mContentLength;
private long mDownloadingSize;
private boolean mNeedProgress;
public HttpFileUtil(Context context, String url, String folder, String filename, HttpFileListener listener, boolean needProgress) {
mContext = context;
mUrl = url;
mFolder = folder;
mFilename = filename;
mListener = listener;
mNeedProgress = needProgress;
}
@Override
public void run() {
if (!VideoDeviceUtil.isNetworkAvailable(mContext) ||
TextUtils.isEmpty(mUrl) || TextUtils.isEmpty(mFolder) || TextUtils.isEmpty(mFilename) || !mUrl.startsWith("http")) {
fail(null);
return;
}
File dstFolder = new File(mFolder);
if (!dstFolder.exists()) {
dstFolder.mkdirs();
} else {
if (dstFolder.isFile()) {
if (mListener != null) {
mListener.onSaveFailed(dstFolder, null);
return;
}
}
}
File dstFile = new File(mFolder + File.separator + mFilename);
HttpURLConnection client = null;
InputStream responseIs = null;
FileOutputStream fos = null;
int statusCode = -1;
boolean success = false;
Exception failException = null;
try {
if (dstFile.exists()) {
dstFile.delete();
}
dstFile.createNewFile();
client = (HttpURLConnection) new URL(mUrl).openConnection();
// 设置网络超时参数
client.setConnectTimeout(TIMEOUT);
client.setReadTimeout(TIMEOUT);
client.setDoInput(true);
client.setRequestMethod("GET");
statusCode = client.getResponseCode();
success = client.getResponseCode() == HttpURLConnection.HTTP_OK;
if (success) {
if (mNeedProgress) {
mContentLength = client.getContentLength();
}
responseIs = client.getInputStream();
int length = -1;
byte[] buffer = new byte[BUFFERED_READER_SIZE];
fos = new FileOutputStream(dstFile);
mDownloadingSize = 0;
mListener.onProgressUpdate(0);
while ((length = responseIs.read(buffer)) != -1) {
fos.write(buffer, 0, length);
if (mNeedProgress) {
int pre = (int) (mDownloadingSize * 100 / mContentLength);
mDownloadingSize += length;
int now = (int) (mDownloadingSize * 100 / mContentLength);
if (pre != now && mListener != null) {
mListener.onProgressUpdate(now);
}
}
}
fos.flush();
if (mListener != null) {
mListener.onProgressUpdate(100);
mListener.onSaveSuccess(dstFile);
}
} else {
failException = new HttpStatusException("http status got exception. code = " + statusCode);
}
} catch (Exception e) {
failException = e;
e.printStackTrace();
} finally {
try {
if (fos != null) {
fos.close();
}
if (responseIs != null) {
responseIs.close();
}
if (client != null) {
client.disconnect();
}
mListener.onProcessEnd();
} catch (IOException e) {
e.printStackTrace();
}
}
if (!success || null != failException) {
mListener.onSaveFailed(dstFile, failException);
}
}
private void fail(Exception e) {
if (mListener != null) {
mListener.onSaveFailed(null, e);
}
mListener = null;
}
}
package com.tencent.liteav.demo.beauty;
/**
* Http状态异常[自定义抛出的异常]
*/
public class HttpStatusException extends Exception {
public HttpStatusException(String detailMessage) {
super(detailMessage);
}
}
package com.tencent.liteav.demo.beauty;
import android.annotation.TargetApi;
import android.graphics.Bitmap;
public interface IBeautyKit {
/**
* 设置指定素材滤镜特效
*
* @param filterImage : 指定素材,即颜色查找表图片。注意:一定要用png格式!!!
* demo用到的滤镜查找表图片位于RTMPAndroidDemo/app/src/main/res/drawable-xxhdpi/目录下。
*/
void setFilter(Bitmap filterImage, int index);
/**
* 设置滤镜效果程度
*
* @param strength : 从0到1,越大滤镜效果越明显,默认取值0.5
*/
void setFilterStrength(float strength);
/**
* 设置绿幕文件(企业版有效,其它版本设置此参数无效)[API >= 18]
* <p>
* 此处的绿幕功能并非智能抠背,它需要被拍摄者的背后有一块绿色的幕布来辅助产生特效。
*
* @param path 视频文件路径。支持 MP4;null 表示关闭特效。
*/
@TargetApi(18)
void setGreenScreenFile(String path);
/**
* 设置美颜类型
*
* @param beautyStyle 美颜风格.三种美颜风格:0 :光滑 1:自然 2:朦胧
*/
void setBeautyStyle(int beautyStyle);
/**
* 设置美颜级别
*
* @param beautyLevel 美颜级别,取值范围0 - 9; 0表示关闭,1 - 9值越大,效果越明显。
*/
void setBeautyLevel(int beautyLevel);
/**
* 设置美白级别
*
* @param whitenessLevel 美白级别,取值范围0 - 9; 0表示关闭,1 - 9值越大,效果越明显。
*/
void setWhitenessLevel(int whitenessLevel);
/**
* 设置红润级别
*
* @param ruddyLevel 红润级别,取值范围0 - 9; 0表示关闭,1 - 9值越大,效果越明显。
*/
void setRuddyLevel(int ruddyLevel);
/**
* 设置大眼级别(企业版有效,其它版本设置此参数无效)
*
* @param eyeScaleLevel 大眼级别,取值范围0 - 9; 0表示关闭,1 - 9值越大,效果越明显。
*/
void setEyeScaleLevel(int eyeScaleLevel);
/**
* 设置瘦脸级别(企业版有效,其它版本设置此参数无效)
*
* @param faceSlimLevel 瘦脸级别,取值范围0 - 9; 0表示关闭,1 - 9值越大,效果越明显。
*/
void setFaceSlimLevel(int faceSlimLevel);
/**
* 设置V脸级别(企业版有效,其它版本设置此参数无效)
*
* @param faceVLevel V脸级别,取值范围0 - 9; 0表示关闭,1 - 9值越大,效果越明显。
*/
void setFaceVLevel(int faceVLevel);
/**
* 设置下巴拉伸或收缩(企业版有效,其它版本设置此参数无效)
*
* @param chinLevel 下巴拉伸或收缩级别,取值范围 -9 - 9;0 表示关闭,小于0表示收缩,大于0表示拉伸。
*/
void setChinLevel(int chinLevel);
/**
* 设置短脸级别(企业版有效,其它版本设置此参数无效)
*
* @param faceShortLevel 短脸级别,取值范围0 - 9; 0表示关闭,1 - 9值越大,效果越明显。
*/
void setFaceShortLevel(int faceShortLevel);
/**
* 设置瘦鼻级别(企业版有效,其它版本设置此参数无效)
*
* @param noseSlimLevel 瘦鼻级别,取值范围0 - 9; 0表示关闭,1 - 9值越大,效果越明显。
*/
void setNoseSlimLevel(int noseSlimLevel);
/**
* 设置亮眼 (企业版有效,其它版本设置此参数无效)
*
* @param eyeLightenLevel 亮眼级别,取值范围0 - 9; 0表示关闭,1 - 9值越大,效果越明显。
*/
void setEyeLightenLevel(int eyeLightenLevel);
/**
* 设置白牙 (企业版有效,其它版本设置此参数无效)
*
* @param toothWhitenLevel 白牙级别,取值范围0 - 9; 0表示关闭,1 - 9值越大,效果越明显。
*/
void setToothWhitenLevel(int toothWhitenLevel);
/**
* 设置祛皱 (企业版有效,其它版本设置此参数无效)
*
* @param wrinkleRemoveLevel 祛皱级别,取值范围0 - 9; 0表示关闭,1 - 9值越大,效果越明显。
*/
void setWrinkleRemoveLevel(int wrinkleRemoveLevel);
/**
* 设置祛眼袋 (企业版有效,其它版本设置此参数无效)
*
* @param pounchRemoveLevel 祛眼袋级别,取值范围0 - 9; 0表示关闭,1 - 9值越大,效果越明显。
*/
void setPounchRemoveLevel(int pounchRemoveLevel);
/**
* 设置祛法令纹 (企业版有效,其它版本设置此参数无效)
*
* @param smileLinesRemoveLevel 祛法令纹级别,取值范围0 - 9; 0表示关闭,1 - 9值越大,效果越明显。
*/
void setSmileLinesRemoveLevel(int smileLinesRemoveLevel);
/**
* 设置发际线 (企业版有效,其它版本设置此参数无效)
*
* @param foreheadLevel 发际线级别,取值范围0 - 9; 0表示关闭,1 - 9值越大,效果越明显。
*/
void setForeheadLevel(int foreheadLevel);
/**
* 设置眼距 (企业版有效,其它版本设置此参数无效)
*
* @param eyeDistanceLevel 眼距级别,取值范围0 - 9; 0表示关闭,1 - 9值越大,效果越明显。
*/
void setEyeDistanceLevel(int eyeDistanceLevel);
/**
* 设置眼角 (企业版有效,其它版本设置此参数无效)
*
* @param eyeAngleLevel 眼角级别,取值范围0 - 9; 0表示关闭,1 - 9值越大,效果越明显。
*/
void setEyeAngleLevel(int eyeAngleLevel);
/**
* 设置嘴型 (企业版有效,其它版本设置此参数无效)
*
* @param mouthShapeLevel 嘴型级别,取值范围0 - 9; 0表示关闭,1 - 9值越大,效果越明显。
*/
void setMouthShapeLevel(int mouthShapeLevel);
/**
* 设置鼻翼 (企业版有效,其它版本设置此参数无效)
*
* @param noseWingLevel 鼻翼级别,取值范围0 - 9; 0表示关闭,1 - 9值越大,效果越明显。
*/
void setNoseWingLevel(int noseWingLevel);
/**
* 设置鼻子位置 (企业版有效,其它版本设置此参数无效)
*
* @param nosePositionLevel 鼻子位置级别,取值范围0 - 9; 0表示关闭,1 - 9值越大,效果越明显。
*/
void setNosePositionLevel(int nosePositionLevel);
/**
* 设置嘴唇厚度 (企业版有效,其它版本设置此参数无效)
*
* @param lipsThicknessLevel 嘴唇厚度级别,取值范围0 - 9; 0表示关闭,1 - 9值越大,效果越明显。
*/
void setLipsThicknessLevel(int lipsThicknessLevel);
/**
* 设置脸型 (企业版有效,其它版本设置此参数无效)
*
* @param faceBeautyLevel 脸型级别,取值范围0 - 9; 0表示关闭,1 - 9值越大,效果越明显。
*/
void setFaceBeautyLevel(int faceBeautyLevel);
/**
* 选择使用哪一款 AI 动效挂件(企业版有效,其它版本设置此参数无效)
*/
void setMotionTmpl(String tmplPath);
/**
* 设置动效静音(企业版有效,其它版本设置此参数无效)
* <p>
* 有些挂件本身会有声音特效,通过此 API 可以关闭这些特效播放时所带的声音效果。
*
* @param motionMute YES:静音;NO:不静音。
*/
void setMotionMute(boolean motionMute);
}
package com.tencent.liteav.demo.beauty;
import android.content.Context;
import android.graphics.Color;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
public class IconTextAdapter extends BaseAdapter {
private static final String TAG = "IconTextAdapter";
private final Context mContext;
private int mTextColorPrimary;
private ArrayList<BeautyData> data = new ArrayList<BeautyData>();
private BeautyPanel.OnItemClickListener mItemClickListener;
// 当前选中
private int mSelectPos;
public IconTextAdapter(Context context) {
mContext = context;
}
public void addAll(ArrayList<BeautyData> beautyDataList) {
data.clear();
data.addAll(beautyDataList);
notifyDataSetChanged();
}
public void clearAllData() {
data.clear();
notifyDataSetChanged();
}
@Override
public int getCount() {
return data.size();
}
@Override
public Object getItem(int position) {
return data.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
convertView = LayoutInflater.from(mContext).inflate(R.layout.item_beauty, parent, false);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
final BeautyData beautyData = data.get(position);
holder.icon.setImageResource(beautyData.icon);
holder.title.setText(beautyData.text);
if (mSelectPos == position) {
holder.title.setTextColor(mTextColorPrimary);
} else {
holder.title.setTextColor(Color.WHITE);
}
convertView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mItemClickListener != null) {
mItemClickListener.onItemClick(beautyData, position);
}
if (mSelectPos != position) {
mSelectPos = position;
notifyDataSetChanged();
}
}
});
return convertView;
}
public void setOnItemClickListener(BeautyPanel.OnItemClickListener itemClickListener) {
mItemClickListener = itemClickListener;
}
public void setTextColor(int colorPrimary) {
mTextColorPrimary = colorPrimary;
}
public class ViewHolder extends RecyclerView.ViewHolder {
private ImageView icon;
private TextView title;
public ViewHolder(View itemView) {
super(itemView);
icon = (ImageView) itemView.findViewById(R.id.icon);
title = (TextView) itemView.findViewById(R.id.title);
}
}
}
package com.tencent.liteav.demo.beauty;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import java.io.File;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* 美颜模块素材下载
*/
public class MaterialDownloader {
private Context mContext;
public static final String DOWNLOAD_FILE_POSTFIX = ".zip";
public static final String ONLINE_MATERIAL_FOLDER = "cameraVideoAnimal";
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
private boolean mProcessing;
private String mUrl;
private Downloadlistener mListener;
private DownloadThreadPool mDownloadThreadPool;
private String mMaterialId;
public MaterialDownloader(Context context, String materialId, String url) {
mContext = context;
mMaterialId = materialId;
mUrl = url;
mProcessing = false;
}
public void start(@Nullable Downloadlistener listener) {
if (listener == null || TextUtils.isEmpty(mUrl) || mProcessing) {
return;
}
mProcessing = true;
mListener = listener;
mListener.onDownloadProgress(0);
HttpFileListener fileListener = new HttpFileListener() {
@Override
public void onSaveSuccess(@NonNull File file) {
//删除该素材目录下的旧文件
File path = new File(file.toString().substring(0, file.toString().indexOf(DOWNLOAD_FILE_POSTFIX)));
if (path.exists() && path.isDirectory()) {
File[] oldFiles = path.listFiles();
if (oldFiles != null) {
for (File f : oldFiles) {
f.delete();
}
}
}
String dataDir = VideoUtil.unZip(file.getPath(), file.getParentFile().getPath());
if (TextUtils.isEmpty(dataDir)) {
mListener.onDownloadFail(mContext.getString(R.string.video_material_download_progress_material_unzip_failed));
stop();
return;
}
file.delete();
mListener.onDownloadSuccess(dataDir);
stop();
}
@Override
public void onSaveFailed(File file, Exception e) {
mListener.onDownloadFail(mContext.getString(R.string.video_material_download_progress_download_failed));
stop();
}
@Override
public void onProgressUpdate(int progress) {
mListener.onDownloadProgress(progress);
}
@Override
public void onProcessEnd() {
mProcessing = false;
}
};
File onlineMaterialDir = VideoDeviceUtil.getExternalFilesDir(mContext, ONLINE_MATERIAL_FOLDER);
if (onlineMaterialDir == null || onlineMaterialDir.getName().startsWith("null")) {
mListener.onDownloadFail(mContext.getString(R.string.video_material_download_progress_no_enough_storage_space));
stop();
return;
}
if (!onlineMaterialDir.exists()) {
onlineMaterialDir.mkdirs();
}
ThreadPoolExecutor threadPool = getThreadExecutor();
threadPool.execute(new HttpFileUtil(mContext, mUrl, onlineMaterialDir.getPath(), mMaterialId + DOWNLOAD_FILE_POSTFIX, fileListener, true));
}
public void stop() {
mListener = null;
}
public synchronized ThreadPoolExecutor getThreadExecutor() {
if (mDownloadThreadPool == null || mDownloadThreadPool.isShutdown()) {
mDownloadThreadPool = new DownloadThreadPool(CORE_POOL_SIZE);
}
return mDownloadThreadPool;
}
public static class DownloadThreadPool extends ThreadPoolExecutor {
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
public DownloadThreadPool(int poolSize) {
super(poolSize, poolSize, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingDeque<Runnable>(),
Executors.defaultThreadFactory(), new DiscardOldestPolicy());
}
}
}
package com.tencent.liteav.demo.beauty;
public class MotionData {
public String mMotionId;
public String mMotionName;
public String mMotionUrl;
public String mMotionPath;
public MotionData(String motionId, String motionName, String motionUrl, String motionPath) {
mMotionId = motionId;
mMotionName = motionName;
mMotionUrl = motionUrl;
mMotionPath = motionPath;
}
}
package com.tencent.liteav.demo.beauty;
import android.content.Context;
import android.database.DataSetObserver;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Adapter;
public class TCHorizontalScrollView extends android.widget.HorizontalScrollView {
private DataSetObserver mObserver;
private Adapter mAdapter;
public TCHorizontalScrollView(Context context) {
super(context);
initialize();
}
public TCHorizontalScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
initialize();
}
public TCHorizontalScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initialize();
}
public void setAdapter(Adapter adapter) {
if (mAdapter != null) {
mAdapter.unregisterDataSetObserver(mObserver);
}
mAdapter = adapter;
mAdapter.registerDataSetObserver(mObserver);
updateAdapter();
}
private void updateAdapter() {
ViewGroup group = (ViewGroup) getChildAt(0);
group.removeAllViews();
for (int i = 0; i < mAdapter.getCount(); i++) {
View view = mAdapter.getView(i, null, group);
group.addView(view);
}
}
void initialize() {
mObserver = new DataSetObserver() {
@Override
public void onChanged() {
super.onChanged();
updateAdapter();
}
@Override
public void onInvalidated() {
super.onInvalidated();
((ViewGroup) getChildAt(0)).removeAllViews();
}
};
}
public void setClicked(int position) {
((ViewGroup) getChildAt(0)).getChildAt(position).performClick();
}
}
\ No newline at end of file
package com.tencent.liteav.demo.beauty;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
/**
* 属性管理
*/
public class UIAttributeUtil {
/**
* 获取主题设置的图片资源的drawable
*
* @param context context
* @param attrId style-attr对应的id
* @param defaultResourceId 默认的图片id
* @return Drawable
*/
public static Drawable getDrawableResources(Context context, int attrId, int defaultResourceId) {
TypedArray a = context.obtainStyledAttributes(new int[]{attrId});
int resourceId = a.getResourceId(0, defaultResourceId);
Drawable drawable = context.getResources().getDrawable(resourceId);
a.recycle();
return drawable;
}
public static int getColorRes(Context context, int attrId, int defaultColorId) {
TypedArray a = context.obtainStyledAttributes(new int[]{attrId});
int color = a.getColor(0, context.getResources().getColor(defaultColorId));
a.recycle();
return color;
}
public static int getTextSizeResources(Context context, int attrId, int defaultTextSize) {
TypedArray a = context.obtainStyledAttributes(new int[]{attrId});
int textSize = a.getDimensionPixelOffset(0, defaultTextSize);
a.recycle();
return textSize;
}
public static int getResResources(Context context, int attrId, int defaultResourceId) {
TypedArray a = context.obtainStyledAttributes(new int[]{attrId});
int resourceId = a.getResourceId(0, defaultResourceId);
a.recycle();
return resourceId;
}
public static int[] getResResourcsArray(Context context, int[] attrId, int[] defaultResourceId) {
int[] resourceIdArray = new int[attrId.length];
TypedArray a = context.obtainStyledAttributes(attrId);
for (int i = 0; i < attrId.length; i++) {
resourceIdArray[i] = a.getResourceId(i, defaultResourceId[i]);
}
a.recycle();
return resourceIdArray;
}
}
package com.tencent.liteav.demo.beauty;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import java.io.File;
public class VideoDeviceUtil {
private static final String TAG = "VideoDeviceUtil";
public VideoDeviceUtil() {
}
public static boolean isNetworkAvailable(@NonNull Context context) {
ConnectivityManager connectivity = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivity == null) {
return false;
} else {
NetworkInfo networkInfo = connectivity.getActiveNetworkInfo();
return networkInfo != null && networkInfo.isConnectedOrConnecting();
}
}
@Nullable
public static File getExternalFilesDir(@NonNull Context context, String folder) {
if (context == null) {
Log.e(TAG, "getExternalFilesDir context is null");
return null;
}
File sdcardDir = context.getApplicationContext().getExternalFilesDir(null);
if (sdcardDir == null) {
Log.e(TAG, "sdcardDir is null");
return null;
}
String path = sdcardDir.getPath();
File file = new File(path + File.separator + folder);
try {
if (file.exists() && file.isFile()) {
file.delete();
}
if (!file.exists()) {
file.mkdirs();
}
} catch (Exception var5) {
var5.printStackTrace();
}
return file;
}
}
package com.tencent.liteav.demo.beauty;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Collection;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class VideoUtil {
private static final String TAG = "VideoUtil";
public VideoUtil() {
}
public static boolean isEmpty(@Nullable Collection object) {
return null == object || object.isEmpty();
}
public static synchronized String unZip(@NonNull String zipFile, @NonNull String targetDir) {
if (TextUtils.isEmpty(zipFile)) {
return null;
} else {
File file = new File(zipFile);
if (!file.exists()) {
return null;
} else {
File targetFolder = new File(targetDir);
if (!targetFolder.exists()) {
targetFolder.mkdirs();
}
String dataDir = null;
short BUFFER = 4096;
FileInputStream fis = null;
ZipInputStream zis = null;
FileOutputStream fos = null;
BufferedOutputStream dest = null;
try {
fis = new FileInputStream(file);
zis = new ZipInputStream(new BufferedInputStream(fis));
while (true) {
while (true) {
String strEntry;
ZipEntry entry;
do {
if ((entry = zis.getNextEntry()) == null) {
return dataDir;
}
strEntry = entry.getName();
} while (strEntry.contains("../"));
if (entry.isDirectory()) {
String count1 = targetDir + File.separator + strEntry;
File data1 = new File(count1);
if (!data1.exists()) {
data1.mkdirs();
}
if (TextUtils.isEmpty(dataDir)) {
dataDir = data1.getPath();
}
} else {
byte[] data = new byte[BUFFER];
String targetFileDir = targetDir + File.separator + strEntry;
File targetFile = new File(targetFileDir);
try {
fos = new FileOutputStream(targetFile);
dest = new BufferedOutputStream(fos, BUFFER);
int count;
while ((count = zis.read(data)) != -1) {
dest.write(data, 0, count);
}
dest.flush();
} catch (IOException var41) {
var41.printStackTrace();
} finally {
try {
if (dest != null) {
dest.close();
}
if (fos != null) {
fos.close();
}
} catch (IOException var40) {
var40.printStackTrace();
}
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (zis != null) {
zis.close();
}
if (fis != null) {
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return dataDir;
}
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<rotate
android:duration="1500"
android:fromDegrees="0"
android:interpolator="@android:anim/linear_interpolator"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="-1"
android:repeatMode="restart"
android:startOffset="-1"
android:toDegrees="+360" />
</set>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment