补充注释及移除部分未用到代码

This commit is contained in:
zlzw 2022-09-22 13:35:45 +08:00
parent d2bb4e4375
commit 1e98de9931
27 changed files with 87 additions and 2387 deletions

View File

@ -17,8 +17,10 @@ import com.faceunity.core.callback.OperateCallback;
import com.faceunity.core.entity.FURenderOutputData; import com.faceunity.core.entity.FURenderOutputData;
import com.faceunity.core.enumeration.CameraFacingEnum; import com.faceunity.core.enumeration.CameraFacingEnum;
import com.faceunity.core.enumeration.FUAIProcessorEnum; import com.faceunity.core.enumeration.FUAIProcessorEnum;
import com.faceunity.core.enumeration.FUAITypeEnum;
import com.faceunity.core.enumeration.FUInputTextureEnum; import com.faceunity.core.enumeration.FUInputTextureEnum;
import com.faceunity.core.enumeration.FUTransformMatrixEnum; import com.faceunity.core.enumeration.FUTransformMatrixEnum;
import com.faceunity.core.faceunity.FUAIKit;
import com.faceunity.core.faceunity.FURenderManager; import com.faceunity.core.faceunity.FURenderManager;
import com.faceunity.core.utils.CameraUtils; import com.faceunity.core.utils.CameraUtils;
import com.faceunity.core.utils.FULogger; import com.faceunity.core.utils.FULogger;
@ -41,7 +43,7 @@ import cn.rongcloud.rtc.api.callback.IRCRTCVideoOutputFrameListener;
import cn.rongcloud.rtc.base.RCRTCVideoFrame; import cn.rongcloud.rtc.base.RCRTCVideoFrame;
/** /**
* 美颜模块管理类接入测试中 * 美颜模块管理类
*/ */
public class FaceManager implements SensorEventListener { public class FaceManager implements SensorEventListener {
private static boolean isInit = false; private static boolean isInit = false;
@ -75,7 +77,6 @@ public class FaceManager implements SensorEventListener {
} }
private FURenderer mFURenderer; private FURenderer mFURenderer;
private FaceUnityView faceUnityView;
/** /**
* 配置美颜SDK * 配置美颜SDK
@ -98,13 +99,8 @@ public class FaceManager implements SensorEventListener {
} }
/** /**
* 绑定控制view * 监听人脸识别个数
*/ */
public void bindControlView(FaceUnityView view) {
this.faceUnityView = view;
faceUnityView.bindDataFactory(mFaceUnityDataFactory);
}
public void setFaceStatusChanged(FaceStatusChanged faceStatusChanged) { public void setFaceStatusChanged(FaceStatusChanged faceStatusChanged) {
this.faceStatusChanged = faceStatusChanged; this.faceStatusChanged = faceStatusChanged;
} }
@ -220,6 +216,21 @@ public class FaceManager implements SensorEventListener {
RCRTCEngine.getInstance().getDefaultVideoStream().setVideoFrameListener(null); RCRTCEngine.getInstance().getDefaultVideoStream().setVideoFrameListener(null);
} }
/**
* 释放资源
*/
public void release() {
mFURenderer.release();
try {
for (FUAITypeEnum value : FUAITypeEnum.values()) {
FUAIKit.getInstance().releaseAIProcessor(value);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public interface FaceStatusChanged { public interface FaceStatusChanged {
void onFaceChanged(int num); void onFaceChanged(int num);
} }

View File

@ -39,6 +39,9 @@ import com.yunbao.faceunity.utils.FaceSPUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
/**
* 美颜配置适配器
*/
public class ContainerRecyclerAdapter extends RecyclerView.Adapter<BaseViewHolder> { public class ContainerRecyclerAdapter extends RecyclerView.Adapter<BaseViewHolder> {
private Context mContext; private Context mContext;
@ -223,18 +226,30 @@ public class ContainerRecyclerAdapter extends RecyclerView.Adapter<BaseViewHolde
} }
/**
* 保存配置
*/
public void save(String key, String data) { public void save(String key, String data) {
FaceSPUtils.getInstance().saveString(key, data); FaceSPUtils.getInstance().saveString(key, data);
} }
/**
* 读取配置
*/
public String getString(String key) { public String getString(String key) {
return FaceSPUtils.getInstance().getString(key); return FaceSPUtils.getInstance().getString(key);
} }
/**
* 删除配置
*/
public void del(String key) { public void del(String key) {
FaceSPUtils.getInstance().del(key); FaceSPUtils.getInstance().del(key);
} }
/**
* 恢复默认设置
*/
public void reset() { public void reset() {
if (vh != null) { if (vh != null) {
vh.reset(list); vh.reset(list);

View File

@ -16,6 +16,9 @@ import com.yunbao.faceunity.entity.MenuGroupBean;
import java.util.List; import java.util.List;
/**
* 主菜单适配器
*/
public class MenuGroupRecyclerAdapter extends RecyclerView.Adapter<MenuGroupRecyclerAdapter.Vh> { public class MenuGroupRecyclerAdapter extends RecyclerView.Adapter<MenuGroupRecyclerAdapter.Vh> {
private Context context; private Context context;
private List<MenuGroupBean> list; private List<MenuGroupBean> list;

View File

@ -33,8 +33,20 @@ public abstract class BaseViewHolder extends RecyclerView.ViewHolder {
public abstract void setData(BaseBean data); public abstract void setData(BaseBean data);
/**
* 读取配置
* @return 是否有保存的配置
*/
public abstract boolean loadData(); public abstract boolean loadData();
/**
* 保存配置
*/
public abstract void saveData(); public abstract void saveData();
/**
* 恢复默认配置
*/
public abstract void reset(List<? extends BaseBean> list); public abstract void reset(List<? extends BaseBean> list);

View File

@ -1,57 +0,0 @@
package com.yunbao.faceunity.base;
import android.view.View;
/**
* DESCRecycleView 通用业务调用
* Created on 2021/4/26
*/
public abstract class BaseDelegate<T> {
/**
* 根据页面以及数据内容返回Item的布局index,默认返回第一个布局
*
* @param data
* @param position
* @return
*/
public int getItemViewType(T data, int position) {
return 0;
}
/**
* 为ViewHolder绑定数据item
*
* @param viewType
* @param helper
* @param data
* @param position
* @return
*/
public abstract void convert(int viewType, BaseViewHolder helper, T data, int position);
/**
* 绑定单击事件
*
* @param view
* @param data
* @param position
*/
public void onItemClickListener(View view, T data, int position) {
}
/**
* 绑定长按事件
*
* @param view
* @param data
* @param position
*/
public boolean onItemLongClickListener(View view, T data, int position) {
return false;
}
}

View File

@ -1,101 +0,0 @@
package com.yunbao.faceunity.base;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.yunbao.faceunity.listener.OnMultiClickListener;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.HashMap;
/**
* DESCRecycleView 通用适配器
* Created on 2021/4/26
*/
public class BaseListAdapter<T> extends RecyclerView.Adapter<BaseViewHolder> {
private ArrayList<T> data;
private BaseDelegate<T> viewHolderDelegate;
private int[] mLayouts;
private HashMap<Integer, BaseViewHolder> mViewHolder = new HashMap<>();
public BaseListAdapter(ArrayList<T> data, BaseDelegate<T> viewHolderDelegate, int... resLayouts) {
mLayouts = resLayouts;
this.data = data;
this.viewHolderDelegate = viewHolderDelegate;
}
@NonNull
@Override
public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(getLayoutId(viewType), viewGroup, false);
return new BaseViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull BaseViewHolder holder, int position) {
mViewHolder.put(position, holder);
viewHolderDelegate.convert(getItemViewType(position), holder, data.get(position), position);
bindViewClickListener(holder, position);
}
@Override
public int getItemCount() {
return data.size();
}
public void setData(ArrayList<T> items) {
data.clear();
data.addAll(items);
notifyDataSetChanged();
}
public T getData(int position) {
return data.get(position);
}
public BaseViewHolder getViewHolderByPosition(int position) {
if (!mViewHolder.containsKey(position)) {
return null;
}
return mViewHolder.get(position);
}
public View getViewByPosition(int position) {
if (mViewHolder.get(position) == null) {
return null;
}
return mViewHolder.get(position).itemView;
}
private void bindViewClickListener(BaseViewHolder holder, int position) {
View view = holder.itemView;
view.setOnClickListener(new OnMultiClickListener() {
@Override
protected void onMultiClick(@Nullable View v) {
viewHolderDelegate.onItemClickListener(view, data.get(position), position);
}
});
view.setOnLongClickListener(v -> viewHolderDelegate.onItemLongClickListener(view, data.get(position), position));
}
@Override
public int getItemViewType(int position) {
return viewHolderDelegate.getItemViewType(data.get(position), position);
}
private int getLayoutId(int viewType) {
return mLayouts[viewType];
}
}

View File

@ -1,361 +0,0 @@
package com.yunbao.faceunity.base;
import android.graphics.Bitmap;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.text.util.Linkify;
import android.util.SparseArray;
import android.view.View;
import android.view.animation.AlphaAnimation;
import android.widget.Checkable;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.RatingBar;
import android.widget.TextView;
import androidx.annotation.ColorInt;
import androidx.annotation.DrawableRes;
import androidx.annotation.IdRes;
import androidx.annotation.StringRes;
import androidx.recyclerview.widget.RecyclerView;
/**
* DESCDESC控件布局绑定
* Created on 2021/4/26
*/
public class BaseViewHolder extends RecyclerView.ViewHolder {
private SparseArray views;
/**
* use itemView instead
*/
private View convertView;
public BaseViewHolder(final View itemView) {
super(itemView);
this.views = new SparseArray<>();
convertView = itemView;
}
/**
* use itemView instead
*
* @return the ViewHolder root view
*/
@Deprecated
public View getConvertView() {
return convertView;
}
/**
* Will set the text of a TextView.
*
* @param viewId The view id.
* @param value The text to put in the text view.
* @return The BaseViewHolder for chaining.
*/
public BaseViewHolder setText(@IdRes int viewId, CharSequence value) {
TextView view = getView(viewId);
view.setText(value);
return this;
}
public BaseViewHolder setText(@IdRes int viewId, @StringRes int strId) {
TextView view = getView(viewId);
view.setText(strId);
return this;
}
/**
* Will set the image of an ImageView from a resource id.
*
* @param viewId The view id.
* @param imageResId The image resource id.
* @return The BaseViewHolder for chaining.
*/
public BaseViewHolder setImageResource(@IdRes int viewId, @DrawableRes int imageResId) {
ImageView view = getView(viewId);
view.setImageResource(imageResId);
return this;
}
/**
* Will set background color of a view.
*
* @param viewId The view id.
* @param color A color, not a resource id.
* @return The BaseViewHolder for chaining.
*/
public BaseViewHolder setBackgroundColor(@IdRes int viewId, @ColorInt int color) {
View view = getView(viewId);
view.setBackgroundColor(color);
return this;
}
/**
* Will set background of a view.
*
* @param viewId The view id.
* @param backgroundRes A resource to use as a background.
* @return The BaseViewHolder for chaining.
*/
public BaseViewHolder setBackgroundRes(@IdRes int viewId, @DrawableRes int backgroundRes) {
View view = getView(viewId);
view.setBackgroundResource(backgroundRes);
return this;
}
/**
* Will set text color of a TextView.
*
* @param viewId The view id.
* @param textColor The text color (not a resource id).
* @return The BaseViewHolder for chaining.
*/
public BaseViewHolder setTextColor(@IdRes int viewId, @ColorInt int textColor) {
TextView view = getView(viewId);
view.setTextColor(textColor);
return this;
}
/**
* Will set the image of an ImageView from a drawable.
*
* @param viewId The view id.
* @param drawable The image drawable.
* @return The BaseViewHolder for chaining.
*/
public BaseViewHolder setImageDrawable(@IdRes int viewId, Drawable drawable) {
ImageView view = getView(viewId);
view.setImageDrawable(drawable);
return this;
}
/**
* Add an action to set the image of an image view. Can be called multiple times.
*/
public BaseViewHolder setImageBitmap(@IdRes int viewId, Bitmap bitmap) {
ImageView view = getView(viewId);
view.setImageBitmap(bitmap);
return this;
}
/**
* Add an action to set the alpha of a view. Can be called multiple times.
* Alpha between 0-1.
*/
public BaseViewHolder setAlpha(@IdRes int viewId, float value) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
getView(viewId).setAlpha(value);
} else {
// Pre-honeycomb hack to set Alpha value
AlphaAnimation alpha = new AlphaAnimation(value, value);
alpha.setDuration(0);
alpha.setFillAfter(true);
getView(viewId).startAnimation(alpha);
}
return this;
}
/**
* Set a view visibility to VISIBLE (true) or GONE (false).
*
* @param viewId The view id.
* @param visible True for VISIBLE, false for GONE.
* @return The BaseViewHolder for chaining.
*/
public BaseViewHolder setGone(@IdRes int viewId, boolean visible) {
View view = getView(viewId);
view.setVisibility(visible ? View.VISIBLE : View.GONE);
return this;
}
/**
* Set a view visibility to VISIBLE (true) or INVISIBLE (false).
*
* @param viewId The view id.
* @param visible True for VISIBLE, false for INVISIBLE.
* @return The BaseViewHolder for chaining.
*/
public BaseViewHolder setVisible(@IdRes int viewId, boolean visible) {
View view = getView(viewId);
view.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
return this;
}
/**
* Add links into a TextView.
*
* @param viewId The id of the TextView to linkify.
* @return The BaseViewHolder for chaining.
*/
public BaseViewHolder linkify(@IdRes int viewId) {
TextView view = getView(viewId);
Linkify.addLinks(view, Linkify.ALL);
return this;
}
/**
* Apply the typeface to the given viewId, and enable subpixel rendering.
*/
public BaseViewHolder setTypeface(@IdRes int viewId, Typeface typeface) {
TextView view = getView(viewId);
view.setTypeface(typeface);
view.setPaintFlags(view.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG);
return this;
}
/**
* Apply the typeface to all the given viewIds, and enable subpixel rendering.
*/
public BaseViewHolder setTypeface(Typeface typeface, int... viewIds) {
for (int viewId : viewIds) {
TextView view = getView(viewId);
view.setTypeface(typeface);
view.setPaintFlags(view.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG);
}
return this;
}
/**
* Sets the progress of a ProgressBar.
*
* @param viewId The view id.
* @param progress The progress.
* @return The BaseViewHolder for chaining.
*/
public BaseViewHolder setProgress(@IdRes int viewId, int progress) {
ProgressBar view = getView(viewId);
view.setProgress(progress);
return this;
}
/**
* Sets the progress and max of a ProgressBar.
*
* @param viewId The view id.
* @param progress The progress.
* @param max The max value of a ProgressBar.
* @return The BaseViewHolder for chaining.
*/
public BaseViewHolder setProgress(@IdRes int viewId, int progress, int max) {
ProgressBar view = getView(viewId);
view.setMax(max);
view.setProgress(progress);
return this;
}
/**
* Sets the range of a ProgressBar to 0...max.
*
* @param viewId The view id.
* @param max The max value of a ProgressBar.
* @return The BaseViewHolder for chaining.
*/
public BaseViewHolder setMax(@IdRes int viewId, int max) {
ProgressBar view = getView(viewId);
view.setMax(max);
return this;
}
/**
* Sets the rating (the number of stars filled) of a RatingBar.
*
* @param viewId The view id.
* @param rating The rating.
* @return The BaseViewHolder for chaining.
*/
public BaseViewHolder setRating(@IdRes int viewId, float rating) {
RatingBar view = getView(viewId);
view.setRating(rating);
return this;
}
/**
* Sets the rating (the number of stars filled) and max of a RatingBar.
*
* @param viewId The view id.
* @param rating The rating.
* @param max The range of the RatingBar to 0...max.
* @return The BaseViewHolder for chaining.
*/
public BaseViewHolder setRating(@IdRes int viewId, float rating, int max) {
RatingBar view = getView(viewId);
view.setMax(max);
view.setRating(rating);
return this;
}
/**
* Sets the tag of the view.
*
* @param viewId The view id.
* @param tag The tag;
* @return The BaseViewHolder for chaining.
*/
public BaseViewHolder setTag(@IdRes int viewId, Object tag) {
View view = getView(viewId);
view.setTag(tag);
return this;
}
/**
* Sets the tag of the view.
*
* @param viewId The view id.
* @param key The key of tag;
* @param tag The tag;
* @return The BaseViewHolder for chaining.
*/
public BaseViewHolder setTag(@IdRes int viewId, int key, Object tag) {
View view = getView(viewId);
view.setTag(key, tag);
return this;
}
/**
* Sets the checked status of a checkable.
*
* @param viewId The view id.
* @param checked The checked status;
* @return The BaseViewHolder for chaining.
*/
public BaseViewHolder setChecked(@IdRes int viewId, boolean checked) {
View view = getView(viewId);
// View unable cast to Checkable
if (view instanceof Checkable) {
((Checkable) view).setChecked(checked);
}
return this;
}
/**
* Set the enabled state of this view.
*
* @param viewId The view id.
* @param enable The checked status;
* @return The BaseViewHolder for chaining.
*/
public BaseViewHolder setEnabled(@IdRes int viewId, boolean enable) {
View view = getView(viewId);
view.setEnabled(enable);
return this;
}
public <T extends View> T getView(int viewId) {
View view = (View) views.get(viewId);
if (view == null) {
view = itemView.findViewById(viewId);
views.put(viewId, view);
}
return (T) view;
}
}

View File

@ -1,149 +0,0 @@
package com.yunbao.faceunity.control
import android.animation.ValueAnimator
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.yunbao.faceunity.R
import com.yunbao.faceunity.base.BaseDelegate
import com.yunbao.faceunity.base.BaseListAdapter
import com.yunbao.faceunity.base.BaseViewHolder
import com.yunbao.faceunity.entity.AnimationFilterBean
import com.yunbao.faceunity.entity.AnimojiBean
import com.yunbao.faceunity.infe.AbstractAnimojiDataFactory
import kotlinx.android.synthetic.main.layout_animo_control.view.*
/**
*
* DESC
* Created on 2020/12/10
*
*/
class AnimojiControlView @JvmOverloads constructor(private val mContext: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :
BaseControlView(mContext, attrs, defStyleAttr) {
private lateinit var mDataFactory: AbstractAnimojiDataFactory
private lateinit var mAnimojiAdapter: BaseListAdapter<AnimojiBean>
private lateinit var mAnimationFilterAdapter: BaseListAdapter<AnimationFilterBean>
// region init
init {
LayoutInflater.from(context).inflate(R.layout.layout_animo_control, this)
initView()
initAdapter()
bindListener()
}
/**
* 给控制绑定AnimojiController数据工厂
*/
fun bindDataFactory(dataFactory: AbstractAnimojiDataFactory) {
mDataFactory = dataFactory
mAnimojiAdapter.setData(dataFactory.animojis)
mAnimationFilterAdapter.setData(dataFactory.filters)
}
/**
* 收回菜单栏
*/
fun hideControlView() {
rg_anim.check(View.NO_ID)
}
private fun initView() {
isBottomShow = true
initHorizontalRecycleView(recycler_view)
}
private fun initAdapter() {
mAnimojiAdapter = BaseListAdapter(ArrayList(), object : BaseDelegate<AnimojiBean>() {
override fun convert(viewType: Int, helper: BaseViewHolder, data: AnimojiBean, position: Int) {
helper.setImageResource(R.id.iv_control, data.iconId)
helper.itemView.isSelected = position == mDataFactory.currentAnimojiIndex
}
override fun onItemClickListener(view: View, data: AnimojiBean, position: Int) {
if (mDataFactory.currentAnimojiIndex != position) {
changeAdapterSelected(mAnimojiAdapter, mDataFactory.currentAnimojiIndex, position)
mDataFactory.currentAnimojiIndex = position
mDataFactory.onAnimojiSelected(data)
}
}
}, R.layout.list_item_control_image_circle)
recycler_view.adapter = mAnimojiAdapter
mAnimationFilterAdapter = BaseListAdapter(ArrayList(), object : BaseDelegate<AnimationFilterBean>() {
override fun convert(viewType: Int, helper: BaseViewHolder, data: AnimationFilterBean, position: Int) {
helper.setImageResource(R.id.iv_control, data.iconId)
helper.itemView.isSelected = position == mDataFactory.currentFilterIndex
}
override fun onItemClickListener(view: View, data: AnimationFilterBean, position: Int) {
if (mDataFactory.currentFilterIndex != position) {
changeAdapterSelected(mAnimationFilterAdapter, mDataFactory.currentFilterIndex, position)
mDataFactory.currentFilterIndex = position
mDataFactory.onFilterSelected(data)
}
}
}, R.layout.list_item_control_image_circle)
}
private fun bindListener() {
rg_anim.setOnCheckedChangeListener { _, checkedId ->
when (checkedId) {
R.id.cb_animoji -> {
changeBottomLayoutAnimator(true)
recycler_view.adapter = mAnimojiAdapter
}
R.id.cb_filter -> {
changeBottomLayoutAnimator(true)
recycler_view.adapter = mAnimationFilterAdapter
}
else -> {
changeBottomLayoutAnimator(false)
}
}
}
}
// endregion
/**
* 底部动画处理
* @param isOpen Boolean
*/
private fun changeBottomLayoutAnimator(isOpen: Boolean) {
if (isOpen == isBottomShow) {
return
}
val start = if (isOpen) resources.getDimensionPixelSize(R.dimen.x98) else resources.getDimensionPixelSize(R.dimen.x266)
val end = if (isOpen) resources.getDimensionPixelSize(R.dimen.x266) else resources.getDimensionPixelSize(R.dimen.x98)
if (bottomLayoutAnimator != null && bottomLayoutAnimator!!.isRunning) {
bottomLayoutAnimator!!.end()
}
bottomLayoutAnimator = ValueAnimator.ofInt(start, end).setDuration(150)
bottomLayoutAnimator!!.addUpdateListener { animation ->
val height = animation.animatedValue as Int
val params = lyt_bottom.layoutParams as ViewGroup.LayoutParams
params.height = height
lyt_bottom.layoutParams = params
if (onBottomAnimatorChangeListener != null) {
val showRate = 1.0f * (height - start) / (end - start)
onBottomAnimatorChangeListener?.onBottomAnimatorChangeListener(if (!isOpen) 1 - showRate else showRate)
}
}
bottomLayoutAnimator!!.start()
isBottomShow = isOpen
}
}

View File

@ -1,98 +0,0 @@
package com.yunbao.faceunity.control;
import android.animation.ValueAnimator;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.SimpleItemAnimator;
import com.yunbao.faceunity.base.BaseListAdapter;
import com.yunbao.faceunity.dialog.BaseDialogFragment;
import com.yunbao.faceunity.dialog.ConfirmDialogFragment;
import com.yunbao.faceunity.listener.OnBottomAnimatorChangeListener;
/**
* DESC自定义菜单Base类
* Created on 2021/4/26
*/
public abstract class BaseControlView extends FrameLayout {
protected Context mContext;
public BaseControlView(@NonNull Context context) {
super(context);
mContext = context;
}
public BaseControlView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mContext = context;
}
public BaseControlView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
}
/**
* adapter单项点击选中状态变更
*
* @param adapter BaseListAdapter<T>
* @param old nt
* @param position Int
*/
protected <T> void changeAdapterSelected(BaseListAdapter<T> adapter, int old, int position) {
if (old >= 0 && adapter.getViewByPosition(old) != null) {
adapter.getViewByPosition(old).setSelected(false);
}
if (position >= 0 && adapter.getViewByPosition(position) != null) {
adapter.getViewByPosition(position).setSelected(true);
}
}
/**
* 显示弹框
*
* @param tip
* @param runnable
*/
protected void showDialog(String tip, Runnable runnable) {
ConfirmDialogFragment confirmDialogFragment = ConfirmDialogFragment.newInstance(tip, new BaseDialogFragment.OnClickListener() {
@Override
public void onConfirm() {
runnable.run();
}
@Override
public void onCancel() {
}
});
confirmDialogFragment.show(((FragmentActivity) mContext).getSupportFragmentManager(), "ConfirmDialogFragmentReset");
}
protected void initHorizontalRecycleView(RecyclerView recyclerView) {
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.HORIZONTAL, false));
((SimpleItemAnimator) recyclerView.getItemAnimator()).setSupportsChangeAnimations(false);
}
/****************************************菜单动画*****************************************************/
protected boolean isBottomShow;
protected ValueAnimator bottomLayoutAnimator = null;
protected OnBottomAnimatorChangeListener onBottomAnimatorChangeListener = null;
}

View File

@ -1,205 +0,0 @@
package com.yunbao.faceunity.control
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import com.faceunity.core.utils.DecimalUtils
import com.yunbao.faceunity.R
import com.yunbao.faceunity.base.BaseDelegate
import com.yunbao.faceunity.base.BaseListAdapter
import com.yunbao.faceunity.base.BaseViewHolder
import com.yunbao.faceunity.entity.BodyBeautyBean
import com.yunbao.faceunity.entity.ModelAttributeData
import com.yunbao.faceunity.infe.AbstractBodyBeautyDataFactory
import com.yunbao.faceunity.seekbar.DiscreteSeekBar
import kotlinx.android.synthetic.main.layout_body_beauty_control.view.*
/**
*
* DESC美体
* Created on 2020/12/11
*
*/
class BodyBeautyControlView @JvmOverloads constructor(private val mContext: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :
BaseControlView(mContext, attrs, defStyleAttr) {
private lateinit var mDataFactory: AbstractBodyBeautyDataFactory
private lateinit var mModelAttributeRange: HashMap<String, ModelAttributeData>
private lateinit var mBodyBeautyBeans: ArrayList<BodyBeautyBean>
private lateinit var mBodyAdapter: BaseListAdapter<BodyBeautyBean>
private var mBodyIndex = 0
// region init
init {
LayoutInflater.from(context).inflate(R.layout.layout_body_beauty_control, this)
initView()
initAdapter()
bindListener()
}
fun bindDataFactory(dataFactory: AbstractBodyBeautyDataFactory) {
mDataFactory = dataFactory
mBodyBeautyBeans = mDataFactory.bodyBeautyParam
mBodyAdapter.setData(mBodyBeautyBeans)
mModelAttributeRange = mDataFactory.modelAttributeRange
val data = mBodyBeautyBeans[mBodyIndex]
val value = mDataFactory.getParamIntensity(data.key)
val stand = mModelAttributeRange[data.key]!!.stand
val maxRange = mModelAttributeRange[data.key]!!.maxRange
seekToSeekBar(value, stand, maxRange)
setRecoverEnable(checkParamsChanged())
}
private fun initView() {
initHorizontalRecycleView(recycler_view)
}
private fun initAdapter() {
mBodyAdapter = BaseListAdapter(ArrayList(), object : BaseDelegate<BodyBeautyBean>() {
override fun convert(viewType: Int, helper: BaseViewHolder, data: BodyBeautyBean, position: Int) {
helper.setText(R.id.tv_control, data.desRes)
val value = mDataFactory.getParamIntensity(data.key)
val stand = mModelAttributeRange[data.key]!!.stand
if (DecimalUtils.doubleEquals(value, stand)) {
helper.setImageResource(R.id.iv_control, data.closeRes)
} else {
helper.setImageResource(R.id.iv_control, data.openRes)
}
helper.itemView.isSelected = position == mBodyIndex
}
override fun onItemClickListener(view: View, data: BodyBeautyBean, position: Int) {
if (mBodyIndex != position) {
changeAdapterSelected(mBodyAdapter, mBodyIndex, position)
mBodyIndex = position
val value = mDataFactory.getParamIntensity(data.key)
val stand = mModelAttributeRange[data.key]!!.stand
val maxRange = mModelAttributeRange[data.key]!!.maxRange
seekToSeekBar(value, stand, maxRange)
}
}
}, R.layout.list_item_control_title_image_circle)
recycler_view.adapter = mBodyAdapter
}
private fun bindListener() {
cyt_main.setOnTouchListener { _, _ -> true }
beauty_seek_bar.setOnProgressChangeListener(object : DiscreteSeekBar.OnSimpleProgressChangeListener() {
override fun onProgressChanged(seekBar: DiscreteSeekBar?, value: Int, fromUser: Boolean) {
if (!fromUser) {
return
}
val valueF = 1.0 * (value - seekBar!!.min) / 100
val data = mBodyBeautyBeans[mBodyIndex]
val value = mDataFactory.getParamIntensity(data.key)
val range = mModelAttributeRange[data.key]!!.maxRange
val res = valueF * range
if (!DecimalUtils.doubleEquals(res, value)) {
mDataFactory.updateParamIntensity(data.key, res)
setRecoverEnable(checkParamsChanged())
updateBeautyItemUI(mBodyAdapter.getViewHolderByPosition(mBodyIndex), data)
}
}
})
lyt_beauty_recover.setOnClickListener {
showDialog(mContext.getString(R.string.dialog_reset_avatar_model)) {
recoverData()
}
}
}
/**
* 设置滚动条数值
*/
private fun seekToSeekBar(value: Double, stand: Double, range: Double) {
if (stand == 0.5) {
beauty_seek_bar.min = -50
beauty_seek_bar.max = 50
beauty_seek_bar.progress = (value * 100 / range - 50).toInt()
} else {
beauty_seek_bar.min = 0
beauty_seek_bar.max = 100
beauty_seek_bar.progress = (value * 100 / range).toInt()
}
beauty_seek_bar.visibility = View.VISIBLE
}
// endregion
/**
* 更新单项是否为基准值显示
*/
private fun updateBeautyItemUI(viewHolder: BaseViewHolder?, data: BodyBeautyBean) {
val value = mDataFactory.getParamIntensity(data.key)
val stand = mModelAttributeRange[data.key]!!.stand
if (DecimalUtils.doubleEquals(value, stand)) {
viewHolder?.setImageResource(R.id.iv_control, data.closeRes)
} else {
viewHolder?.setImageResource(R.id.iv_control, data.openRes)
}
}
private fun recoverData() {
mBodyBeautyBeans.forEach {
val default = mModelAttributeRange[it.key]!!.default
mDataFactory.updateParamIntensity(it.key, default)
}
val data = mBodyBeautyBeans[mBodyIndex]
val value = mDataFactory.getParamIntensity(data.key)
val stand = mModelAttributeRange[data.key]!!.stand
val maxRange = mModelAttributeRange[data.key]!!.maxRange
seekToSeekBar(value, stand, maxRange)
mBodyAdapter.notifyDataSetChanged()
setRecoverEnable(false)
}
/**
* 遍历数据确认还原按钮是否可以点击
* @return Boolean
*/
private fun checkParamsChanged(): Boolean {
var item = mBodyBeautyBeans[mBodyIndex]
var value = mDataFactory.getParamIntensity(item.key)
var default = mModelAttributeRange[item.key]!!.default
if (!DecimalUtils.doubleEquals(value, default)) {
return true
}
mBodyBeautyBeans.forEach {
value = mDataFactory.getParamIntensity(it.key)
default = mModelAttributeRange[it.key]!!.default
if (!DecimalUtils.doubleEquals(value, default)) {
return true
}
}
return false
}
/**
* 重置还原按钮状态
* @param enable Boolean
*/
private fun setRecoverEnable(enable: Boolean) {
if (enable) {
tv_beauty_recover.alpha = 1f
iv_beauty_recover.alpha = 1f
} else {
tv_beauty_recover.alpha = 0.6f
iv_beauty_recover.alpha = 0.6f
}
lyt_beauty_recover.isEnabled = enable
}
}

View File

@ -1,826 +0,0 @@
package com.yunbao.faceunity.control
import android.animation.ValueAnimator
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.animation.AlphaAnimation
import android.view.animation.Animation
import android.view.animation.AnimationSet
import android.view.animation.TranslateAnimation
import android.widget.ImageView
import android.widget.LinearLayout
import com.faceunity.core.utils.DecimalUtils
import com.yunbao.faceunity.R
import com.yunbao.faceunity.base.BaseDelegate
import com.yunbao.faceunity.base.BaseListAdapter
import com.yunbao.faceunity.base.BaseViewHolder
import com.yunbao.faceunity.dialog.ToastHelper
import com.yunbao.faceunity.entity.FaceBeautyBean
import com.yunbao.faceunity.entity.FaceBeautyFilterBean
import com.yunbao.faceunity.entity.FaceBeautyStyleBean
import com.yunbao.faceunity.entity.ModelAttributeData
import com.yunbao.faceunity.infe.AbstractFaceBeautyDataFactory
import com.yunbao.faceunity.seekbar.DiscreteSeekBar
import kotlinx.android.synthetic.main.layout_face_beauty_control.view.*
import kotlin.collections.set
/**
*
* DESC美颜
* Created on 2020/11/17
*
*/
class FaceBeautyControlView @JvmOverloads constructor(private val mContext: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :
BaseControlView(mContext, attrs, defStyleAttr) {
private lateinit var mDataFactory: AbstractFaceBeautyDataFactory
/* 美颜、美型 */
private lateinit var mModelAttributeRange: HashMap<String, ModelAttributeData>
private var mSkinBeauty = ArrayList<FaceBeautyBean>()
private var mShapeBeauty = ArrayList<FaceBeautyBean>()
private var mShapeBeautySubItem = ArrayList<FaceBeautyBean>()
private var mSubItemUIValueCache: HashMap<String,Double> = HashMap()//美型子项脸型的UI缓存值
private var mSkinIndex = 0
private var mShapeIndex = 1
private var mIsOnBeautyShapeMain = true//美型是否在主项上
private lateinit var mBeautyAdapter: BaseListAdapter<FaceBeautyBean>
/* 滤镜 */
private var mFilters = ArrayList<FaceBeautyFilterBean>()
private lateinit var mFiltersAdapter: BaseListAdapter<FaceBeautyFilterBean>
/* 风格 */
private var mStyles = ArrayList<FaceBeautyStyleBean>()
private lateinit var mStylesAdapter: BaseListAdapter<FaceBeautyStyleBean>
private var mEnableBottomRationClick = true
// region init
init {
LayoutInflater.from(context).inflate(R.layout.layout_face_beauty_control, this)
initView()
initAdapter()
bindListener()
}
/**
* 给控制绑定FaceBeautyController数据工厂
* @param dataFactory IFaceBeautyDataFactory
*/
fun bindDataFactory(dataFactory: AbstractFaceBeautyDataFactory) {
mDataFactory = dataFactory
mModelAttributeRange = dataFactory.modelAttributeRange
mSkinBeauty = dataFactory.skinBeauty
mShapeBeauty = dataFactory.shapeBeauty
mShapeBeautySubItem = dataFactory.shapeBeautySubItem
mFilters = dataFactory.beautyFilters
mStyles = dataFactory.beautyStyles
mFiltersAdapter.setData(mFilters)
mStylesAdapter.setData(mStyles)
if (dataFactory.currentStyleIndex > -1) {
lyt_style_recover.isSelected = false
setBottomCheckRatioEnable(false)
var data = mStyles[dataFactory.currentStyleIndex]
mDataFactory.onStyleSelected(data.key)
} else {
lyt_style_recover.isSelected = true
setBottomCheckRatioEnable(true)
}
beauty_radio_group.check(View.NO_ID)
//恢复上一次脸型选项的UI值
mSubItemUIValueCache = mDataFactory.getCurrentFaceShapeUIValue()
}
/**
* 收回菜单栏
*/
fun hideControlView() {
beauty_radio_group.check(View.NO_ID)
}
/**
* View初始化
*/
private fun initView() {
initHorizontalRecycleView(recycler_view)
}
/**
* 构造Adapter
*/
private fun initAdapter() {
mStylesAdapter = BaseListAdapter(
ArrayList(), object : BaseDelegate<FaceBeautyStyleBean>() {
override fun convert(viewType: Int, helper: BaseViewHolder, data: FaceBeautyStyleBean, position: Int) {
helper.setText(R.id.tv_control, data.desRes)
helper.setImageResource(R.id.iv_control, data.imageRes)
helper.itemView.isSelected = mDataFactory.currentStyleIndex == position
}
override fun onItemClickListener(view: View, data: FaceBeautyStyleBean, position: Int) {
super.onItemClickListener(view, data, position)
if (mDataFactory.currentStyleIndex != position) {
lyt_style_recover.isSelected = false
setBottomCheckRatioEnable(false)
changeAdapterSelected(mStylesAdapter, mDataFactory.currentStyleIndex, position)
mDataFactory.currentStyleIndex = position
mDataFactory.onStyleSelected(data.key)
}
}
}, R.layout.list_item_control_title_image_circle
)
mFiltersAdapter = BaseListAdapter(
ArrayList(), object : BaseDelegate<FaceBeautyFilterBean>() {
override fun convert(viewType: Int, helper: BaseViewHolder, data: FaceBeautyFilterBean, position: Int) {
helper.setText(R.id.tv_control, data.desRes)
helper.setImageResource(R.id.iv_control, data.imageRes)
helper.itemView.isSelected = mDataFactory.currentFilterIndex == position
}
override fun onItemClickListener(view: View, data: FaceBeautyFilterBean, position: Int) {
super.onItemClickListener(view, data, position)
if (mDataFactory.currentFilterIndex != position) {
changeAdapterSelected(mFiltersAdapter, mDataFactory.currentFilterIndex, position)
mDataFactory.currentFilterIndex = position
mDataFactory.onFilterSelected(data.key, data.intensity, data.desRes)
if (position == 0) {
beauty_seek_bar.visibility = View.INVISIBLE
} else {
seekToSeekBar(data.intensity, 0.0, 1.0)
}
}
}
}, R.layout.list_item_control_title_image_square
)
mBeautyAdapter = BaseListAdapter(ArrayList(), object : BaseDelegate<FaceBeautyBean>() {
override fun convert(viewType: Int, helper: BaseViewHolder, data: FaceBeautyBean, position: Int) {
val isShinSelected = beauty_radio_group.checkedCheckBoxId == R.id.beauty_radio_skin_beauty
helper.itemView.isSelected = if (isShinSelected) mSkinIndex == position else mShapeIndex == position
helper.setText(R.id.tv_control, data.desRes)
//主项的时候才需要显示
// helper.setVisible(R.id.iv_oval_spot, !isShinSelected && mIsOnBeautyShapeMain && position ==0)
val value = mDataFactory.getParamIntensity(data.key)
when (data.buttonType) {
FaceBeautyBean.ButtonType.BACK_BUTTON -> {
helper.setImageResource(R.id.iv_control, data.closeRes)
}
FaceBeautyBean.ButtonType.SUB_ITEM_BUTTON -> {
//判断当前UI值 和 真实值是否全是空的如果是空的则不选中
//先过UI值
var choose = false
run outside@{
mSubItemUIValueCache.forEach {
if (it.value > 0) {
choose = true
}
}
mShapeBeautySubItem.forEach {
if (it.buttonType == FaceBeautyBean.ButtonType.NORMAL_BUTTON) {
if (mDataFactory.getParamIntensity(it.key) > 0) {
choose = true
}
}
}
}
helper.setImageResource(R.id.iv_control, if (choose) data.openRes else data.closeRes)
}
//普通按钮
else -> {
val stand = mModelAttributeRange[data.key]!!.stand
if (DecimalUtils.doubleEquals(value, stand)) {
helper.setImageResource(R.id.iv_control, data.closeRes)
} else {
helper.setImageResource(R.id.iv_control, data.openRes)
}
if (!data.canUseFunction) {
val ivControl = helper.getView<ImageView>(R.id.iv_control)
ivControl?.imageAlpha = 154
} else {
val ivControl = helper.getView<ImageView>(R.id.iv_control)
ivControl?.imageAlpha = 255
}
if (openEnterAnimation && needEnterAnimation && position != 0) {
enterAnimation(helper.itemView)
if (position >=4 || (mBeautyAdapter.itemCount < 5 && position == mBeautyAdapter.itemCount - 1)) {
needEnterAnimation = false
}
}
}
}
}
override fun onItemClickListener(view: View, data: FaceBeautyBean, position: Int) {
val isShinSelected = beauty_radio_group.checkedCheckBoxId == R.id.beauty_radio_skin_beauty
if ((isShinSelected && position == mSkinIndex) || (!isShinSelected && position == mShapeIndex)) {
return
}
if (!data.canUseFunction) {
ToastHelper.showNormalToast(mContext,data.toastDesRes)
return
}
if (isShinSelected) {
changeAdapterSelected(mBeautyAdapter, mSkinIndex, position)
val value = mDataFactory.getParamIntensity(data.key)
val stand = mModelAttributeRange[data.key]!!.stand
val maxRange = mModelAttributeRange[data.key]!!.maxRange
seekToSeekBar(value, stand, maxRange)
mSkinIndex = position
} else {
when (data.buttonType) {
FaceBeautyBean.ButtonType.BACK_BUTTON -> {
//返回按钮
mBeautyAdapter.setData(mShapeBeauty)
//没有按钮被选中,需要隐藏进度条
beauty_seek_bar.visibility = View.INVISIBLE
changeAdapterSelected(mBeautyAdapter, mShapeIndex, -1)
mShapeIndex = -1
mIsOnBeautyShapeMain = true
needEnterAnimation = true
}
FaceBeautyBean.ButtonType.SUB_ITEM_BUTTON -> {
//子项按钮
//选中的是哪一个子项 -> 在FaceBeauty中有记录
run outside@{
mShapeBeautySubItem.forEachIndexed{ index, value ->
if (mDataFactory.getCurrentOneHotFaceShape() == value.key) {//获取当前作用的脸型
mShapeIndex = index
return@outside
}
}
}
mBeautyAdapter.setData(mShapeBeautySubItem)
if (mShapeBeautySubItem.size >= 1) {
beauty_seek_bar.visibility = View.VISIBLE
val faceBeautyBean = mShapeBeautySubItem[mShapeIndex]
if (faceBeautyBean.buttonType == FaceBeautyBean.ButtonType.NORMAL_BUTTON) {
val value = mDataFactory.getParamIntensity(faceBeautyBean.key)
val stand = mModelAttributeRange[faceBeautyBean.key]!!.stand
val maxRange = mModelAttributeRange[faceBeautyBean.key]!!.maxRange
seekToSeekBar(value, stand, maxRange)
}
}
mIsOnBeautyShapeMain = false
needEnterAnimation = true
}
//普通按钮
else -> {
//点击的是子项普通按钮还是主项普通按钮1.子项普通之间按钮效果One Hot 2.主项普通按钮之间效果可叠加
beauty_seek_bar.visibility = View.VISIBLE
changeAdapterSelected(mBeautyAdapter, mShapeIndex, position)
//判断一下是子项还是主项1.主项直接设置改点击对象的值2.子项需要获取之前的缓存如果存在缓存设置回之前的值然后还要将上一个点击过的子项sdk值设置为零UI值进行缓存
var value:Double
if (mIsOnBeautyShapeMain) {
value = mDataFactory.getParamIntensity(data.key)
} else {
//子项 one hot + 如果有UI值显示UI值 -> 并将UI缓存值设置到SDK
value = if (mSubItemUIValueCache.contains(data.key)) {
var value = mSubItemUIValueCache[data.key]!!
mDataFactory.updateParamIntensity(data.key, value)
mSubItemUIValueCache.remove(data.key)!!
} else
mDataFactory.getParamIntensity(data.key)
//将上一个点击的有效项设置为空
if (mShapeIndex >= 0) {
var beforeData = mBeautyAdapter.getData(mShapeIndex)
when (beforeData.buttonType) {
FaceBeautyBean.ButtonType.NORMAL_BUTTON -> {
//算法值要设置为零但是点击回来的时候需要根据UI值(缓存值)重新设置回算法值
mSubItemUIValueCache[beforeData.key] = mDataFactory.getParamIntensity(beforeData.key)
mDataFactory.updateParamIntensity(beforeData.key,0.0)
}
}
}
mDataFactory.setCurrentOneHotFaceShape(data.key)
mBeautyAdapter.notifyItemChanged(mShapeIndex)
mBeautyAdapter.notifyItemChanged(position)
}
//设置当前点击bean的进度值
val stand = mModelAttributeRange[data.key]!!.stand
val maxRange = mModelAttributeRange[data.key]!!.maxRange
seekToSeekBar(value, stand, maxRange)
mShapeIndex = position
}
}
}
}
}, R.layout.list_item_control_title_image_circle)
}
/**
* 绑定监听事件
*/
private fun bindListener() {
/*拦截触碰事件*/
fyt_bottom_view.setOnTouchListener { _, _ -> true }
/*菜单控制*/
bindBottomRadioListener()
/*滑动条控制*/
bindSeekBarListener()
/*比对开关*/
iv_compare.setOnTouchStateListener { v, event ->
val action = event.action
if (action == MotionEvent.ACTION_DOWN) {
v.alpha = 0.7f
mDataFactory.enableFaceBeauty(false)
} else if (action == MotionEvent.ACTION_UP) {
v.alpha = 1f
mDataFactory.enableFaceBeauty(true)
}
true
}
/*还原数据*/
lyt_beauty_recover.setOnClickListener {
showDialog(mContext.getString(R.string.dialog_reset_avatar_model)) { recoverData() }
}
lyt_style_recover.setOnClickListener {
if (it.isSelected) {
return@setOnClickListener
}
changeAdapterSelected(mStylesAdapter, mDataFactory.currentStyleIndex, -1)
mDataFactory.currentStyleIndex = -1
it.isSelected = true
setBottomCheckRatioEnable(true)
mDataFactory.onStyleSelected(null)
}
iv_reset.setOnClickListener {
mDataFactory.resetParamIntensity()
var item:FaceBeautyBean? = null
when (beauty_radio_group.checkedCheckBoxId) {
R.id.beauty_radio_skin_beauty -> {
mBeautyAdapter.notifyDataSetChanged()
item = mSkinBeauty[mSkinIndex]
setRecoverFaceSkinEnable(true)
}
R.id.beauty_radio_face_shape -> {
mBeautyAdapter.notifyDataSetChanged()
item = mShapeBeauty[mShapeIndex]
setRecoverFaceSkinEnable(true)
}
R.id.beauty_radio_filter -> {
mFiltersAdapter.notifyDataSetChanged()
beauty_seek_bar.visibility = View.INVISIBLE
}
R.id.beauty_radio_style -> {
mStylesAdapter.notifyDataSetChanged()
}
}
item?.let {
val value = mDataFactory.getParamIntensity(it.key)
val stand = mModelAttributeRange[it.key]!!.stand
val maxRange = mModelAttributeRange[it.key]!!.maxRange
seekToSeekBar(value, stand, maxRange)
}
}
}
/**
* 滚动条绑定事件
*/
private fun bindSeekBarListener() {
beauty_seek_bar.setOnProgressChangeListener(object : DiscreteSeekBar.OnSimpleProgressChangeListener() {
override fun onProgressChanged(seekBar: DiscreteSeekBar?, value: Int, fromUser: Boolean) {
if (!fromUser) {
return
}
val valueF = 1.0 * (value - seekBar!!.min) / 100
when (beauty_radio_group.checkedCheckBoxId) {
R.id.beauty_radio_skin_beauty -> {
val bean = mSkinBeauty[mSkinIndex]
val range = mModelAttributeRange[bean.key]!!.maxRange
val res = valueF * range
val value = mDataFactory.getParamIntensity(bean.key)
if (!DecimalUtils.doubleEquals(res, value)) {
mDataFactory.updateParamIntensity(bean.key, res)
setRecoverFaceSkinEnable(checkFaceSkinChanged())
updateBeautyItemUI(mBeautyAdapter.getViewHolderByPosition(mSkinIndex), bean)
}
}
R.id.beauty_radio_face_shape -> {
if (mShapeIndex < 0) return
val bean = mBeautyAdapter.getData(mShapeIndex)
when (bean.buttonType) {
FaceBeautyBean.ButtonType.NORMAL_BUTTON -> {
//判断一下这个按钮的类型
val range = mModelAttributeRange[bean.key]!!.maxRange
val res = valueF * range
val value = mDataFactory.getParamIntensity(bean.key)
if (!DecimalUtils.doubleEquals(res, value)) {
mDataFactory.updateParamIntensity(bean.key, res)
setRecoverFaceSkinEnable(checkFaceShapeChanged())
updateBeautyItemUI(mBeautyAdapter.getViewHolderByPosition(mShapeIndex), bean)
}
}
}
}
R.id.beauty_radio_filter -> {
val bean = mFilters[mDataFactory.currentFilterIndex]
if (!DecimalUtils.doubleEquals(bean.intensity, valueF)) {
bean.intensity = valueF
mDataFactory.updateFilterIntensity(valueF)
}
}
}
}
})
}
/**
* 底部导航栏绑定监听事件处理RecycleView等相关布局变更
*/
private fun bindBottomRadioListener() {
beauty_radio_group.setOnDispatchActionUpListener { x ->
if (!mEnableBottomRationClick) {
val width = beauty_radio_group.measuredWidth
when {
x < width * 0.25 -> {
val toastStr = mContext.getString(R.string.beauty_face_style_toast, mContext.getString(R.string.beauty_radio_skin_beauty))
ToastHelper.showNormalToast(mContext, toastStr)
}
x < width * 0.5 -> {
val toastStr = mContext.getString(R.string.beauty_face_style_toast, mContext.getString(R.string.beauty_radio_face_shape))
ToastHelper.showNormalToast(mContext, toastStr)
}
x < width * 0.75f -> {
val toastStr = mContext.getString(R.string.beauty_face_style_toast, mContext.getString(R.string.beauty_radio_filter))
ToastHelper.showNormalToast(mContext, toastStr)
}
}
}
}
beauty_radio_group.setOnCheckedChangeListener { _, checkedId ->
//视图变化
when (checkedId) {
R.id.beauty_radio_skin_beauty, R.id.beauty_radio_face_shape -> {
iv_compare.visibility = View.VISIBLE
beauty_seek_bar.visibility = View.VISIBLE
lyt_style_recover.visibility = View.GONE
lyt_beauty_recover.visibility = View.VISIBLE
iv_line.visibility = View.VISIBLE
}
R.id.beauty_radio_filter -> {
iv_compare.visibility = View.VISIBLE
beauty_seek_bar.visibility = if (mDataFactory.currentFilterIndex == 0) View.INVISIBLE else View.VISIBLE
lyt_style_recover.visibility = View.GONE
lyt_beauty_recover.visibility = View.GONE
iv_line.visibility = View.GONE
}
R.id.beauty_radio_style -> {
iv_compare.visibility = View.VISIBLE
beauty_seek_bar.visibility = View.INVISIBLE
lyt_beauty_recover.visibility = View.GONE
lyt_style_recover.visibility = View.VISIBLE
iv_line.visibility = View.VISIBLE
}
View.NO_ID -> {
iv_compare.visibility = View.INVISIBLE
mDataFactory.enableFaceBeauty(true)
}
}
//数据变化
when (checkedId) {
R.id.beauty_radio_skin_beauty -> {
mBeautyAdapter.setData(mSkinBeauty)
recycler_view.adapter = mBeautyAdapter
val item = mSkinBeauty[mSkinIndex]
val value = mDataFactory.getParamIntensity(item.key)
val stand = mModelAttributeRange[item.key]!!.stand
val maxRange = mModelAttributeRange[item.key]!!.maxRange
seekToSeekBar(value, stand, maxRange)
setRecoverFaceSkinEnable(checkFaceSkinChanged())
changeBottomLayoutAnimator(true)
}
R.id.beauty_radio_face_shape -> {
mBeautyAdapter.setData(mShapeBeauty)
recycler_view.adapter = mBeautyAdapter
if (mShapeIndex >= 0) {
val item = mShapeBeauty[mShapeIndex]
val value = mDataFactory.getParamIntensity(item.key)
val stand = mModelAttributeRange[item.key]!!.stand
val maxRange = mModelAttributeRange[item.key]!!.maxRange
seekToSeekBar(value, stand, maxRange)
setRecoverFaceSkinEnable(checkFaceShapeChanged())
changeBottomLayoutAnimator(true)
} else {
beauty_seek_bar.visibility = View.INVISIBLE
}
}
R.id.beauty_radio_filter -> {
recycler_view.adapter = mFiltersAdapter
recycler_view.scrollToPosition(mDataFactory.currentFilterIndex)
if (mDataFactory.currentFilterIndex == 0) {
beauty_seek_bar.visibility = View.INVISIBLE
} else {
seekToSeekBar(mFilters[mDataFactory.currentFilterIndex].intensity, 0.0, 1.0)
}
changeBottomLayoutAnimator(true)
}
R.id.beauty_radio_style -> {
recycler_view.adapter = mStylesAdapter
if (mDataFactory.currentStyleIndex > -1) {
recycler_view.scrollToPosition(mDataFactory.currentStyleIndex)
lyt_style_recover.isSelected = false
} else {
lyt_style_recover.isSelected = true
}
changeBottomLayoutAnimator(true)
}
View.NO_ID -> {
changeBottomLayoutAnimator(false)
mDataFactory.enableFaceBeauty(true)
}
}
}
}
private fun setBottomCheckRatioEnable(enable: Boolean) {
mEnableBottomRationClick = enable
var i = 0
val childCount: Int = beauty_radio_group.getChildCount()
while (i < childCount) {
val view: View = beauty_radio_group.getChildAt(i)
if (view.id != R.id.beauty_radio_style) {
view.alpha = if (enable) 1f else 0.6f
view.isEnabled = enable
}
i++
}
}
// endregion
// region 业务处理
/**
* 设置滚动条数值
* @param value Double 结果值
* @param stand Double 标准值
* @param range Double 范围区间
*/
private fun seekToSeekBar(value: Double, stand: Double, range: Double) {
if (stand == 0.5) {
beauty_seek_bar.min = -50
beauty_seek_bar.max = 50
beauty_seek_bar.progress = (value * 100 / range - 50).toInt()
} else {
beauty_seek_bar.min = 0
beauty_seek_bar.max = 100
beauty_seek_bar.progress = (value * 100 / range).toInt()
}
beauty_seek_bar.visibility = View.VISIBLE
}
/**
* 更新单项是否为基准值显示
*/
private fun updateBeautyItemUI(viewHolder: BaseViewHolder?, item: FaceBeautyBean) {
val value = mDataFactory.getParamIntensity(item.key)
val stand = mModelAttributeRange[item.key]!!.stand
if (DecimalUtils.doubleEquals(value, stand)) {
viewHolder?.setImageResource(R.id.iv_control, item.closeRes)
} else {
viewHolder?.setImageResource(R.id.iv_control, item.openRes)
}
mBeautyAdapter.notifyDataSetChanged()
}
/**
* 重置还原按钮状态
*/
private fun setRecoverFaceSkinEnable(enable: Boolean) {
if (enable) {
tv_beauty_recover.alpha = 1f
iv_beauty_recover.alpha = 1f
} else {
tv_beauty_recover.alpha = 0.6f
iv_beauty_recover.alpha = 0.6f
}
lyt_beauty_recover.isEnabled = enable
}
/**
* 遍历美肤数据确认还原按钮是否可以点击
*/
private fun checkFaceSkinChanged(): Boolean {
val item = mSkinBeauty[mSkinIndex]
var value = mDataFactory.getParamIntensity(item.key)
var default = mModelAttributeRange[item.key]!!.default
if (!DecimalUtils.doubleEquals(value, default)) {
return true
}
mSkinBeauty.forEach {
value = mDataFactory.getParamIntensity(it.key)
default = mModelAttributeRange[it.key]!!.default
if (!DecimalUtils.doubleEquals(value, default)) {
return true
}
}
return false
}
/**
* 遍历美型数据确认还原按钮是否可以点击
*/
private fun checkFaceShapeChanged(): Boolean {
if (checkFaceShapeChanged(mShapeBeauty) || checkFaceShapeChanged(mShapeBeautySubItem))
return true
return false
}
/**
* 遍历美型数据确认还原按钮是否可以点击
*/
private fun checkFaceShapeChanged(shapeBeauty: ArrayList<FaceBeautyBean>): Boolean {
var value: Double
var default: Double
if (shapeBeauty.size > mShapeIndex) {
var item = shapeBeauty[mShapeIndex]
item?.let {
value = mDataFactory.getParamIntensity(item.key)
default = mModelAttributeRange[item.key]!!.default
if (!DecimalUtils.doubleEquals(value, default)) {
return true
}
}
}
shapeBeauty.forEach {
when (it.buttonType) {
FaceBeautyBean.ButtonType.NORMAL_BUTTON -> {
value = mDataFactory.getParamIntensity(it.key)
default = mModelAttributeRange[it.key]!!.default
if (!DecimalUtils.doubleEquals(value, default)) {
return true
}
}
}
}
return false
}
/**
* 还原 美型美肤数据
*/
private fun recoverData() {
when (beauty_radio_group.checkedCheckBoxId) {
R.id.beauty_radio_skin_beauty -> {
mSkinBeauty.forEach {
val default = mModelAttributeRange[it.key]!!.default
mDataFactory.updateParamIntensity(it.key, default)
}
val item = mSkinBeauty[mSkinIndex]
val value = mDataFactory.getParamIntensity(item.key)
val stand = mModelAttributeRange[item.key]!!.stand
val maxRange = mModelAttributeRange[item.key]!!.maxRange
seekToSeekBar(value, stand, maxRange)
mBeautyAdapter.notifyDataSetChanged()
setRecoverFaceSkinEnable(false)
}
R.id.beauty_radio_face_shape -> {
//还原主项和子项
mShapeBeauty.forEach {
when (it.buttonType) {
FaceBeautyBean.ButtonType.NORMAL_BUTTON -> {
val default = mModelAttributeRange[it.key]!!.default
mDataFactory.updateParamIntensity(it.key, default)
}
}
}
//还原子项
mShapeBeautySubItem.forEach {
when (it.buttonType) {
FaceBeautyBean.ButtonType.NORMAL_BUTTON -> {
val default = mModelAttributeRange[it.key]!!.default
mDataFactory.updateParamIntensity(it.key, default)
}
}
}
//获取当前shapeAdapter中被选中的项
var value = 0.0
var stand = 0.0
var maxRange = 1.0
if (mShapeIndex > 0) {
val item = mBeautyAdapter.getData(mShapeIndex)
when (item.buttonType) {
FaceBeautyBean.ButtonType.NORMAL_BUTTON -> {
value = mDataFactory.getParamIntensity(item.key)
stand = mModelAttributeRange[item.key]!!.stand
maxRange = mModelAttributeRange[item.key]!!.maxRange
}
}
}
seekToSeekBar(value, stand, maxRange)
mBeautyAdapter.notifyDataSetChanged()
setRecoverFaceSkinEnable(false)
}
}
}
/**
* 底部动画处理
* @param isOpen Boolean
*/
private fun changeBottomLayoutAnimator(isOpen: Boolean) {
if (isBottomShow == isOpen) {
return
}
val start = if (isOpen) resources.getDimension(R.dimen.x1).toInt() else resources.getDimension(R.dimen.x268).toInt()
val end = if (isOpen) resources.getDimension(R.dimen.x268).toInt() else resources.getDimension(R.dimen.x1).toInt()
if (bottomLayoutAnimator != null && bottomLayoutAnimator!!.isRunning) {
bottomLayoutAnimator!!.end()
}
bottomLayoutAnimator = ValueAnimator.ofInt(start, end).setDuration(150)
bottomLayoutAnimator!!.addUpdateListener { animation ->
val height = animation.animatedValue as Int
val params = fyt_bottom_view.layoutParams as LinearLayout.LayoutParams
params.height = height
fyt_bottom_view.layoutParams = params
if (onBottomAnimatorChangeListener != null) {
val showRate = 1.0f * (height - start) / (end - start)
onBottomAnimatorChangeListener?.onBottomAnimatorChangeListener(if (!isOpen) 1 - showRate else showRate)
}
if (DecimalUtils.floatEquals(animation.animatedFraction, 1.0f) && isOpen) {
iv_compare.visibility = View.VISIBLE
}
}
bottomLayoutAnimator!!.start()
isBottomShow = isOpen
}
override fun onDetachedFromWindow() {
//被销毁前记录此时的UI值用于下一次启动的时候恢复
mSubItemUIValueCache.forEach {
//应该要将UI值保存用于后续恢复
}
super.onDetachedFromWindow()
}
/* item入场动画总开关 */
val openEnterAnimation = false
/* 是否需要对该子项进行入场动画 */
var needEnterAnimation = false
/**
* recycleView ITEM 子项入场动画
*/
fun enterAnimation(view:View){
//动画集合
val animSet = AnimationSet(false)
//位移动画
val translateAnim = TranslateAnimation(
Animation.ABSOLUTE, 0f, Animation.ABSOLUTE, 0f,
Animation.ABSOLUTE, 100f, Animation.ABSOLUTE, 0f)
//渐变动画
val alphaAnim = AlphaAnimation(0.0f, 1.0f)
animSet.addAnimation(translateAnim)
animSet.addAnimation(alphaAnim)
animSet.duration = 300
animSet.fillAfter = true
animSet.addAnimation(alphaAnim)
view.startAnimation(animSet)
}
/**
* 是否展示还原按钮
*/
fun setResetButton(isVisible:Boolean) {
if (isVisible)
iv_reset.visibility = View.VISIBLE
else
iv_reset.visibility = View.GONE
}
}

View File

@ -1,102 +0,0 @@
package com.yunbao.faceunity.control;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import com.yunbao.faceunity.R;
import com.yunbao.faceunity.base.BaseDelegate;
import com.yunbao.faceunity.base.BaseListAdapter;
import com.yunbao.faceunity.base.BaseViewHolder;
import com.yunbao.faceunity.entity.PropBean;
import com.yunbao.faceunity.infe.AbstractPropDataFactory;
import java.util.ArrayList;
/**
* DESC贴图AR面具
* Created on 2021/4/26
*/
public class PropControlView extends BaseControlView {
private AbstractPropDataFactory mDataFactory;
private BaseListAdapter<PropBean> mPropAdapter;
private RecyclerView recyclerView;
public PropControlView(@NonNull Context context) {
super(context);
init();
}
public PropControlView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public PropControlView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
// region init
private void init() {
LayoutInflater.from(mContext).inflate(R.layout.layout_effect_control, this);
initView();
initAdapter();
}
/**
* 给控制绑定 EffectController数据工厂
*
* @param dataFactory IFaceBeautyDataFactory
*/
public void bindDataFactory(AbstractPropDataFactory dataFactory) {
mDataFactory = dataFactory;
mPropAdapter.setData(dataFactory.getPropBeans());
}
/**
* View初始化
*/
private void initView() {
recyclerView = findViewById(R.id.recycler_view);
initHorizontalRecycleView(recyclerView);
}
/**
* Adapter初始化
*/
private void initAdapter() {
mPropAdapter = new BaseListAdapter<>(new ArrayList<>(), new BaseDelegate<PropBean>() {
@Override
public void convert(int viewType, BaseViewHolder helper, PropBean data, int position) {
helper.setImageResource(R.id.iv_control, data.getIconId());
helper.itemView.setSelected(position == mDataFactory.getCurrentPropIndex());
}
@Override
public void onItemClickListener(View view, PropBean data, int position) {
if (mDataFactory.getCurrentPropIndex() != position) {
changeAdapterSelected(mPropAdapter, mDataFactory.getCurrentPropIndex(), position);
mDataFactory.setCurrentPropIndex(position);
mDataFactory.onItemSelected(data);
}
}
}, R.layout.list_item_control_image_circle);
recyclerView.setAdapter(mPropAdapter);
}
// endregion
}

View File

@ -29,6 +29,6 @@ public class FaceParam {
// 占位符以下均未使用 // 占位符以下均未使用
public static final int FACE_ANIM_AR_MASK=900; public static final int FACE_ANIM_AR_MASK=900;
public static final int FACE_EXPRESSION_RECOGNITION=1000; public static final int FACE_EXPRESSION_RECOGNITION=1000;
public static final int FACE_FACE_WARP=1000; public static final int FACE_FACE_WARP=1100;
public static final int FACE_GESTURE_RECOGNITION=1100; public static final int FACE_GESTURE_RECOGNITION=1200;
} }

View File

@ -1,94 +0,0 @@
package com.yunbao.faceunity.dialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
/**
* @author Richie on 2018.09.19
*/
public abstract class BaseDialogFragment extends DialogFragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
View dialogView = createDialogView(inflater, container);
getDialog().setCanceledOnTouchOutside(false);//点击屏幕不消失
getDialog().setOnKeyListener(new DialogInterface.OnKeyListener() {//点击返回键不消失
@Override
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
return true;
}
return false;
}
});
initWindowParams();
return dialogView;
}
/**
* 创建 dialog view
*
* @param inflater
* @param container
* @return
*/
protected abstract View createDialogView(LayoutInflater inflater, @Nullable ViewGroup container);
protected int getDialogWidth() {
return WindowManager.LayoutParams.WRAP_CONTENT;
}
protected int getDialogHeight() {
return WindowManager.LayoutParams.WRAP_CONTENT;
}
private void initWindowParams() {
Dialog dialog = getDialog();
if (dialog != null) {
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
Window window = dialog.getWindow();
if (window != null) {
window.getDecorView().setPadding(0, 0, 0, 0);
window.setBackgroundDrawableResource(android.R.color.transparent);
WindowManager.LayoutParams windowAttributes = window.getAttributes();
windowAttributes.gravity = Gravity.CENTER;
windowAttributes.width = getDialogWidth();
windowAttributes.height = getDialogHeight();
window.setAttributes(windowAttributes);
}
}
}
public interface OnClickListener {
/**
* 确认
*/
void onConfirm();
/**
* 取消
*/
void onCancel();
}
public interface OnDismissListener {
/**
* 消失
*/
void onDismiss();
}
}

View File

@ -1,105 +0,0 @@
package com.yunbao.faceunity.dialog;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.yunbao.faceunity.R;
/**
* 确认对话框
*
* @author Richie on 2018.08.28
*/
public class ConfirmDialogFragment extends BaseDialogFragment {
private static final String TITLE = "content";
private static final String CONFIRM = "confirm";
private static final String CANCEL = "cancel";
private OnClickListener mOnClickListener;
/**
* 创建对话框
*
* @param title
* @param onClickListener
* @return
*/
public static ConfirmDialogFragment newInstance(@NonNull String title, @NonNull OnClickListener onClickListener) {
ConfirmDialogFragment fragment = new ConfirmDialogFragment();
fragment.mOnClickListener = onClickListener;
Bundle bundle = new Bundle();
bundle.putString(TITLE, title);
fragment.setArguments(bundle);
return fragment;
}
public static ConfirmDialogFragment newInstance(@NonNull String title, @NonNull String confirmText,
@NonNull String cancelText, @NonNull OnClickListener onClickListener) {
ConfirmDialogFragment fragment = new ConfirmDialogFragment();
fragment.mOnClickListener = onClickListener;
Bundle bundle = new Bundle();
bundle.putString(TITLE, title);
bundle.putString(CONFIRM, confirmText);
bundle.putString(CANCEL, cancelText);
fragment.setArguments(bundle);
return fragment;
}
@Override
protected View createDialogView(LayoutInflater inflater, @Nullable ViewGroup container) {
View view = inflater.inflate(R.layout.dialog_confirm, container, false);
View.OnClickListener onClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
dismiss();
int id = v.getId();
if (id == R.id.tv_confirm) {
if (mOnClickListener != null) {
mOnClickListener.onConfirm();
}
} else if (id == R.id.tv_cancel) {
if (mOnClickListener != null) {
mOnClickListener.onCancel();
}
}
}
};
String confirmTxt = getArguments().getString(CONFIRM);
TextView tvConfirm = view.findViewById(R.id.tv_confirm);
if (!TextUtils.isEmpty(confirmTxt)) {
tvConfirm.setText(confirmTxt);
}
String cancelTxt = getArguments().getString(CANCEL);
TextView tvCancel = view.findViewById(R.id.tv_cancel);
if (!TextUtils.isEmpty(cancelTxt)) {
tvCancel.setText(cancelTxt);
}
tvConfirm.setOnClickListener(onClickListener);
tvCancel.setOnClickListener(onClickListener);
String title = getArguments().getString(TITLE);
((TextView) view.findViewById(R.id.tv_content)).setText(title);
return view;
}
@Override
protected int getDialogWidth() {
return getResources().getDimensionPixelSize(R.dimen.x562);
}
@Override
protected int getDialogHeight() {
return getResources().getDimensionPixelSize(R.dimen.x294);
}
public void setOnClickListener(OnClickListener onClickListener) {
mOnClickListener = onClickListener;
}
}

