补充注释及移除部分未用到代码
This commit is contained in:
parent
d2bb4e4375
commit
1e98de9931
@ -17,8 +17,10 @@ import com.faceunity.core.callback.OperateCallback;
|
||||
import com.faceunity.core.entity.FURenderOutputData;
|
||||
import com.faceunity.core.enumeration.CameraFacingEnum;
|
||||
import com.faceunity.core.enumeration.FUAIProcessorEnum;
|
||||
import com.faceunity.core.enumeration.FUAITypeEnum;
|
||||
import com.faceunity.core.enumeration.FUInputTextureEnum;
|
||||
import com.faceunity.core.enumeration.FUTransformMatrixEnum;
|
||||
import com.faceunity.core.faceunity.FUAIKit;
|
||||
import com.faceunity.core.faceunity.FURenderManager;
|
||||
import com.faceunity.core.utils.CameraUtils;
|
||||
import com.faceunity.core.utils.FULogger;
|
||||
@ -41,7 +43,7 @@ import cn.rongcloud.rtc.api.callback.IRCRTCVideoOutputFrameListener;
|
||||
import cn.rongcloud.rtc.base.RCRTCVideoFrame;
|
||||
|
||||
/**
|
||||
* 美颜模块管理类,接入测试中
|
||||
* 美颜模块管理类
|
||||
*/
|
||||
public class FaceManager implements SensorEventListener {
|
||||
private static boolean isInit = false;
|
||||
@ -75,7 +77,6 @@ public class FaceManager implements SensorEventListener {
|
||||
}
|
||||
|
||||
private FURenderer mFURenderer;
|
||||
private FaceUnityView faceUnityView;
|
||||
|
||||
/**
|
||||
* 配置美颜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) {
|
||||
this.faceStatusChanged = faceStatusChanged;
|
||||
}
|
||||
@ -220,6 +216,21 @@ public class FaceManager implements SensorEventListener {
|
||||
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 {
|
||||
void onFaceChanged(int num);
|
||||
}
|
||||
|
@ -39,6 +39,9 @@ import com.yunbao.faceunity.utils.FaceSPUtils;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 美颜配置适配器
|
||||
*/
|
||||
public class ContainerRecyclerAdapter extends RecyclerView.Adapter<BaseViewHolder> {
|
||||
|
||||
private Context mContext;
|
||||
@ -223,18 +226,30 @@ public class ContainerRecyclerAdapter extends RecyclerView.Adapter<BaseViewHolde
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存配置
|
||||
*/
|
||||
public void save(String key, String data) {
|
||||
FaceSPUtils.getInstance().saveString(key, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取配置
|
||||
*/
|
||||
public String getString(String key) {
|
||||
return FaceSPUtils.getInstance().getString(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除配置
|
||||
*/
|
||||
public void del(String key) {
|
||||
FaceSPUtils.getInstance().del(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 恢复默认设置
|
||||
*/
|
||||
public void reset() {
|
||||
if (vh != null) {
|
||||
vh.reset(list);
|
||||
|
@ -16,6 +16,9 @@ import com.yunbao.faceunity.entity.MenuGroupBean;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 主菜单适配器
|
||||
*/
|
||||
public class MenuGroupRecyclerAdapter extends RecyclerView.Adapter<MenuGroupRecyclerAdapter.Vh> {
|
||||
private Context context;
|
||||
private List<MenuGroupBean> list;
|
||||
|
@ -33,8 +33,20 @@ public abstract class BaseViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
public abstract void setData(BaseBean data);
|
||||
|
||||
/**
|
||||
* 读取配置
|
||||
* @return 是否有保存的配置
|
||||
*/
|
||||
public abstract boolean loadData();
|
||||
|
||||
/**
|
||||
* 保存配置
|
||||
*/
|
||||
public abstract void saveData();
|
||||
|
||||
/**
|
||||
* 恢复默认配置
|
||||
*/
|
||||
public abstract void reset(List<? extends BaseBean> list);
|
||||
|
||||
|
||||
|
@ -1,57 +0,0 @@
|
||||
package com.yunbao.faceunity.base;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
/**
|
||||
* DESC:RecycleView 通用业务调用
|
||||
* 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;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
/**
|
||||
* DESC:RecycleView 通用适配器
|
||||
* 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];
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
|
||||
/**
|
||||
* DESC:DESC:控件布局绑定
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
|
||||
}
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
@ -29,6 +29,6 @@ public class FaceParam {
|
||||
// 占位符,以下均未使用
|
||||
public static final int FACE_ANIM_AR_MASK=900;
|
||||
public static final int FACE_EXPRESSION_RECOGNITION=1000;
|
||||
public static final int FACE_FACE_WARP=1000;
|
||||
public static final int FACE_GESTURE_RECOGNITION=1100;
|
||||
public static final int FACE_FACE_WARP=1100;
|
||||
public static final int FACE_GESTURE_RECOGNITION=1200;
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
package com.yunbao.faceunity.listener;
|
||||
|
||||
/**
|
||||
* DESC:底部菜单动画回调
|
||||
* Created on 2021/4/26
|
||||
*/
|
||||
public interface OnBottomAnimatorChangeListener {
|
||||
void onBottomAnimatorChangeListener(float showRate);
|
||||
}
|
@ -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);
|
||||
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
package com.yunbao.faceunity.repo;
|
||||
|
||||
public class FineStickerSource {
|
||||
|
||||
}
|
@ -77,19 +77,9 @@ public class FaceUnityView extends LinearLayout implements StickerDownloadHelper
|
||||
private void init() {
|
||||
LayoutInflater.from(mContext).inflate(R.layout.layout_faceunity, this);
|
||||
initView();
|
||||
bindBottomView();
|
||||
FineStickerDataFactory.getInstance().addCallback(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定数据工厂
|
||||
*
|
||||
* @param dataFactory FaceUnityDataFactory
|
||||
*/
|
||||
public void bindDataFactory(FaceUnityDataFactory dataFactory) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化View
|
||||
*/
|
||||
@ -111,6 +101,9 @@ public class FaceUnityView extends LinearLayout implements StickerDownloadHelper
|
||||
initViewClick();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化配置点击事件
|
||||
*/
|
||||
private void initViewClick() {
|
||||
menu2Back.setOnClickListener(v -> {
|
||||
Object tag = menu2Back.getTag();
|
||||
@ -138,6 +131,9 @@ public class FaceUnityView extends LinearLayout implements StickerDownloadHelper
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 回到默认界面
|
||||
*/
|
||||
private void goBackMainMenu() {
|
||||
setContainerRecycler(new ArrayList<>());
|
||||
title.setText("美顏特效選擇");
|
||||
@ -147,23 +143,9 @@ public class FaceUnityView extends LinearLayout implements StickerDownloadHelper
|
||||
menuDiy.setVisibility(GONE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 底部功能菜单切换
|
||||
* 配置主菜单
|
||||
*/
|
||||
private void bindBottomView() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* UI菜单显示控制
|
||||
*
|
||||
* @param index Int
|
||||
*/
|
||||
private void showFunction(int index) {
|
||||
|
||||
}
|
||||
|
||||
private void initMenuGroup() {
|
||||
MenuGroupRecyclerAdapter adapter = new MenuGroupRecyclerAdapter(mContext);
|
||||
menuGroup.setLayoutManager(new GridLayoutManager(mContext, 4));
|
||||
@ -228,6 +210,9 @@ public class FaceUnityView extends LinearLayout implements StickerDownloadHelper
|
||||
menuGroup.setAdapter(adapter);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建Tab
|
||||
*/
|
||||
private List<TabLayout.Tab> createTabs(Map<Integer, Integer> map) {
|
||||
List<TabLayout.Tab> list = new ArrayList<>();
|
||||
for (Integer key : map.keySet()) {
|
||||
@ -238,6 +223,9 @@ public class FaceUnityView extends LinearLayout implements StickerDownloadHelper
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建菜单
|
||||
*/
|
||||
private List<TabLayout.Tab> createTabs(List<FineStickerTagEntity> tags) {
|
||||
List<TabLayout.Tab> list = new ArrayList<>();
|
||||
for (FineStickerTagEntity tag : tags) {
|
||||
@ -253,6 +241,9 @@ public class FaceUnityView extends LinearLayout implements StickerDownloadHelper
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建菜单
|
||||
*/
|
||||
private List<TabLayout.Tab> createTabs(ArrayList<MakeupCustomClassBean> tags) {
|
||||
List<TabLayout.Tab> list = new ArrayList<>();
|
||||
for (MakeupCustomClassBean tag : tags) {
|
||||
@ -264,6 +255,9 @@ public class FaceUnityView extends LinearLayout implements StickerDownloadHelper
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置菜单
|
||||
*/
|
||||
private void setTab(List<TabLayout.Tab> tabs) {
|
||||
tabLayout.removeAllTabs();
|
||||
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) {
|
||||
containerRecycler.setLayoutManager(new GridLayoutManager(mContext, count));
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置美颜Recycler内容
|
||||
* @param list
|
||||
*/
|
||||
private void setContainerRecycler(ArrayList<? extends BaseBean> list) {
|
||||
if (containerAdapter == null) {
|
||||
containerAdapter = new ContainerRecyclerAdapter(mContext);
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -23,6 +23,10 @@ class SeekBarUtils {
|
||||
}
|
||||
bar.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换成滚动条的值
|
||||
*/
|
||||
fun seekToValue(range:Double,value:Int,seekBarMin:Int):Double{
|
||||
val valueF: Double = 1.0 * (value - seekBarMin) / 100
|
||||
return range*valueF;
|
||||
|
@ -1,5 +1,8 @@
|
||||
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.Intent;
|
||||
import android.os.Build;
|
||||
@ -32,17 +35,14 @@ import com.tencent.rtmp.ui.TXCloudVideoView;
|
||||
import com.tencent.ugc.TXUGCBase;
|
||||
import com.yunbao.common.CommonAppConfig;
|
||||
import com.yunbao.common.Constants;
|
||||
import com.yunbao.common.activity.WebViewActivity;
|
||||
import com.yunbao.common.bean.AdBean;
|
||||
import com.yunbao.common.bean.ConfigBean;
|
||||
import com.yunbao.common.bean.IMLoginModel;
|
||||
import com.yunbao.common.bean.UserBean;
|
||||
import com.yunbao.common.custom.CircleProgress;
|
||||
import com.yunbao.common.event.DataUserInfoEvent;
|
||||
import com.yunbao.common.glide.ImgLoader;
|
||||
import com.yunbao.common.http.CommonHttpConsts;
|
||||
import com.yunbao.common.http.CommonHttpUtil;
|
||||
import com.yunbao.common.http.HttpCallback;
|
||||
import com.yunbao.common.interfaces.CommonCallback;
|
||||
import com.yunbao.common.manager.IMLoginManager;
|
||||
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.ToastUtil;
|
||||
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.main.activity.EntryActivity;
|
||||
import com.yunbao.main.activity.MainActivity;
|
||||
import com.yunbao.main.activity.PDLiveConversationListActivity;
|
||||
import com.yunbao.main.http.MainHttpConsts;
|
||||
import com.yunbao.main.http.MainHttpUtil;
|
||||
import com.yunbao.main.manager.imrongcloud.ConversationIMListManager;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
@ -77,9 +69,6 @@ import java.util.List;
|
||||
|
||||
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.
|
||||
*/
|
||||
|
@ -3,7 +3,6 @@ package com.yunbao.live.dialog;
|
||||
import android.app.ActionBar;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
@ -13,8 +12,6 @@ import android.view.WindowManager;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
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.ui.FaceUnityView;
|
||||
import com.yunbao.live.R;
|
||||
@ -63,7 +60,6 @@ public class LiveFaceUnityDialogFragment extends AbsDialogFragment {
|
||||
@Override
|
||||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
manager.bindControlView(faceView);
|
||||
}
|
||||
|
||||
public void setManager(FaceManager manager) {
|
||||
|
@ -1,6 +1,5 @@
|
||||
package com.yunbao.live.views;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@ -35,7 +34,6 @@ import com.yunbao.common.utils.ToastUtil;
|
||||
import com.yunbao.common.utils.WordUtil;
|
||||
import com.yunbao.common.views.AbsViewHolder;
|
||||
import com.yunbao.faceunity.FaceManager;
|
||||
import com.yunbao.faceunity.ui.FaceUnityView;
|
||||
import com.yunbao.live.R;
|
||||
import com.yunbao.live.activity.LiveActivity;
|
||||
import com.yunbao.live.activity.LiveRyAnchorActivity;
|
||||
|
@ -1,5 +1,7 @@
|
||||
package com.yunbao.main.activity;
|
||||
|
||||
import static com.yunbao.common.CommonAppContext.isReady;
|
||||
|
||||
import android.Manifest;
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
@ -84,11 +86,8 @@ import com.yunbao.common.utils.VersionUtil;
|
||||
import com.yunbao.common.utils.WordUtil;
|
||||
import com.yunbao.common.views.AbsMainViewHolder;
|
||||
import com.yunbao.common.views.weight.ViewClicksAntiShake;
|
||||
import com.yunbao.faceunity.FaceManager;
|
||||
import com.yunbao.live.activity.LiveAudienceActivity;
|
||||
import com.yunbao.live.activity.LiveRyAnchorActivity;
|
||||
import com.yunbao.live.bean.LiveBean;
|
||||
import com.yunbao.live.dialog.LiveFaceUnityDialogFragment;
|
||||
import com.yunbao.live.http.LiveHttpConsts;
|
||||
import com.yunbao.live.http.LiveHttpUtil;
|
||||
import com.yunbao.live.presenter.LiveRoomCheckLivePresenter;
|
||||
@ -139,8 +138,6 @@ import io.rong.push.PushManager;
|
||||
import io.rong.push.PushType;
|
||||
import kotlin.Unit;
|
||||
|
||||
import static com.yunbao.common.CommonAppContext.isReady;
|
||||
|
||||
@Route(path = RouteUtil.PATH_MAIN)
|
||||
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);
|
||||
isfloatBannernet = true;
|
||||
initAnchorRecommendBanner();
|
||||
FaceManager manager = new FaceManager();
|
||||
manager.initFURender(mContext);
|
||||
LiveFaceUnityDialogFragment fragment = new LiveFaceUnityDialogFragment(mContext);
|
||||
fragment.setManager(manager);
|
||||
fragment.show(((MainActivity) mContext).getSupportFragmentManager(), "FaceUnity");
|
||||
} else {
|
||||
floatBanner.setVisibility(View.GONE);
|
||||
findViewById(R.id.banner_click).setVisibility(View.GONE);
|
||||
|
Loading…
Reference in New Issue
Block a user