EffectFragment.java 56 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372
  1. package im.zego.bytedance.beauty.fragment;
  2. import static im.zego.bytedance.beauty.manager.EffectDataManager.TYPE_LOCAL_STYLE_MAKEUP_2D;
  3. import static im.zego.bytedance.beauty.manager.EffectDataManager.TYPE_STICKER;
  4. import static im.zego.bytedance.beauty.manager.EffectDataManager.TYPE_STYLE_MAKEUP_2D;
  5. import static im.zego.bytedance.common.model.EffectType.STANDARD_NOT_ASIA;
  6. import static im.zego.bytedance.beauty.manager.EffectDataManager.DESC_HAIR_DYE_FULL;
  7. import static im.zego.bytedance.beauty.manager.EffectDataManager.DESC_HAIR_DYE_HIGHLIGHT;
  8. import static im.zego.bytedance.beauty.manager.EffectDataManager.DESC_HAIR_DYE_HIGHLIGHT_PART_A;
  9. import static im.zego.bytedance.beauty.manager.EffectDataManager.DESC_HAIR_DYE_HIGHLIGHT_PART_B;
  10. import static im.zego.bytedance.beauty.manager.EffectDataManager.DESC_HAIR_DYE_HIGHLIGHT_PART_C;
  11. import static im.zego.bytedance.beauty.manager.EffectDataManager.DESC_HAIR_DYE_HIGHLIGHT_PART_D;
  12. import static im.zego.bytedance.beauty.manager.EffectDataManager.MASK;
  13. import static im.zego.bytedance.beauty.manager.EffectDataManager.OFFSET;
  14. import static im.zego.bytedance.beauty.manager.EffectDataManager.TYPE_BEAUTY_FACE;
  15. import static im.zego.bytedance.beauty.manager.EffectDataManager.TYPE_BEAUTY_FACE_WHITEN_DEFAULT;
  16. import static im.zego.bytedance.beauty.manager.EffectDataManager.TYPE_BEAUTY_FACE_WHITEN_FENBAI;
  17. import static im.zego.bytedance.beauty.manager.EffectDataManager.TYPE_BEAUTY_FACE_WHITEN_LENGBAI;
  18. import static im.zego.bytedance.beauty.manager.EffectDataManager.TYPE_BEAUTY_FACE_WHITEN_MEIHEI;
  19. import static im.zego.bytedance.beauty.manager.EffectDataManager.TYPE_BEAUTY_FACE_WHITEN_XIAOMAI;
  20. import static im.zego.bytedance.beauty.manager.EffectDataManager.TYPE_BEAUTY_RESHAPE;
  21. import static im.zego.bytedance.beauty.manager.EffectDataManager.TYPE_BEAUTY_SUIT;
  22. import static im.zego.bytedance.beauty.manager.EffectDataManager.TYPE_CLOSE;
  23. import static im.zego.bytedance.beauty.manager.EffectDataManager.TYPE_FILTER;
  24. import static im.zego.bytedance.beauty.manager.EffectDataManager.TYPE_FILTER_AMG;
  25. import static im.zego.bytedance.beauty.manager.EffectDataManager.TYPE_HAIR_DYE;
  26. import static im.zego.bytedance.beauty.manager.EffectDataManager.TYPE_HAIR_DYE_HIGHLIGHT;
  27. import static im.zego.bytedance.beauty.manager.EffectDataManager.TYPE_MAKEUP_HAIR;
  28. import android.annotation.SuppressLint;
  29. import android.content.Context;
  30. import android.os.Bundle;
  31. import android.os.Handler;
  32. import android.view.LayoutInflater;
  33. import android.view.View;
  34. import android.view.ViewGroup;
  35. import android.widget.ImageView;
  36. import android.widget.TextView;
  37. import androidx.annotation.Nullable;
  38. import androidx.fragment.app.Fragment;
  39. import androidx.fragment.app.FragmentManager;
  40. import androidx.fragment.app.FragmentTransaction;
  41. import im.zego.bytedance.beauty.adapter.SelectStatusRVAdapter;
  42. import im.zego.bytedance.beauty.manager.BeautyData;
  43. import im.zego.bytedance.common.adapter.ItemViewRVAdapter;
  44. import im.zego.bytedance.common.fragment.ItemViewPageFragment;
  45. import im.zego.bytedance.common.fragment.TabBoardFragment;
  46. import im.zego.bytedance.common.model.EffectType;
  47. import im.zego.bytedance.common.utils.DensityUtils;
  48. import im.zego.bytedance.R;
  49. import im.zego.bytedance.beauty.manager.EffectDataManager;
  50. import im.zego.bytedance.beauty.manager.FilterDataManager;
  51. import im.zego.bytedance.beauty.manager.LocalParamDataManager;
  52. import im.zego.bytedance.beauty.model.ColorItem;
  53. import im.zego.bytedance.beauty.model.ComposerNode;
  54. import im.zego.bytedance.beauty.model.EffectButtonItem;
  55. import im.zego.bytedance.beauty.model.FilterItem;
  56. import im.zego.bytedance.beauty.view.ColorListView;
  57. import im.zego.bytedance.beauty.view.ProgressBar;
  58. import im.zego.bytedance.beauty.view.RadioTextView;
  59. import im.zego.bytedance.util.LogUtils;
  60. import java.util.ArrayList;
  61. import java.util.Arrays;
  62. import java.util.Collections;
  63. import java.util.HashMap;
  64. import java.util.HashSet;
  65. import java.util.List;
  66. import java.util.Set;
  67. public class EffectFragment extends TabBoardFragment implements View.OnClickListener,
  68. BeautyFaceFragment.IBeautyCallBack,
  69. FilterCategoryFragment.IFilterCallback,
  70. FilterFragment.IFilterCallback,
  71. ProgressBar.OnProgressChangedListener,
  72. ColorListView.ColorSelectCallback,
  73. ItemViewRVAdapter.OnItemClickListener<EffectButtonItem> {
  74. private static final String ARG_PARAM_COLOR_LIST_POSITION = "color_list_position";
  75. private static final String ARG_PARAM_USE_PROGRESS_BAR = "use_progress_bar";
  76. public static final int BOARD_FRAGMENT_HEAD_INSIDE = 0;
  77. public static final int BOARD_FRAGMENT_HEAD_ABOVE = 1;
  78. public static final String TAG_OPTION_BEAUTY_FRAGMENT = "option_beauty_fragment";
  79. public static final String TAG_OPTION_FILTER_FRAGMENT = "option_filter_fragment";
  80. public String mTagOptionFragment;
  81. public static final String TAG_VARY_HEIGHT = "vary_height";
  82. public static final int ANIMATION_DURATION = 400;
  83. private ProgressBar pb;
  84. private RadioTextView mRtFilter;
  85. private RadioTextView mRtMakeUp;
  86. private float[] mItemIntensity;
  87. private TextView tvTitle;
  88. private ColorListView colorListView;
  89. private ImageView ivCloseMakeupOption;
  90. private int colorListPosition = BOARD_FRAGMENT_HEAD_INSIDE;
  91. private boolean useProgressBar = true;
  92. private EffectButtonItem mSecondItem = null;
  93. private int mSecondItemType = 0;
  94. public Set<EffectButtonItem> getSelectNodes() {
  95. return mSelectNodes;
  96. }
  97. // {zh} 所有被选中的小项 {en} All selected items
  98. private Set<EffectButtonItem> mSelectNodes;
  99. private FilterItem mSelectFilter = new FilterItem(TYPE_CLOSE, R.string.filter_normal, R.drawable.clear);
  100. // {zh} 当前选中的小项 {en} Current selected item
  101. private EffectButtonItem mCurrentItem;
  102. // {zh} 由于滤镜与其他特效不在一个体系,其他的特效(美颜、美型、美体、美妆等)都通过 {en} Since filters are not in the same system as other special effects, other special effects (beauty, beauty, body beauty, beauty makeup, etc.) are passed
  103. // {zh} EffectButtonItem 管理了,但是滤镜不在这个体系,所以包括保存项、强度都需要单独管理 {en} EffectButtonItem is managed, but the filter is not in this system, so the saving items and strength need to be managed separately
  104. // {zh} TODO:尝试将滤镜也纳入 EffectButtonItem 体系,或者移出当前 fragment {en} TODO: Try to include the filter in the EffectButtonItem system, or remove the current fragment
  105. // private String mSavedFilterPath;
  106. // private float mSavedFilterIntensity;
  107. private boolean mIsFilter;
  108. private IEffectCallback mEffectCallback;
  109. private List<TabItem> mTabList;
  110. private EffectDataManager mEffectDataManager;
  111. private FilterDataManager mFilterDataManager;
  112. public static EffectFragment newInstance(int param1, boolean param2) {
  113. EffectFragment fragment = new EffectFragment();
  114. Bundle args = new Bundle();
  115. args.putInt(ARG_PARAM_COLOR_LIST_POSITION, param1);
  116. args.putBoolean(ARG_PARAM_USE_PROGRESS_BAR, param2);
  117. fragment.setArguments(args);
  118. return fragment;
  119. }
  120. @Override
  121. public void onCreate(@Nullable Bundle savedInstanceState) {
  122. super.onCreate(savedInstanceState);
  123. if (getArguments() != null) {
  124. colorListPosition = getArguments().getInt(ARG_PARAM_COLOR_LIST_POSITION);
  125. useProgressBar = getArguments().getBoolean(ARG_PARAM_USE_PROGRESS_BAR);
  126. }
  127. }
  128. /** {zh}
  129. * 设置Fragment回调
  130. */
  131. /** {en}
  132. * Set Fragment Callback
  133. */
  134. public EffectFragment setCallback(IEffectCallback callback) {
  135. mEffectCallback = callback;
  136. return this;
  137. }
  138. public EffectFragment setColorListPosition(int position) {
  139. colorListPosition = position;
  140. return this;
  141. }
  142. public EffectFragment useProgressBar(Boolean bool) {
  143. useProgressBar = bool;
  144. return this;
  145. }
  146. public void setData(Context context, EffectDataManager dataManager, FilterDataManager filterManager) {
  147. mEffectDataManager = dataManager;
  148. mFilterDataManager = filterManager;
  149. if (mEffectDataManager == null) return;
  150. if (mFilterDataManager == null) return;
  151. // Fix: java.util.ConcurrentModificationException
  152. mSelectNodes = Collections.synchronizedSet(new HashSet<EffectButtonItem>());
  153. mTabList = BeautyData.INSTANCE.getTabItems();
  154. ArrayList<Fragment> fragmentList = new ArrayList<>();
  155. ArrayList<String> titleList = new ArrayList<>();
  156. for (TabItem tabItem : mTabList) {
  157. if (tabItem.id == TYPE_FILTER) {
  158. fragmentList.add(
  159. new FilterCategoryFragment().setData(mFilterDataManager.getItems()).setFilterCallback(this)
  160. );
  161. } else if (tabItem.id == TYPE_LOCAL_STYLE_MAKEUP_2D || tabItem.id == TYPE_STICKER) {
  162. ItemViewPageFragment<SelectStatusRVAdapter> fragment = new ItemViewPageFragment();
  163. fragment.setAdapter(new SelectStatusRVAdapter(Arrays.asList(mEffectDataManager.getSubItem(tabItem.id).getChildren()), EffectFragment.this));
  164. fragmentList.add(fragment);
  165. } else {
  166. fragmentList.add(
  167. new BeautyFaceFragment()
  168. .setData(mEffectDataManager.getItem(tabItem.id))
  169. .setSelectNodes(mSelectNodes)
  170. .setEffectDataManager(mEffectDataManager)
  171. .setBeautyCallBack(this)
  172. );
  173. }
  174. titleList.add(context.getString(tabItem.title));
  175. }
  176. setFragmentList(fragmentList);
  177. setTitleList(titleList);
  178. }
  179. public void updateLocalParam(boolean isFirstRun) {
  180. if (mSelectNodes == null) {
  181. return;
  182. }
  183. LogUtils.e("LocalParamDataManager.useLocalParamStorage() = " + LocalParamDataManager.useLocalParamStorage());
  184. if (LocalParamDataManager.useLocalParamStorage() && !isFirstRun) {
  185. for (EffectButtonItem item : mSelectNodes) {
  186. item.setSelected(false);
  187. }
  188. mSelectNodes.clear();
  189. Set<EffectButtonItem> localStoredSet = mEffectDataManager.getLocalStoredItems(0);
  190. mSelectNodes.addAll(localStoredSet);
  191. mSelectFilter = mFilterDataManager.getLocalStoredItems();
  192. List<Fragment> fragmentList = getFragmentList();
  193. for (Fragment fragment : fragmentList) {
  194. if (fragment instanceof FilterCategoryFragment) {
  195. ((FilterCategoryFragment) fragment).updateLocalParam(getEffectType());
  196. } else if (fragment instanceof BeautyFaceFragment) {
  197. ((BeautyFaceFragment) fragment).updateLocalParam(getEffectType());
  198. } else {
  199. }
  200. }
  201. // pb.setProgress(0.0f);
  202. if (mCurrentItem != null && mCurrentItem.getNode() != null) {
  203. pb.setProgress(mCurrentItem.getNode().getIntensityArray()[0]);
  204. }
  205. } else {
  206. mSelectNodes.clear();
  207. Set<EffectButtonItem> defaultSet = mEffectDataManager.getDefaultItems();
  208. mSelectNodes.addAll(defaultSet);
  209. if (LocalParamDataManager.useLocalParamStorage()) {
  210. for (EffectButtonItem item : defaultSet) {
  211. LocalParamDataManager.saveComposerNode(item);
  212. }
  213. }
  214. EffectButtonItem suitItemGroup = mEffectDataManager.getItem(TYPE_BEAUTY_SUIT);
  215. mEffectDataManager.getSuitDefautItem().setSelected(true);
  216. suitItemGroup.setSelectChild(mEffectDataManager.getSuitDefautItem());
  217. if (LocalParamDataManager.useLocalParamStorage()) {
  218. LocalParamDataManager.saveComposerNode(suitItemGroup);
  219. for (EffectButtonItem item : suitItemGroup.getChildren()) {
  220. LocalParamDataManager.saveComposerNode(item);
  221. }
  222. }
  223. mFilterDataManager.resetAll();
  224. }
  225. boolean viewLoaded = getView() != null;
  226. // reset UI
  227. if (viewLoaded) {
  228. refreshVP();
  229. }
  230. }
  231. @Override
  232. public EffectType getEffectType() {
  233. if (mEffectCallback == null) {
  234. return EffectType.LITE_ASIA;
  235. }
  236. return mEffectCallback.getEffectType();
  237. }
  238. @Nullable
  239. @Override
  240. public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
  241. return inflater.inflate(R.layout.fragment_effect, container, false);
  242. }
  243. @SuppressLint("ClickableViewAccessibility")
  244. @Override
  245. public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
  246. super.onViewCreated(view, savedInstanceState);
  247. mRtFilter = view.findViewById(R.id.rt_intensity);
  248. mRtMakeUp = view.findViewById(R.id.rt_cold_warm);
  249. mRtFilter.setOnClickListener(this);
  250. mRtMakeUp.setOnClickListener(this);
  251. pb = view.findViewById(R.id.pb1);
  252. pb.setOnProgressChangedListener(this);
  253. if (!useProgressBar) {
  254. pb.setVisibility(View.GONE);
  255. isShowBeautyProProcessBarRT(false);
  256. } else if (getEffectType() == EffectType.LITE_ASIA || getEffectType() == EffectType.LITE_NOT_ASIA) {
  257. pb.setVisibility(View.INVISIBLE);
  258. isShowBeautyProProcessBarRT(false);
  259. }
  260. LayoutInflater.from(getContext()).inflate(R.layout.layout_effect_board_head, view.findViewById(R.id.fl_board_head), true);
  261. tvTitle = view.findViewById(R.id.tv_title_identify);
  262. ivCloseMakeupOption = view.findViewById(R.id.iv_close_makeup_option);
  263. ivCloseMakeupOption.setOnClickListener(this);
  264. switch (colorListPosition) {
  265. case BOARD_FRAGMENT_HEAD_ABOVE:
  266. colorListView = view.findViewById(R.id.color_list_above);
  267. break;
  268. default:
  269. colorListView = view.findViewById(R.id.color_list);
  270. }
  271. }
  272. @Override
  273. public void onResume() {
  274. super.onResume();
  275. if (mCurrentItem != null) {
  276. boolean viewLoaded = getView() != null;
  277. // reset UI
  278. if (viewLoaded) {
  279. refreshVP();
  280. pb.setNegativeable(needProgressBarNegetive(mCurrentItem));
  281. float[] validIntensity = mCurrentItem.getValidIntensity();
  282. if (validIntensity != null && validIntensity.length > 0) {
  283. pb.setProgress(validIntensity[0]);
  284. }
  285. ArrayList<ColorItem> colorItems = mCurrentItem.getColorItems();
  286. if (colorItems != null && colorItems.size() > 0 && mCurrentItem.getParent() != null) {
  287. colorListView.setSelect(mCurrentItem.getParent().getSelectColorIndex());
  288. }
  289. }
  290. }
  291. }
  292. private void removeOrAddItem(Set<EffectButtonItem> set, EffectButtonItem item, boolean add) {
  293. if (add) {
  294. if (item.getAvailableItem() != null) {
  295. set.add(item);
  296. item.setSelected(true).setSelectedRelation(true);
  297. if (LocalParamDataManager.useLocalParamStorage()) {
  298. LocalParamDataManager.saveComposerNode(item);
  299. }
  300. }
  301. } else {
  302. item.setSelectChild(null);
  303. set.remove(item);
  304. item.setSelected(false).setSelectedRelation(false);
  305. if (!item.hasChildren() && LocalParamDataManager.useLocalParamStorage()) {
  306. LocalParamDataManager.updateComposerNode(item);
  307. }
  308. this.onEffectItemClose(item);
  309. if (item.hasChildren()) {
  310. for (EffectButtonItem child : item.getChildren()) {
  311. removeOrAddItem(set, child, false);
  312. }
  313. }
  314. }
  315. }
  316. private boolean needProgressBarNegetive(EffectButtonItem item) {
  317. if (null == item) {
  318. return false;
  319. }
  320. if (null == mRtMakeUp || null == item.getNode()) {
  321. return item.isEnableNegative();
  322. }
  323. return item.isEnableNegative() || (mRtMakeUp.isSelected() && Arrays.equals(item.getNode().getKeyArray(), new String[]{"whiten", "warm"}));
  324. }
  325. @Override
  326. public void onEffectItemClick(EffectButtonItem item) {
  327. if (item == null) return;
  328. if (item.hasChildren()) {
  329. // {zh} 检查所有child中有无「被选中的根节点」,若有则选做mCurrentItem;有颜色更新colorPanel {en} Check whether there is a "selected root node" in all children. If so, select mCurrentItem; update colorPanel with color
  330. EffectButtonItem child = item.getSelectChild();
  331. if (mSelectNodes.contains(child) && !child.hasChildren()) {
  332. mCurrentItem = child;
  333. LogUtils.d("update mCurrentItem = " + mCurrentItem);
  334. // {zh} 该子节点有颜色选项时,设置colorListView的相应颜色为父节点颜色的选中状态 {en} When the sub-node has a color option, set the corresponding color of colorListView to the selected state of the parent node color
  335. ArrayList<ColorItem> colorItems = child.getColorItems();
  336. if (colorItems != null && colorItems.size() > 0) {
  337. colorListView.setSelect(item.getSelectColorIndex());
  338. }
  339. }
  340. // show tips
  341. showTip(getString(item.getTitleId()), item.getDesc() == 0 ? "" : getString(item.getDesc()));
  342. // set progressbar display status
  343. EffectButtonItem selectChild = item.getSelectChild();
  344. if (selectChild != null) {
  345. updateProgressWithItem(selectChild);
  346. } else {
  347. updateProgressWithItem(item.getChildren()[0]);
  348. }
  349. // display optionFragment & colorPanel
  350. if (mSecondItem == null) {
  351. mSecondItem = item;
  352. }
  353. mSecondItemType += 1;
  354. showOrHideOptionFragment(true, item);
  355. } else {
  356. mCurrentItem = item;
  357. LogUtils.d("update mCurrentItem = " + mCurrentItem);
  358. // set progressbar display status
  359. updateProgressWithItem(item);
  360. if (item.getId() == TYPE_CLOSE) {
  361. showOrHideColorPanel(false, null);
  362. }
  363. // take effect of items in mSelectNodes
  364. if (mCurrentItem.getParent() != null && mCurrentItem.getParent().getId() == TYPE_BEAUTY_SUIT) {
  365. if ((mCurrentItem.getId() & MASK) == TYPE_BEAUTY_SUIT) {
  366. EffectButtonItem faceItem = mEffectDataManager.getItem(TYPE_BEAUTY_FACE);
  367. EffectButtonItem reshapeItem = mEffectDataManager.getItem(TYPE_BEAUTY_RESHAPE);
  368. removeOrAddItem(mSelectNodes, faceItem, false);
  369. removeOrAddItem(mSelectNodes, reshapeItem, false);
  370. HashMap<EffectButtonItem, Float> suitItemsMap = mEffectDataManager.getSuitItemsAndDefaultValue(item.getId());
  371. if (suitItemsMap.isEmpty()) return;
  372. EffectButtonItem[] childItems = suitItemsMap.keySet().toArray(new EffectButtonItem[0]);
  373. for (int i = 0; i < childItems.length; i++) {
  374. EffectButtonItem childItem = childItems[i];
  375. if (childItem != null && childItem.getNode() != null) {
  376. childItem.getNode().setIntensityArray(new float[]{suitItemsMap.get(childItem)});
  377. childItem.getIntensityArray()[0] = suitItemsMap.get(childItem);
  378. removeOrAddItem(mSelectNodes, childItem, true);
  379. }
  380. }
  381. //updateComposerNodes(new HashSet<>(Arrays.asList(childItems)));
  382. updateComposerNodes(mSelectNodes);
  383. updateComposerNodeIntensity(new HashSet<>(Arrays.asList(childItems)));
  384. }
  385. refreshVP();
  386. } else {
  387. updateComposerNodes(mSelectNodes);
  388. }
  389. // set intensity & color by msg interface
  390. if (((item.getId() & MASK) == TYPE_HAIR_DYE) || (item.getDesc() == DESC_HAIR_DYE_FULL) || (item.getDesc() == DESC_HAIR_DYE_HIGHLIGHT)) {
  391. if (item.getNode() != null) {
  392. // {zh} 有颜色选择的情况,需要将颜色值设置到强度数组中 {en} If there is a color selection, you need to set the color value to the intensity array
  393. ArrayList<ColorItem> colorItems = item.getColorItems();
  394. if (colorItems != null && colorItems.size() > 0) {
  395. if (item.getId() == TYPE_HAIR_DYE_HIGHLIGHT) {
  396. showOrHideColorPanel(true, colorItems);
  397. }
  398. // {zh} 设置颜色栏选中状态 {en} Set the color bar selection state
  399. int index = mCurrentItem.getSelectColorIndex();
  400. if (mEffectCallback != null) {
  401. if ((item.getId() == TYPE_CLOSE) && (item.getDesc() == DESC_HAIR_DYE_HIGHLIGHT)) {
  402. int[] parts = new int[]{
  403. DESC_HAIR_DYE_HIGHLIGHT_PART_A,
  404. DESC_HAIR_DYE_HIGHLIGHT_PART_B,
  405. DESC_HAIR_DYE_HIGHLIGHT_PART_C,
  406. DESC_HAIR_DYE_HIGHLIGHT_PART_D,
  407. };
  408. for (int part : parts) {
  409. mEffectCallback.onHairDyeSelected(part, item.getColorItems().get(index));
  410. }
  411. } else {
  412. mEffectCallback.onHairDyeSelected(item.getDesc(), item.getColorItems().get(index));
  413. }
  414. }
  415. colorListView.setSelect(index);
  416. }
  417. }
  418. showTip(getString(item.getTitleId()), "");
  419. return;
  420. }
  421. // set intensity & color by composer node interface
  422. if (item.getNode() != null) {
  423. // {zh} 有颜色选择的情况,需要将颜色值设置到强度数组中 {en} If there is a color selection, you need to set the color value to the intensity array
  424. ArrayList<ColorItem> colorItems = item.getColorItems();
  425. if (colorItems != null && colorItems.size() > 0) {
  426. if (colorItems != null && colorItems.size() > 0) {
  427. showOrHideColorPanel(true, colorItems);
  428. } else {
  429. showOrHideColorPanel(false, null);
  430. }
  431. // {zh} 设置颜色栏选中状态 {en} Set the color bar selection state
  432. int index = item.getParent().getSelectColorIndex();
  433. colorListView.setSelect(index);
  434. if (item.getIntensityArray().length == 4) {
  435. item.getIntensityArray()[1] = colorItems.get(index).getR();
  436. item.getIntensityArray()[2] = colorItems.get(index).getG();
  437. item.getIntensityArray()[3] = colorItems.get(index).getB();
  438. }
  439. }
  440. updateComposerNodeIntensity(item);
  441. }
  442. // show tips
  443. if (item.getParent() != null) {
  444. if (item.getParent().getId() == TYPE_BEAUTY_SUIT) {
  445. showTip(getString(R.string.tab_face_suit_tips), "");
  446. } else {
  447. showTip(getString(item.getTitleId()), item.getDesc() == 0 ? "" : getString(item.getDesc()));
  448. }
  449. }
  450. }
  451. }
  452. @Override
  453. public void onEffectItemClose(EffectButtonItem item) {
  454. if (item.getIntensityArray() != null) {
  455. for (int i = 0; i < item.getIntensityArray().length; i++) {
  456. String[] keyArray = item.getNode().getKeyArray();
  457. if (Arrays.equals(item.getNode().getKeyArray(), new String[]{"whiten", "warm"}) && i < keyArray.length) {
  458. item.getIntensityArray()[i] = "warm".equals(keyArray[i]) ? 0.5f : 0f;
  459. } else {
  460. item.getIntensityArray()[i] = needProgressBarNegetive(item) ? 0.5f : 0f;
  461. }
  462. }
  463. }
  464. updateComposerNodeIntensity(item);
  465. }
  466. /** {zh}
  467. * @param filterItem 滤镜对象
  468. * @param position 滤镜位置
  469. * @brief 滤镜点击回调
  470. * @details 滤镜的点击与 EffectButtonItem 不同,需要另外处理
  471. */
  472. /** {en}
  473. * @param filterItem Filter object
  474. * @param position Filter location
  475. * @brief Filter click callback
  476. * @details Filter clicks are different from EffectButtonItem and need additional processing
  477. */
  478. @Override
  479. public void onFilterSelected(FilterItem filterItem, int position) {
  480. if (filterItem == null) return;
  481. // if (filterItem.getParent() != null) {
  482. // filterItem.getParent().setSelectChild(filterItem);
  483. // }
  484. filterItem.setSelected(true).setSelectedRelation(true);
  485. if (filterItem.hasChildren()) {
  486. // {zh} 解决点击item才能发生作用对象的问题,检查所有child中有无「被选中的根节点」,若有则选做mCurrentItem;有颜色更新colorPanel {en} Solve the problem that the object can only be used by clicking item. Check whether there is a "selected root node" in all children. If so, select mCurrentItem; update colorPanel with color
  487. for (EffectButtonItem child : filterItem.getChildren()) {
  488. if (child.equals(mSelectFilter) && !child.hasChildren()) {
  489. mCurrentItem = child;
  490. LogUtils.d("update mCurrentItem = " + mCurrentItem);
  491. }
  492. }
  493. if (filterItem.getSelectChild() != null) {
  494. mIsFilter = filterItem.getId() == TYPE_FILTER;
  495. }
  496. showTip(getString(filterItem.getTitleId()), filterItem.getDesc() == 0 ? "" : getString(filterItem.getDesc()));
  497. showOrHideOptionFragment(true, filterItem);
  498. } else {
  499. mIsFilter = true;
  500. if (mSelectFilter != null) {
  501. if (!filterItem.equals(mSelectFilter)) {
  502. mSelectFilter.setSelected(false).setSelectedRelation(false);
  503. if (LocalParamDataManager.useLocalParamStorage()) {
  504. LocalParamDataManager.saveFilter(mSelectFilter);
  505. }
  506. }
  507. }
  508. filterItem.setSelected(true).setSelected(true);
  509. float defaultIntensity = filterItem == null ? 0f : filterItem.getIntensity();
  510. String filterPath = filterItem == null ? "" : filterItem.getResource();
  511. pb.setProgress(defaultIntensity);
  512. updateFilter(filterPath);
  513. updateFilterIntensity(defaultIntensity);
  514. // mSavedFilterPath = filterPath;
  515. // mSavedFilterIntensity = defaultIntensity;
  516. mCurrentItem = filterItem;
  517. mSelectFilter = filterItem;
  518. if (LocalParamDataManager.useLocalParamStorage()) {
  519. LocalParamDataManager.saveFilter(mSelectFilter);
  520. }
  521. // {zh} 显示tip {en} Display tips
  522. showTip(getContext().getString(filterItem.getTitleId()), "");
  523. }
  524. }
  525. /** {zh}
  526. * @param progressBar 事件来源
  527. * @param progress 进度,0-1
  528. * @param isFromUser 事件是否来自于手动滑动
  529. * @brief 分发强度
  530. * @details 将滑杆的滑动事件分发出去,两个出口
  531. * 1、调用各 fragment 更新 UI
  532. * 2、调用 updateFilterIntensity/updateComposerNodeIntensity 更新特效强度
  533. */
  534. /** {en}
  535. * @param progressBar Event source
  536. * @param progress progress, 0-1
  537. * @param isFromUser Whether the event comes from manual sliding
  538. * @brief Distribution strength
  539. * @details Distribute the sliding event of the slider, two exits
  540. * 1, call each fragment to update the UI
  541. * 2, call updateFilterIntensity/updateComposerNodeIntensity update the special effect strength
  542. */
  543. @Override
  544. public void onProgressChanged(ProgressBar progressBar, float progress, boolean isFromUser) {
  545. if (!isFromUser) {
  546. return;
  547. }
  548. // {zh} 滤镜不在EffectButtonItem体系 {en} Filter not in EffectButtonItem system
  549. if (!mIsFilter) {
  550. if (mCurrentItem == null || mCurrentItem.getId() < 0) return;
  551. }
  552. if (progressBar != null && progressBar.getProgress() != progress) {
  553. progressBar.setProgress(progress);
  554. }
  555. if (mIsFilter) {
  556. mSelectFilter.setIntensity(progress);
  557. updateFilterIntensity(progress);
  558. refreshVP();
  559. return;
  560. }
  561. if (mCurrentItem.getAvailableItem() == null ||
  562. (mCurrentItem.getAvailableItem().getNode().getKeyArray() == null || mCurrentItem.getAvailableItem().getNode().getKeyArray().length == 0) ||
  563. (mCurrentItem.getAvailableItem().getIntensityArray().length <= 0)) {
  564. return;
  565. }
  566. if (isBeautyPro(mCurrentItem.getId()) || mCurrentItem.getId() == TYPE_STYLE_MAKEUP_2D || mCurrentItem.getId() == TYPE_LOCAL_STYLE_MAKEUP_2D) {
  567. int index = mRtFilter.isSelected() ? 0 : 1;
  568. mCurrentItem.getAvailableItem().getIntensityArray()[index] = progress;
  569. ComposerNode node = mCurrentItem.getAvailableItem().getNode();
  570. LogUtils.d("progress = " + progress);
  571. updateComposerNodeIntensity(node.getPath(), node.getKeyArray()[index], progress);
  572. } else {
  573. mCurrentItem.getAvailableItem().getIntensityArray()[0] = progress;
  574. LogUtils.d("progress = " + progress);
  575. updateComposerNodeIntensity(mCurrentItem);
  576. }
  577. refreshVP();
  578. }
  579. @Override
  580. public void onProgressEnd(ProgressBar progressBar, float progress, boolean isFormUser) {
  581. if (LocalParamDataManager.useLocalParamStorage()) {
  582. if (mCurrentItem instanceof FilterItem) {
  583. LocalParamDataManager.saveFilter(mSelectFilter);
  584. } else {
  585. LocalParamDataManager.saveComposerNode(mCurrentItem);
  586. }
  587. }
  588. }
  589. @Override
  590. public void onColorSelected(int index) {
  591. if (mTabList.get(getSelectedTabId()).id == TYPE_HAIR_DYE_HIGHLIGHT) {
  592. mCurrentItem.setSelectColorIndex(index);
  593. LogUtils.d("onColorSelected: " + mCurrentItem);
  594. if (mCurrentItem.getIntensityArray().length == 4) {
  595. ArrayList<ColorItem> colorItems = mCurrentItem.getColorItems();
  596. mCurrentItem.getIntensityArray()[1] = colorItems.get(index).getR();
  597. mCurrentItem.getIntensityArray()[2] = colorItems.get(index).getG();
  598. mCurrentItem.getIntensityArray()[3] = colorItems.get(index).getB();
  599. }
  600. if (mEffectCallback != null) {
  601. mEffectCallback.onHairDyeSelected(mCurrentItem.getDesc(), mCurrentItem.getColorItems().get(index));
  602. }
  603. return;
  604. }
  605. mCurrentItem.getParent().setSelectColorIndex(index);
  606. LogUtils.d("onColorSelected: " + mCurrentItem);
  607. if (mCurrentItem.getIntensityArray().length == 4) {
  608. ArrayList<ColorItem> colorItems = mCurrentItem.getColorItems();
  609. mCurrentItem.getIntensityArray()[1] = colorItems.get(index).getR();
  610. mCurrentItem.getIntensityArray()[2] = colorItems.get(index).getG();
  611. mCurrentItem.getIntensityArray()[3] = colorItems.get(index).getB();
  612. }
  613. if (LocalParamDataManager.useLocalParamStorage()) {
  614. LocalParamDataManager.saveComposerNode(mCurrentItem);
  615. }
  616. updateComposerNodeIntensity(mCurrentItem);
  617. }
  618. /** {zh}
  619. * 根据当前Nodes直接刷新特效
  620. * 在EffectDataManager
  621. */
  622. /** {en}
  623. * Refresh effects directly based on current Nodes
  624. * in EffectDataManager
  625. */
  626. public void refreshByCurrentSelect() {
  627. updateComposerNodes(mSelectNodes);
  628. for (EffectButtonItem it : mSelectNodes) {
  629. updateComposerNodeIntensity(it);
  630. }
  631. }
  632. /** {zh}
  633. * @brief 设置默认特效
  634. * @details 将所有的值都设置为默认给定的值,并加入默认的美颜、美型特效,需要解决三个问题
  635. * 1、各功能强度变动后,需要更新 UI
  636. * 2、修改默认值不影响当前的选中状态(原来选中的按钮依旧选中,进度条依旧指示当前选中的按钮)
  637. * 3、不影响其他功能
  638. */
  639. /** {en}
  640. * @brief Set default effects
  641. * @details Set all values to the default given values, and add the default beauty and beauty effects. Three problems need to be solved
  642. * 1. After the strength of each function changes, you need to update the UI
  643. * 2. Modifying the default value does not affect the current selected state (the original selected button is still selected, and the progress bar still indicates the currently selected button)
  644. * 3. It does not affect other functions
  645. */
  646. public void resetToDefault() {
  647. if (mEffectCallback == null) return;
  648. boolean viewLoaded = getView() != null;
  649. mSelectNodes.clear();
  650. Set<EffectButtonItem> defaultSet = mEffectDataManager.getDefaultItems();
  651. mSelectNodes.addAll(defaultSet);
  652. LogUtils.e("mSelectNode=" + mSelectNodes + " size = " + mSelectNodes.size());
  653. if (LocalParamDataManager.useLocalParamStorage()) {
  654. LocalParamDataManager.reset();
  655. for (EffectButtonItem defaultItem : defaultSet) {
  656. LocalParamDataManager.saveComposerNode(defaultItem);
  657. }
  658. }
  659. if (mCurrentItem != null && !mSelectNodes.contains(mCurrentItem)) {
  660. // {zh} 进度条复位 {en} Progress bar reset
  661. if (needProgressBarNegetive(mCurrentItem)) {
  662. pb.setProgress(0.5f);
  663. } else {
  664. pb.setProgress(0.f);
  665. }
  666. mCurrentItem = null;
  667. }
  668. // mSavedFilterPath = null;
  669. // mSavedFilterIntensity = 0.f;
  670. // mSelectFilter = new FilterItem(TYPE_CLOSE, R.string.filter_normal, R.drawable.clear, null,0.0f);
  671. mSelectFilter.setSelected(false).setSelectedRelation(false);
  672. mSelectFilter = (FilterItem) mFilterDataManager.getItems().getChildren()[0];
  673. mSecondItemType = 0;
  674. mSecondItem = null;
  675. for (Fragment fragment : getFragmentList()) {
  676. if (fragment instanceof FilterFragment) {
  677. ((FilterFragment) fragment).setSelected(0);
  678. }
  679. if (fragment instanceof BeautyFaceFragment) {
  680. ((BeautyFaceFragment) fragment).refreshSelectedItem();
  681. }
  682. if (fragment instanceof FilterCategoryFragment) {
  683. ((FilterCategoryFragment) fragment).resetItem();
  684. }
  685. }
  686. // reset UI
  687. if (viewLoaded) {
  688. // {zh} 选择默认套装 {en} Select Default Package
  689. EffectButtonItem suitItemGroup = mEffectDataManager.getItem(TYPE_BEAUTY_SUIT);
  690. mEffectDataManager.getSuitDefautItem().setSelected(true);
  691. suitItemGroup.setSelectChild(mEffectDataManager.getSuitDefautItem());
  692. removeOrAddItem(mSelectNodes, mEffectDataManager.getSuitDefautItem(), true);
  693. refreshVP();
  694. showOrHideOptionFragment(false, null);
  695. if (mCurrentItem != null) {
  696. updateProgressWithItem(mCurrentItem);
  697. }
  698. // {zh} 默认美颜没有滤镜,强度置0 {en} The default beauty has no filter, the intensity is set to 0
  699. if (mIsFilter) {
  700. pb.setProgress(0.f);
  701. }
  702. }
  703. }
  704. // {zh} 更新 ViewPager UI {en} Update ViewPager UI
  705. private void refreshVP() {
  706. for (Fragment fragment : getFragmentList()) {
  707. if (fragment instanceof BeautyFaceFragment) {
  708. ((BeautyFaceFragment) fragment).refreshUI();
  709. } else if (fragment instanceof FilterFragment) {
  710. ((FilterFragment) fragment).setSelectFilter(mSelectFilter);
  711. ((FilterFragment) fragment).refreshUI();
  712. } else if (fragment instanceof FilterCategoryFragment) {
  713. ((FilterCategoryFragment) fragment).setSelectFilter(mSelectFilter);
  714. ((FilterCategoryFragment) fragment).refreshUI();
  715. } else if (fragment instanceof ItemViewPageFragment) {
  716. ((ItemViewPageFragment<?>) fragment).refreshUI();
  717. }
  718. }
  719. Fragment makeupOptionFragment = getOptionFragment(TAG_OPTION_BEAUTY_FRAGMENT);
  720. if (null != makeupOptionFragment) {
  721. ((BeautyFaceFragment) makeupOptionFragment).refreshUI();
  722. }
  723. makeupOptionFragment = getOptionFragment(TAG_OPTION_FILTER_FRAGMENT);
  724. if (null != makeupOptionFragment) {
  725. ((FilterFragment) makeupOptionFragment).refreshUI();
  726. }
  727. }
  728. private void updateComposerNodes(Set<EffectButtonItem> effectButtonItems) {
  729. if (mEffectCallback == null) {
  730. return;
  731. }
  732. mEffectCallback.updateComposeNodes(effectButtonItems);
  733. }
  734. private void updateComposerNodeIntensity(EffectButtonItem effectButtonItem) {
  735. if (mEffectCallback == null) {
  736. return;
  737. }
  738. mEffectCallback.updateComposerNodeIntensity(effectButtonItem);
  739. }
  740. private void updateComposerNodeIntensity(Set<EffectButtonItem> effectButtonItem) {
  741. if (mEffectCallback == null) {
  742. return;
  743. }
  744. mEffectCallback.updateComposerNodeIntensity(effectButtonItem);
  745. }
  746. private void updateFilter(String filter) {
  747. if (mEffectCallback == null) {
  748. return;
  749. }
  750. mEffectCallback.onFilterSelected(filter);
  751. }
  752. private void updateComposerNodeIntensity(String node, String key, float value) {
  753. if (mEffectCallback == null) {
  754. return;
  755. }
  756. mEffectCallback.updateComposerNodeIntensity(node, key, value);
  757. }
  758. /** {zh}
  759. * 根据回调显示tip,滤镜和二级美妆按钮需要在屏幕上部弹出气泡
  760. *
  761. * @param title
  762. * @param desc
  763. */
  764. /** {en}
  765. * According to the callback, the tip, filter and secondary makeup buttons need to pop bubbles on the upper part of the screen
  766. *
  767. * @param title
  768. * @param desc
  769. */
  770. private void showTip(String title, String desc) {
  771. if (mEffectCallback == null) {
  772. return;
  773. }
  774. mEffectCallback.showTip(title, desc);
  775. }
  776. public void showOrHideColorPanel(boolean isShow, ArrayList<ColorItem> colorItems) {
  777. switch (colorListPosition) {
  778. case BOARD_FRAGMENT_HEAD_ABOVE:
  779. showColorListHeadAbove(isShow, colorItems);
  780. break;
  781. default:
  782. showColorListHeadInside(isShow, colorItems);
  783. }
  784. }
  785. private void showColorListHeadAbove(boolean isShow, ArrayList<ColorItem> colorItems) {
  786. int height = getResources().getDimensionPixelSize(R.dimen.height_board_total);
  787. int pbHeight = 0;
  788. if (useProgressBar) {
  789. pbHeight = getResources().getDimensionPixelSize(R.dimen.height_progress_bar);
  790. }
  791. float colorListHeight = DensityUtils.dp2px(getContext(), 24);
  792. float colorListHeightMarginBottom = getResources().getDimensionPixelSize(R.dimen.colorlistview_margin_bottom);
  793. if (isShow) {
  794. if (colorItems != null && colorItems.size() > 0) {
  795. colorListView.setVisibility(View.VISIBLE);
  796. super.setBoardFragmentHeight(height + pbHeight + colorListHeight + colorListHeightMarginBottom, 0);
  797. colorListView.updateColors(colorItems, this);
  798. }
  799. } else {
  800. super.setBoardFragmentHeight(height + pbHeight, 0);
  801. colorListView.setVisibility(View.GONE);
  802. }
  803. }
  804. private void showColorListHeadInside(boolean isShow, ArrayList<ColorItem> colorItems) {
  805. if (isShow) {
  806. if (colorItems != null && colorItems.size() > 0) {
  807. colorListView.setVisibility(View.VISIBLE);
  808. tvTitle.setVisibility(View.GONE);
  809. colorListView.updateColors(colorItems, this);
  810. }
  811. } else {
  812. colorListView.setVisibility(View.GONE);
  813. tvTitle.setVisibility(View.VISIBLE);
  814. }
  815. }
  816. private void updateFilterIntensity(float intensity) {
  817. if (mEffectCallback == null) {
  818. return;
  819. }
  820. mEffectCallback.onFilterValueChanged(intensity);
  821. }
  822. private Fragment getOptionFragment(String tag) {
  823. FragmentManager manager = getChildFragmentManager();
  824. FragmentTransaction transaction = manager.beginTransaction();
  825. transaction.setCustomAnimations(R.anim.board_enter, R.anim.board_exit);
  826. return manager.findFragmentByTag(tag);
  827. }
  828. /** {zh}
  829. * @param isShow 是否显示
  830. * @brief 显示/隐藏三级菜单
  831. * @details 显示/隐藏三级菜单,在没有实例的情况下会先初始化一个实例
  832. */
  833. /** {en}
  834. * @param isShow Whether to show
  835. * @brief Show/hide the three-level menu
  836. * @details Show/hide the three-level menu, which initializes an instance first if there is no instance
  837. */
  838. private void showOrHideOptionFragment(boolean isShow, EffectButtonItem item) {
  839. FragmentManager manager = getChildFragmentManager();
  840. FragmentTransaction transaction = manager.beginTransaction();
  841. transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
  842. // transaction.setCustomAnimations(R.anim.board_enter, R.anim.board_exit);
  843. if (item == null) {
  844. } else if (item instanceof FilterItem) {
  845. mTagOptionFragment = TAG_OPTION_FILTER_FRAGMENT;
  846. } else {
  847. mTagOptionFragment = TAG_OPTION_BEAUTY_FRAGMENT;
  848. }
  849. Fragment optionFragment = getOptionFragment(mTagOptionFragment);
  850. if (item == null) {
  851. mTagOptionFragment = null;
  852. }
  853. if (isShow) {
  854. // {zh} BoardFragment 变高应用示例 {en} BoardFragment Height Application Example
  855. // setBoardFragmentHeight(DensityUtils.dp2px(getContext(),260),ANIMATION_DURATION);
  856. mCurrentItem = item.getSelectChild();
  857. hideTabPage(ANIMATION_DURATION / 2);
  858. ivCloseMakeupOption.setVisibility(View.VISIBLE);
  859. tvTitle.setVisibility(View.VISIBLE);
  860. tvTitle.animate().alpha(1).setDuration(ANIMATION_DURATION / 2).start();
  861. tvTitle.setText(item.getTitleId());
  862. ivCloseMakeupOption.animate().alpha(1).setDuration(ANIMATION_DURATION / 2).start();
  863. if (!item.isSelected()) {
  864. item.setSelectChild(item.getChildren()[0]);
  865. }
  866. if (optionFragment == null) {
  867. optionFragment = generateMakeupOptionFragment(mTagOptionFragment);
  868. switch (mTagOptionFragment) {
  869. case TAG_OPTION_FILTER_FRAGMENT:
  870. ((FilterFragment) optionFragment).setData((FilterItem) item).setFilterCallback(this);
  871. transaction.add(R.id.fl_board_content, optionFragment, TAG_OPTION_FILTER_FRAGMENT).commit();
  872. break;
  873. default:
  874. ((BeautyFaceFragment) optionFragment).setData(item).setSelectNodes(mSelectNodes).setBeautyCallBack(this);
  875. transaction.add(R.id.fl_board_content, optionFragment, TAG_OPTION_BEAUTY_FRAGMENT).commit();
  876. }
  877. } else {
  878. switch (mTagOptionFragment) {
  879. case TAG_OPTION_FILTER_FRAGMENT:
  880. ((FilterFragment) optionFragment).setData((FilterItem) item).setFilterCallback(this);
  881. break;
  882. default:
  883. ((BeautyFaceFragment) optionFragment).setData(item).setSelectNodes(mSelectNodes);
  884. }
  885. transaction.show(optionFragment).commit();
  886. }
  887. for (EffectButtonItem child : item.getChildren()) {
  888. if (mSelectNodes.contains(child) && item.getColorItems() != null) {
  889. showOrHideColorPanel(true, item.getColorItems());
  890. }
  891. }
  892. } else {
  893. // {zh} BoardFragment 变高应用示例 {en} BoardFragment Height Application Example
  894. // setBoardFragmentHeight(getResources().getDimension(R.dimen.height_board_total),ANIMATION_DURATION);
  895. if (colorListView != null) {
  896. // {zh} 清空保存到颜色值 {en} Clear Save to Color Value
  897. showOrHideColorPanel(false, null);
  898. }
  899. if (optionFragment == null) return;
  900. transaction.hide(optionFragment).commit();
  901. showTabPage(ANIMATION_DURATION / 2);
  902. tvTitle.animate().alpha(0).setDuration(ANIMATION_DURATION / 2).start();
  903. ivCloseMakeupOption.animate().alpha(0).setDuration(ANIMATION_DURATION / 2).start();
  904. new Handler().postDelayed(new Runnable() {
  905. @Override
  906. public void run() {
  907. tvTitle.setVisibility(View.GONE);
  908. ivCloseMakeupOption.setVisibility(View.GONE);
  909. }
  910. }, ANIMATION_DURATION / 2);
  911. }
  912. }
  913. private Fragment generateMakeupOptionFragment(String tag) {
  914. switch (tag) {
  915. case TAG_OPTION_FILTER_FRAGMENT:
  916. return new FilterFragment();
  917. default:
  918. return new BeautyFaceFragment();
  919. }
  920. }
  921. private int getTypeWithPosition(int position) {
  922. if (position >= this.mTabList.size()) {
  923. return -1;
  924. }
  925. return this.mTabList.get(position).id;
  926. }
  927. /** {zh}
  928. * @param item EffectButtonItem
  929. * @brief 根据 EffectButtonItem 更新滑杆
  930. */
  931. /** {en}
  932. * @param item EffectButtonItem
  933. * @brief Update sliders by EffectButtonItem
  934. */
  935. private void updateProgressWithItem(EffectButtonItem item) {
  936. pb.setNegativeable(needProgressBarNegetive(item));
  937. if (isBeautyPro(item.getId()) || item.getId() == TYPE_LOCAL_STYLE_MAKEUP_2D || item.getId() == TYPE_STYLE_MAKEUP_2D) {
  938. mItemIntensity = item.getIntensityArray();
  939. updateProgressBar();
  940. } else {
  941. float[] validIntensity = item.getValidIntensity();
  942. if (validIntensity != null && validIntensity.length > 0) {
  943. pb.setProgress(validIntensity[0]);
  944. } else {
  945. pb.setProgress(0.f);
  946. }
  947. }
  948. if (useProgressBar) {
  949. if (item.getId() == TYPE_MAKEUP_HAIR
  950. || (item.getId() & MASK) == TYPE_BEAUTY_SUIT
  951. || (item.getParent() != null && item.getParent().getId() == TYPE_MAKEUP_HAIR)) {
  952. pb.setVisibility(View.INVISIBLE);
  953. isShowBeautyProProcessBarRT(false);
  954. } else {
  955. pb.setVisibility(View.VISIBLE);
  956. isShowBeautyProProcessBarRT(isBeautyPro(item.getId()) || item.getId() == TYPE_LOCAL_STYLE_MAKEUP_2D || item.getId() == TYPE_STYLE_MAKEUP_2D);
  957. }
  958. }
  959. }
  960. private boolean isBeautyPro(int id) {
  961. return (getEffectType() == STANDARD_NOT_ASIA || getEffectType() == EffectType.STANDARD_ASIA)
  962. && (id == TYPE_BEAUTY_FACE_WHITEN_DEFAULT
  963. || id == TYPE_BEAUTY_FACE_WHITEN_FENBAI
  964. || id == TYPE_BEAUTY_FACE_WHITEN_LENGBAI
  965. || id == TYPE_BEAUTY_FACE_WHITEN_MEIHEI
  966. || id == TYPE_BEAUTY_FACE_WHITEN_XIAOMAI);
  967. }
  968. // {zh} 设定BoardFragment高度 {en} Set BoardFragment Height
  969. // height unit: px, duration unit: ms
  970. protected float setBoardFragmentHeight(float height, int duration) {
  971. float pbHeight = getResources().getDimension(R.dimen.height_progress_bar);
  972. float diffHeight = super.setBoardFragmentHeight(height + pbHeight, duration);
  973. mEffectCallback.setImgCompareHeightBy(diffHeight, duration);
  974. return diffHeight;
  975. }
  976. @Override
  977. public void onClick(View v) {
  978. super.onClick(v);
  979. if (v.getId() == R.id.iv_close_makeup_option) {
  980. if (mSecondItemType == 2) {
  981. mSecondItemType -= 1;
  982. mCurrentItem = null;
  983. mIsFilter = false;
  984. showOrHideOptionFragment(true, mSecondItem);
  985. } else if (mSecondItemType == 1) {
  986. mSecondItemType = 0;
  987. mSecondItem = null;
  988. mCurrentItem = null;
  989. mIsFilter = false;
  990. showOrHideOptionFragment(false, null);
  991. } else {
  992. mSecondItemType = 0;
  993. mSecondItem = null;
  994. mCurrentItem = null;
  995. mIsFilter = false;
  996. showOrHideOptionFragment(false, null);
  997. }
  998. refreshVP();
  999. } else if (v.getId() == R.id.rt_intensity) {
  1000. mRtFilter.setState(true);
  1001. mRtMakeUp.setState(false);
  1002. pb.setNegativeable(false);
  1003. updateProgressBar();
  1004. } else if (v.getId() == R.id.rt_cold_warm) {
  1005. mRtFilter.setState(false);
  1006. mRtMakeUp.setState(true);
  1007. pb.setNegativeable(false);
  1008. updateProgressBar();
  1009. }
  1010. }
  1011. private void updateProgressBar() {
  1012. if (mItemIntensity == null || mItemIntensity.length == 0) {
  1013. pb.setProgress(0);
  1014. return;
  1015. }
  1016. if (mRtFilter.isSelected()) {
  1017. pb.setProgress(mItemIntensity[0]);
  1018. } else if (mRtMakeUp.isSelected()) {
  1019. pb.setProgress(mItemIntensity[1]);
  1020. }
  1021. }
  1022. private int printPos(int p) {
  1023. return p >> OFFSET;
  1024. }
  1025. @Override
  1026. public void onViewPagerSelected(int position) {
  1027. int stickerType = getTypeWithPosition(position);
  1028. mIsFilter = stickerType == TYPE_FILTER || stickerType == TYPE_FILTER_AMG;
  1029. if (mIsFilter) {
  1030. pb.setNegativeable(false);
  1031. isShowBeautyProProcessBarRT(false);
  1032. if (mSelectFilter != null) {
  1033. pb.setProgress(mSelectFilter.getIntensity());
  1034. pb.setVisibility(View.VISIBLE);
  1035. } else {
  1036. pb.setProgress(0.f);
  1037. pb.setVisibility(View.INVISIBLE);
  1038. }
  1039. mIsFilter = false;
  1040. mCurrentItem = null;
  1041. } else {
  1042. if (mEffectDataManager.getItem(stickerType).getSelectChild() == null || mEffectDataManager.getItem(stickerType).getSelectChild().getChildren().length == 0) {
  1043. mCurrentItem = mEffectDataManager.getItem(stickerType).getSelectRoot();
  1044. if (mCurrentItem != null) {
  1045. LogUtils.d("update mCurrentItem = " + mCurrentItem);
  1046. if (mCurrentItem != null) {
  1047. updateProgressWithItem(mCurrentItem);
  1048. }
  1049. } else {
  1050. isShowBeautyProProcessBarRT(false);
  1051. pb.setVisibility(View.INVISIBLE);
  1052. }
  1053. } else {
  1054. mCurrentItem = null;
  1055. }
  1056. }
  1057. }
  1058. @Override
  1059. public void onClickEvent(View view) {
  1060. if (mEffectCallback == null) {
  1061. LogUtils.e("mEffectCallback == null!!");
  1062. return;
  1063. }
  1064. mEffectCallback.onClickEvent(view);
  1065. }
  1066. @Override
  1067. public void setData() {
  1068. }
  1069. private void isShowBeautyProProcessBarRT(boolean isShow) {
  1070. if (isShow) {
  1071. mRtFilter.setVisibility(View.VISIBLE);
  1072. mRtMakeUp.setVisibility(View.VISIBLE);
  1073. } else {
  1074. mRtFilter.setVisibility(View.GONE);
  1075. mRtMakeUp.setVisibility(View.GONE);
  1076. }
  1077. }
  1078. @Override
  1079. public void onItemClick(EffectButtonItem item, int position) {
  1080. onBeautySelect(item, position);
  1081. refreshVP();
  1082. }
  1083. private void onBeautySelect(EffectButtonItem item, int position) {
  1084. if (item == null) {
  1085. return;
  1086. }
  1087. if (item.getPath() != null && item.getPath().startsWith("stickers/")) { // 是贴纸,不需要显示进度条
  1088. mEffectCallback.onStickSelect(item);
  1089. pb.setVisibility(View.GONE);
  1090. isShowBeautyProProcessBarRT(false);
  1091. } else { // 风格装要显示进度,并且显示选项
  1092. mEffectCallback.onMakeUpSelect(item);
  1093. updateProgressWithItem(item);
  1094. mCurrentItem = item;
  1095. mCurrentItem.setSelectedRelation(true);
  1096. // if (item.getId() != EffectDataManager.TYPE_CLOSE) {
  1097. // item.setSelected(true);
  1098. // if (LocalParamDataManager.useLocalParamStorage()) {
  1099. // LocalParamDataManager.saveComposerNode(item);
  1100. // }
  1101. // }
  1102. }
  1103. }
  1104. public static class TabItem {
  1105. public int id;
  1106. public int title;
  1107. public TabItem(int id, int title) {
  1108. this.id = id;
  1109. this.title = title;
  1110. }
  1111. }
  1112. public interface IEffectCallback {
  1113. /** {zh}
  1114. * @param nodes 字符串数组,存储所有设置的美颜内容,当 node 长度为 0 时意为关闭美妆
  1115. * @param tags 与 nodes 一一对应
  1116. * @brief 更新特效
  1117. */
  1118. /** {en}
  1119. * @ nodes character string array, stores all settings of beauty content, when the node length is 0, it means to turn off beauty makeup
  1120. * @ tags one-to-one correspondence with nodes
  1121. * @brief update special effects
  1122. */
  1123. void updateComposeNodes(Set<EffectButtonItem> effectButtonItems);
  1124. /** {zh}
  1125. * @param effectButtonItem 特效名称
  1126. * @brief 更新特效强度
  1127. */
  1128. /** {en}
  1129. * @param effectButtonItem Effect name
  1130. * @brief Update effect strength
  1131. */
  1132. void updateComposerNodeIntensity(EffectButtonItem effectButtonItem);
  1133. /** {zh}
  1134. * @param effectButtonItem 特效名称
  1135. * @brief 更新特效强度
  1136. */
  1137. /** {en}
  1138. * @param effectButtonItems Effect name
  1139. * @brief Update effect strength
  1140. */
  1141. void updateComposerNodeIntensity(Set<EffectButtonItem> effectButtonItems);
  1142. /** {zh}
  1143. * @param filter 滤镜名称
  1144. * @brief 更新滤镜
  1145. */
  1146. /** {en}
  1147. * @param filter Filter name
  1148. * @brief Update filter
  1149. */
  1150. void onFilterSelected(String filter);
  1151. /** {zh}
  1152. * @param cur 强度值,0-1
  1153. * @brief 更新滤镜强度
  1154. */
  1155. /** {en}
  1156. * @param cur strength value, 0-1
  1157. * @brief update filter strength
  1158. */
  1159. void onFilterValueChanged(float cur);
  1160. /** {zh}
  1161. * 回调Fragment内部点击事件
  1162. */
  1163. /** {en}
  1164. * Callback Fragment Internal Click Event
  1165. */
  1166. void onClickEvent(View view);
  1167. /** {zh}
  1168. * 获取当前选中的EffectType
  1169. *
  1170. * @return
  1171. */
  1172. /** {en}
  1173. * Get the currently selected EffectType
  1174. *
  1175. * @return
  1176. */
  1177. EffectType getEffectType();
  1178. /** {zh}
  1179. * 显示tip
  1180. */
  1181. /** {en}
  1182. * Display tips
  1183. */
  1184. void showTip(String title, String desc);
  1185. /** {zh}
  1186. * 调节对比按钮的高度
  1187. */
  1188. /** {en}
  1189. * Display tips
  1190. */
  1191. void setImgCompareHeightBy(float y, int duration);
  1192. /** {zh}
  1193. * @param part 设置的挑染颜色
  1194. * @param colorItem 设置的挑染部位
  1195. * @brief 更新挑染设置
  1196. */
  1197. /** {en}
  1198. * @param part selected hair dye part
  1199. * @param colorItem selected hair dye color
  1200. * @brief update hair dye color
  1201. */
  1202. void onHairDyeSelected(int part, ColorItem colorItem);
  1203. /** {zh}
  1204. * @param node 特效名称
  1205. * @param key 功能 key
  1206. * @param value 强度值
  1207. * @brief 更新特效强度
  1208. */
  1209. /** {en}
  1210. * @param node Effect name
  1211. * @param key Function key
  1212. * @param value Strength value
  1213. * @brief Update effect strength
  1214. */
  1215. void updateComposerNodeIntensity(String node, String key, float value);
  1216. /**
  1217. * 贴纸选择
  1218. * @param item
  1219. */
  1220. void onStickSelect(EffectButtonItem item);
  1221. /**
  1222. * 风格装选择
  1223. * @param item
  1224. */
  1225. void onMakeUpSelect(EffectButtonItem item);
  1226. }
  1227. }