View File

@ -1,117 +0,0 @@
package com.yunbao.faceunity.dialog;
import android.content.Context;
import android.content.res.Resources;
import android.util.TypedValue;
import android.view.Gravity;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.StringRes;
import com.yunbao.faceunity.R;
import java.lang.ref.WeakReference;
/**
* Created by tujh on 2018/6/28.
*/
public final class ToastHelper {
private static Toast sNormalToast;
private static Toast sWhiteTextToast;
private static WeakReference<Context> mWeakContext;
public static void showToast(Context context, String str) {
Toast toast = Toast.makeText(context, str, Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
}
public static void showToast(Context context, @StringRes int strId) {
showToast(context, context.getString(strId));
}
public static void showWhiteTextToast(Context context, @StringRes int strId) {
showWhiteTextToast(context, context.getString(strId));
}
public static void showNormalToast(Context context, @StringRes int strId) {
showNormalToast(context, context.getString(strId));
}
public static void dismissToast() {
dismissWhiteTextToast();
dismissNormalToast();
}
public static void dismissWhiteTextToast() {
if (sWhiteTextToast != null) {
sWhiteTextToast.cancel();
}
}
public static void dismissNormalToast() {
if (sNormalToast != null) {
sNormalToast.cancel();
}
}
public static void showWhiteTextToast(Context context, String text) {
if (mWeakContext != null && mWeakContext.get() == context && sWhiteTextToast != null) {
TextView view = (TextView) sWhiteTextToast.getView();
view.setText(text);
if (!view.isShown()) {
sWhiteTextToast.show();
}
return;
}
mWeakContext = new WeakReference<>(context);
Resources resources = context.getResources();
TextView textView = new TextView(context);
textView.setTextColor(resources.getColor(R.color.colorWhite));
textView.setGravity(Gravity.CENTER);
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, resources.getDimension(R.dimen.x64));
textView.setText(text);
sWhiteTextToast = new Toast(context);
sWhiteTextToast.setView(textView);
sWhiteTextToast.setDuration(Toast.LENGTH_SHORT);
int yOffset = context.getResources().getDimensionPixelSize(R.dimen.x560);
sWhiteTextToast.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, yOffset);
sWhiteTextToast.show();
}
public static void showNormalToast(Context context, String text) {
if (mWeakContext != null && mWeakContext.get() == context && sNormalToast != null) {
TextView view = (TextView) sNormalToast.getView();
view.setText(text);
if (!view.isShown()) {
sNormalToast.show();
}
return;
}
mWeakContext = new WeakReference<>(context);
Resources resources = context.getResources();
TextView textView = new TextView(context);
textView.setTextColor(resources.getColor(R.color.colorWhite));
textView.setGravity(Gravity.CENTER);
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, resources.getDimension(R.dimen.x26));
textView.setBackgroundResource(R.drawable.bg_toast_more);
int hPadding = resources.getDimensionPixelSize(R.dimen.x28);
int vPadding = resources.getDimensionPixelSize(R.dimen.x16);
textView.setPadding(hPadding, vPadding, hPadding, vPadding);
textView.setText(text);
sNormalToast = new Toast(context);
sNormalToast.setView(textView);
sNormalToast.setDuration(Toast.LENGTH_SHORT);
int yOffset = context.getResources().getDimensionPixelSize(R.dimen.x182);
sNormalToast.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, yOffset);
sNormalToast.show();
}
}

View File

@ -1,9 +0,0 @@
package com.yunbao.faceunity.listener;
/**
* DESC底部菜单动画回调
* Created on 2021/4/26
*/
public interface OnBottomAnimatorChangeListener {
void onBottomAnimatorChangeListener(float showRate);
}

View File

@ -1,40 +0,0 @@
package com.yunbao.faceunity.listener;
import android.view.View;
import android.view.View.OnClickListener;
/**
* DESC
* Created on 2021/4/26
*/
public abstract class OnMultiClickListener implements OnClickListener {
private long mLastClickTime = 0L;
private int mViewId = View.NO_ID;
private static long MIN_CLICK_DELAY_TIME = 500L;
@Override
public void onClick(View v) {
long curClickTime = System.currentTimeMillis();
int viewId = v.getId();
if (mViewId == viewId) {
if (curClickTime - mLastClickTime >= MIN_CLICK_DELAY_TIME) {
mLastClickTime = curClickTime;
onMultiClick(v);
}
} else {
mViewId = viewId;
mLastClickTime = curClickTime;
onMultiClick(v);
}
}
/**
* 处理后的点击事件
*
* @param v
*/
protected abstract void onMultiClick(View v);
}

View File

@ -1,41 +0,0 @@
package com.yunbao.faceunity.model;
import com.faceunity.core.entity.FUBundleData;
import com.faceunity.core.faceunity.FURenderKit;
import com.faceunity.core.model.facebeauty.FaceBeauty;
import com.yunbao.faceunity.listener.IFaceModel;
import com.yunbao.faceunity.utils.FaceUnityConfig;
/**
* 美颜模块
*/
public class FaceBeautyModel extends IFaceModel<FaceBeauty> {
private FaceBeauty beauty;
/**
* 构造美颜模块
* 参考配置https://gitee.com/hangzhou_xiangxin_1/FULiveDemoDroid/blob/master/doc/4.%E7%BE%8E%E9%A2%9C.md
*/
@Override
public FaceBeauty Builder() {
beauty = new FaceBeauty(new FUBundleData(FaceUnityConfig.BUNDLE_FACE_BEAUTIFICATION));
return beauty;
}
/**
* 应用美颜
*/
@Override
public void apply() {
super.apply();
FURenderKit kit = FURenderKit.getInstance();
kit.setFaceBeauty(beauty);
}
@Override
public void setEnable(boolean enable) {
beauty.setEnable(enable);
}
}

View File

@ -1,5 +0,0 @@
package com.yunbao.faceunity.repo;
public class FineStickerSource {
}

View File

@ -77,19 +77,9 @@ public class FaceUnityView extends LinearLayout implements StickerDownloadHelper
private void init() { private void init() {
LayoutInflater.from(mContext).inflate(R.layout.layout_faceunity, this); LayoutInflater.from(mContext).inflate(R.layout.layout_faceunity, this);
initView(); initView();
bindBottomView();
FineStickerDataFactory.getInstance().addCallback(this); FineStickerDataFactory.getInstance().addCallback(this);
} }
/**
* 绑定数据工厂
*
* @param dataFactory FaceUnityDataFactory
*/
public void bindDataFactory(FaceUnityDataFactory dataFactory) {
}
/** /**
* 初始化View * 初始化View
*/ */
@ -111,6 +101,9 @@ public class FaceUnityView extends LinearLayout implements StickerDownloadHelper
initViewClick(); initViewClick();
} }
/**
* 初始化配置点击事件
*/
private void initViewClick() { private void initViewClick() {
menu2Back.setOnClickListener(v -> { menu2Back.setOnClickListener(v -> {
Object tag = menu2Back.getTag(); Object tag = menu2Back.getTag();
@ -138,6 +131,9 @@ public class FaceUnityView extends LinearLayout implements StickerDownloadHelper
}); });
} }
/**
* 回到默认界面
*/
private void goBackMainMenu() { private void goBackMainMenu() {
setContainerRecycler(new ArrayList<>()); setContainerRecycler(new ArrayList<>());
title.setText("美顏特效選擇"); title.setText("美顏特效選擇");
@ -147,23 +143,9 @@ public class FaceUnityView extends LinearLayout implements StickerDownloadHelper
menuDiy.setVisibility(GONE); menuDiy.setVisibility(GONE);
} }
/** /**
* 底部功能菜单切换 * 配置主菜单
*/ */
private void bindBottomView() {
}
/**
* UI菜单显示控制
*
* @param index Int
*/
private void showFunction(int index) {
}
private void initMenuGroup() { private void initMenuGroup() {
MenuGroupRecyclerAdapter adapter = new MenuGroupRecyclerAdapter(mContext); MenuGroupRecyclerAdapter adapter = new MenuGroupRecyclerAdapter(mContext);
menuGroup.setLayoutManager(new GridLayoutManager(mContext, 4)); menuGroup.setLayoutManager(new GridLayoutManager(mContext, 4));
@ -228,6 +210,9 @@ public class FaceUnityView extends LinearLayout implements StickerDownloadHelper
menuGroup.setAdapter(adapter); menuGroup.setAdapter(adapter);
} }
/**
* 创建Tab
*/
private List<TabLayout.Tab> createTabs(Map<Integer, Integer> map) { private List<TabLayout.Tab> createTabs(Map<Integer, Integer> map) {
List<TabLayout.Tab> list = new ArrayList<>(); List<TabLayout.Tab> list = new ArrayList<>();
for (Integer key : map.keySet()) { for (Integer key : map.keySet()) {
@ -238,6 +223,9 @@ public class FaceUnityView extends LinearLayout implements StickerDownloadHelper
return list; return list;
} }
/**
* 创建菜单
*/
private List<TabLayout.Tab> createTabs(List<FineStickerTagEntity> tags) { private List<TabLayout.Tab> createTabs(List<FineStickerTagEntity> tags) {
List<TabLayout.Tab> list = new ArrayList<>(); List<TabLayout.Tab> list = new ArrayList<>();
for (FineStickerTagEntity tag : tags) { for (FineStickerTagEntity tag : tags) {
@ -253,6 +241,9 @@ public class FaceUnityView extends LinearLayout implements StickerDownloadHelper
return list; return list;
} }
/**
* 创建菜单
*/
private List<TabLayout.Tab> createTabs(ArrayList<MakeupCustomClassBean> tags) { private List<TabLayout.Tab> createTabs(ArrayList<MakeupCustomClassBean> tags) {
List<TabLayout.Tab> list = new ArrayList<>(); List<TabLayout.Tab> list = new ArrayList<>();
for (MakeupCustomClassBean tag : tags) { for (MakeupCustomClassBean tag : tags) {
@ -264,6 +255,9 @@ public class FaceUnityView extends LinearLayout implements StickerDownloadHelper
return list; return list;
} }
/**
* 设置菜单
*/
private void setTab(List<TabLayout.Tab> tabs) { private void setTab(List<TabLayout.Tab> tabs) {
tabLayout.removeAllTabs(); tabLayout.removeAllTabs();
for (TabLayout.Tab tab : tabs) { for (TabLayout.Tab tab : tabs) {
@ -367,10 +361,18 @@ public class FaceUnityView extends LinearLayout implements StickerDownloadHelper
}); });
} }
/**
* 设置美颜选项配置行数图标为5个拖动条为2个
* @param count
*/
private void changeRecyclerItemCount(int count) { private void changeRecyclerItemCount(int count) {
containerRecycler.setLayoutManager(new GridLayoutManager(mContext, count)); containerRecycler.setLayoutManager(new GridLayoutManager(mContext, count));
} }
/**
* 设置美颜Recycler内容
* @param list
*/
private void setContainerRecycler(ArrayList<? extends BaseBean> list) { private void setContainerRecycler(ArrayList<? extends BaseBean> list) {
if (containerAdapter == null) { if (containerAdapter == null) {
containerAdapter = new ContainerRecyclerAdapter(mContext); containerAdapter = new ContainerRecyclerAdapter(mContext);

View File

@ -1,12 +0,0 @@
package com.yunbao.faceunity.utils;
import com.faceunity.core.entity.FUCameraConfig;
public class FaceCameraConfig {
/**
* 默认相机配置
*/
public static FUCameraConfig getDefFUCameraConfig(){
return new FUCameraConfig();
}
}

View File

@ -23,6 +23,10 @@ class SeekBarUtils {
} }
bar.visibility = View.VISIBLE bar.visibility = View.VISIBLE
} }
/**
* 转换成滚动条的值
*/
fun seekToValue(range:Double,value:Int,seekBarMin:Int):Double{ fun seekToValue(range:Double,value:Int,seekBarMin:Int):Double{
val valueF: Double = 1.0 * (value - seekBarMin) / 100 val valueF: Double = 1.0 * (value - seekBarMin) / 100
return range*valueF; return range*valueF;

View File

@ -1,5 +1,8 @@
package com.shayu.phonelive.activity; package com.shayu.phonelive.activity;
import static com.yunbao.common.CommonAppContext.logger;
import static com.yunbao.common.CommonAppContext.mFirebaseAnalytics;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Build; import android.os.Build;
@ -32,17 +35,14 @@ import com.tencent.rtmp.ui.TXCloudVideoView;
import com.tencent.ugc.TXUGCBase; import com.tencent.ugc.TXUGCBase;
import com.yunbao.common.CommonAppConfig; import com.yunbao.common.CommonAppConfig;
import com.yunbao.common.Constants; import com.yunbao.common.Constants;
import com.yunbao.common.activity.WebViewActivity;
import com.yunbao.common.bean.AdBean; import com.yunbao.common.bean.AdBean;
import com.yunbao.common.bean.ConfigBean; import com.yunbao.common.bean.ConfigBean;
import com.yunbao.common.bean.IMLoginModel; import com.yunbao.common.bean.IMLoginModel;
import com.yunbao.common.bean.UserBean;
import com.yunbao.common.custom.CircleProgress; import com.yunbao.common.custom.CircleProgress;
import com.yunbao.common.event.DataUserInfoEvent; import com.yunbao.common.event.DataUserInfoEvent;
import com.yunbao.common.glide.ImgLoader; import com.yunbao.common.glide.ImgLoader;
import com.yunbao.common.http.CommonHttpConsts; import com.yunbao.common.http.CommonHttpConsts;
import com.yunbao.common.http.CommonHttpUtil; import com.yunbao.common.http.CommonHttpUtil;
import com.yunbao.common.http.HttpCallback;
import com.yunbao.common.interfaces.CommonCallback; import com.yunbao.common.interfaces.CommonCallback;
import com.yunbao.common.manager.IMLoginManager; import com.yunbao.common.manager.IMLoginManager;
import com.yunbao.common.manager.imrongcloud.RongcloudIMManager; import com.yunbao.common.manager.imrongcloud.RongcloudIMManager;
@ -53,19 +53,11 @@ import com.yunbao.common.utils.RouteUtil;
import com.yunbao.common.utils.SpUtil; import com.yunbao.common.utils.SpUtil;
import com.yunbao.common.utils.ToastUtil; import com.yunbao.common.utils.ToastUtil;
import com.yunbao.common.utils.WordUtil; import com.yunbao.common.utils.WordUtil;
import com.yunbao.faceunity.FaceManager;
import com.yunbao.live.activity.LiveAudienceActivity;
import com.yunbao.live.bean.LiveBean;
import com.yunbao.live.dialog.LiveFaceUnityDialogFragment;
import com.yunbao.live.http.LiveHttpUtil;
import com.yunbao.live.presenter.LiveRoomCheckLivePresenter;
import com.yunbao.live.views.LauncherAdViewHolder; import com.yunbao.live.views.LauncherAdViewHolder;
import com.yunbao.main.activity.EntryActivity; import com.yunbao.main.activity.EntryActivity;
import com.yunbao.main.activity.MainActivity; import com.yunbao.main.activity.MainActivity;
import com.yunbao.main.activity.PDLiveConversationListActivity;
import com.yunbao.main.http.MainHttpConsts; import com.yunbao.main.http.MainHttpConsts;
import com.yunbao.main.http.MainHttpUtil; import com.yunbao.main.http.MainHttpUtil;
import com.yunbao.main.manager.imrongcloud.ConversationIMListManager;
import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.Subscribe;
@ -77,9 +69,6 @@ import java.util.List;
import myname.pdlive.shayu.R; import myname.pdlive.shayu.R;
import static com.yunbao.common.CommonAppContext.logger;
import static com.yunbao.common.CommonAppContext.mFirebaseAnalytics;
/** /**
* Created by cxf on 2018/9/17. * Created by cxf on 2018/9/17.
*/ */

View File

@ -3,7 +3,6 @@ package com.yunbao.live.dialog;
import android.app.ActionBar; import android.app.ActionBar;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.graphics.Color;
import android.os.Bundle; import android.os.Bundle;
import android.view.Gravity; import android.view.Gravity;
import android.view.View; import android.view.View;
@ -13,8 +12,6 @@ import android.view.WindowManager;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.yunbao.common.dialog.AbsDialogFragment; import com.yunbao.common.dialog.AbsDialogFragment;
import com.yunbao.common.utils.DpUtil;
import com.yunbao.common.utils.ToastUtil;
import com.yunbao.faceunity.FaceManager; import com.yunbao.faceunity.FaceManager;
import com.yunbao.faceunity.ui.FaceUnityView; import com.yunbao.faceunity.ui.FaceUnityView;
import com.yunbao.live.R; import com.yunbao.live.R;
@ -63,7 +60,6 @@ public class LiveFaceUnityDialogFragment extends AbsDialogFragment {
@Override @Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) { public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState); super.onActivityCreated(savedInstanceState);
manager.bindControlView(faceView);
} }
public void setManager(FaceManager manager) { public void setManager(FaceManager manager) {

View File

@ -1,6 +1,5 @@
package com.yunbao.live.views; package com.yunbao.live.views;
import android.app.Activity;
import android.app.Dialog; import android.app.Dialog;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@ -35,7 +34,6 @@ import com.yunbao.common.utils.ToastUtil;
import com.yunbao.common.utils.WordUtil; import com.yunbao.common.utils.WordUtil;
import com.yunbao.common.views.AbsViewHolder; import com.yunbao.common.views.AbsViewHolder;
import com.yunbao.faceunity.FaceManager; import com.yunbao.faceunity.FaceManager;
import com.yunbao.faceunity.ui.FaceUnityView;
import com.yunbao.live.R; import com.yunbao.live.R;
import com.yunbao.live.activity.LiveActivity; import com.yunbao.live.activity.LiveActivity;
import com.yunbao.live.activity.LiveRyAnchorActivity; import com.yunbao.live.activity.LiveRyAnchorActivity;

View File

@ -1,5 +1,7 @@
package com.yunbao.main.activity; package com.yunbao.main.activity;
import static com.yunbao.common.CommonAppContext.isReady;
import android.Manifest; import android.Manifest;
import android.animation.Animator; import android.animation.Animator;
import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorListenerAdapter;
@ -84,11 +86,8 @@ import com.yunbao.common.utils.VersionUtil;
import com.yunbao.common.utils.WordUtil; import com.yunbao.common.utils.WordUtil;
import com.yunbao.common.views.AbsMainViewHolder; import com.yunbao.common.views.AbsMainViewHolder;
import com.yunbao.common.views.weight.ViewClicksAntiShake; import com.yunbao.common.views.weight.ViewClicksAntiShake;
import com.yunbao.faceunity.FaceManager;
import com.yunbao.live.activity.LiveAudienceActivity; import com.yunbao.live.activity.LiveAudienceActivity;
import com.yunbao.live.activity.LiveRyAnchorActivity;
import com.yunbao.live.bean.LiveBean; import com.yunbao.live.bean.LiveBean;
import com.yunbao.live.dialog.LiveFaceUnityDialogFragment;
import com.yunbao.live.http.LiveHttpConsts; import com.yunbao.live.http.LiveHttpConsts;
import com.yunbao.live.http.LiveHttpUtil; import com.yunbao.live.http.LiveHttpUtil;
import com.yunbao.live.presenter.LiveRoomCheckLivePresenter; import com.yunbao.live.presenter.LiveRoomCheckLivePresenter;
@ -139,8 +138,6 @@ import io.rong.push.PushManager;
import io.rong.push.PushType; import io.rong.push.PushType;
import kotlin.Unit; import kotlin.Unit;
import static com.yunbao.common.CommonAppContext.isReady;
@Route(path = RouteUtil.PATH_MAIN) @Route(path = RouteUtil.PATH_MAIN)
public class MainActivity extends AbsActivity implements MainAppBarLayoutListener { public class MainActivity extends AbsActivity implements MainAppBarLayoutListener {
@ -567,11 +564,6 @@ public class MainActivity extends AbsActivity implements MainAppBarLayoutListene
// findViewById(R.id.banner_click).setVisibility(View.VISIBLE); // findViewById(R.id.banner_click).setVisibility(View.VISIBLE);
isfloatBannernet = true; isfloatBannernet = true;
initAnchorRecommendBanner(); initAnchorRecommendBanner();
FaceManager manager = new FaceManager();
manager.initFURender(mContext);
LiveFaceUnityDialogFragment fragment = new LiveFaceUnityDialogFragment(mContext);
fragment.setManager(manager);
fragment.show(((MainActivity) mContext).getSupportFragmentManager(), "FaceUnity");
} else { } else {
floatBanner.setVisibility(View.GONE); floatBanner.setVisibility(View.GONE);
findViewById(R.id.banner_click).setVisibility(View.GONE); findViewById(R.id.banner_click).setVisibility(View.GONE);