1、效果图展示
2、实现思路
实现配置:
1)自定义的GridView
2)自定义的TabLayout(需求中要求下划线比字体短)
3)自定义的ScrollView实现流程:
每一个Tag 标签对应着一个布局,也就是自定义的GridView(因为需要计算高度),把每一个Tag 标签布局对应着一层,计算每一层的高度,然后区分手势滑动以及通过TabLayout的Tab选择,在ScrollView中移动布局即可
3、自定义的TabLayout
EnhanceTabLayout.java
public class EnhanceTabLayout extends FrameLayout {
private TabLayout mTabLayout;
private List mTabList;
private List mCustomViewList;
private int mSelectIndicatorColor;
private int mSelectTextColor;
private int mUnSelectTextColor;
private int mIndicatorHeight;
private int mIndicatorWidth;
private int mTabMode;
private int mTabTextSize;
public EnhanceTabLayout(@NonNull Context context) {
super(context);
init(context, null);
}
public EnhanceTabLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public EnhanceTabLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public EnhanceTabLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
private void readAttr(Context context, AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.EnhanceTabLayout);
mSelectIndicatorColor = typedArray.getColor(R.styleable.EnhanceTabLayout_tabIndicatorColor, context.getResources().getColor(R.color.colorAccent));
mUnSelectTextColor = typedArray.getColor(R.styleable.EnhanceTabLayout_tabTextColor, Color.parseColor("#666666"));
mSelectTextColor = typedArray.getColor(R.styleable.EnhanceTabLayout_tabSelectTextColor, context.getResources().getColor(R.color.colorAccent));
mIndicatorHeight = typedArray.getDimensionPixelSize(R.styleable.EnhanceTabLayout_tabIndicatorHeight, 1);
mIndicatorWidth = typedArray.getDimensionPixelSize(R.styleable.EnhanceTabLayout_tabIndicatorWidth, 0);
mTabTextSize = typedArray.getDimensionPixelSize(R.styleable.EnhanceTabLayout_tabTextSize, 13);
mTabMode = typedArray.getInt(R.styleable.EnhanceTabLayout_tab_Mode, 2);
typedArray.recycle();
}
private void init(Context context, AttributeSet attrs) {
readAttr(context, attrs);
mTabList = new ArrayList<>();
mCustomViewList = new ArrayList<>();
View view = LayoutInflater.from(getContext()).inflate(R.layout.enhance_tab_layout, this, true);
mTabLayout = (TabLayout) view.findViewById(R.id.enhance_tab_view);
// 添加属性
mTabLayout.setTabMode(mTabMode == 1 ? TabLayout.MODE_FIXED : TabLayout.MODE_SCROLLABLE);
mTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
// onTabItemSelected(tab.getPosition());
// Tab 选中之后,改变各个Tab的状态
for (int i = 0; i < mTabLayout.getTabCount(); i++) {
View view = mTabLayout.getTabAt(i).getCustomView();
if (view == null) {
return;
}
TextView text = (TextView) view.findViewById(R.id.tab_item_text);
View indicator = view.findViewById(R.id.tab_item_indicator);
if (i == tab.getPosition()) { // 选中状态
text.setTextColor(mSelectTextColor);
indicator.setBackgroundColor(mSelectIndicatorColor);
indicator.setVisibility(View.VISIBLE);
} else {// 未选中状态
text.setTextColor(mUnSelectTextColor);
indicator.setVisibility(View.INVISIBLE);
}
}
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
public List getCustomViewList() {
return mCustomViewList;
}
public void addOnTabSelectedListener(TabLayout.OnTabSelectedListener onTabSelectedListener) {
mTabLayout.addOnTabSelectedListener(onTabSelectedListener);
}
/**
* 与TabLayout 联动
*
* @param viewPager
*/
public void setupWithViewPager(@Nullable ViewPager viewPager) {
mTabLayout.addOnTabSelectedListener(new ViewPagerOnTabSelectedListener(viewPager, this));
}
/**
* retrive TabLayout Instance
*
* @return
*/
public TabLayout getTabLayout() {
return mTabLayout;
}
/**
* 添加tab
*
* @param tab
*/
public void addTab(String tab) {
mTabList.add(tab);
View customView = getTabView(getContext(), tab, mIndicatorWidth, mIndicatorHeight, mTabTextSize);
mCustomViewList.add(customView);
mTabLayout.addTab(mTabLayout.newTab().setCustomView(customView));
}
public static class ViewPagerOnTabSelectedListener implements TabLayout.OnTabSelectedListener {
private final ViewPager mViewPager;
private final WeakReference mTabLayoutRef;
public ViewPagerOnTabSelectedListener(ViewPager viewPager, EnhanceTabLayout enhanceTabLayout) {
mViewPager = viewPager;
mTabLayoutRef = new WeakReference(enhanceTabLayout);
}
@Override
public void onTabSelected(TabLayout.Tab tab) {
mViewPager.setCurrentItem(tab.getPosition());
EnhanceTabLayout mTabLayout = mTabLayoutRef.get();
if (mTabLayoutRef != null) {
List customViewList = mTabLayout.getCustomViewList();
if (customViewList == null || customViewList.size() == 0) {
return;
}
for (int i = 0; i < customViewList.size(); i++) {
View view = customViewList.get(i);
if (view == null) {
return;
}
TextView text = (TextView) view.findViewById(R.id.tab_item_text);
View indicator = view.findViewById(R.id.tab_item_indicator);
if (i == tab.getPosition()) { // 选中状态
text.setTextColor(mTabLayout.mSelectTextColor);
indicator.setBackgroundColor(mTabLayout.mSelectIndicatorColor);
indicator.setVisibility(View.VISIBLE);
} else {// 未选中状态
text.setTextColor(mTabLayout.mUnSelectTextColor);
indicator.setVisibility(View.INVISIBLE);
}
}
}
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
// No-op
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
// No-op
}
}
/**
* 获取Tab 显示的内容
*
* @param context
* @param
* @return
*/
public static View getTabView(Context context, String text, int indicatorWidth, int indicatorHeight, int textSize) {
View view = LayoutInflater.from(context).inflate(R.layout.tab_item_layout, null);
TextView tabText = (TextView) view.findViewById(R.id.tab_item_text);
if (indicatorWidth > 0) {
View indicator = view.findViewById(R.id.tab_item_indicator);
ViewGroup.LayoutParams layoutParams = indicator.getLayoutParams();
layoutParams.width = indicatorWidth;
layoutParams.height = indicatorHeight;
indicator.setLayoutParams(layoutParams);
}
tabText.setTextSize(textSize);
tabText.setText(text);
return view;
}
}
tab_item_layout.xml
enhance_tab_layout.xml
styleable.xml
4、自定义的GridView
MyGridView.java
public class MyGridView extends GridView {
public MyGridView(android.content.Context context,
android.util.AttributeSet attrs) {
super(context, attrs);
}
/**
* 设置不滚动
*/
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
}
5、自定义的ScrollView
ObservableScrollView.java
public class ObservableScrollView extends ScrollView {
private ScrollViewListener scrollViewListener = null;
public ObservableScrollView(Context context) {
super(context);
}
public ObservableScrollView(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
}
public ObservableScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setScrollViewListener(ScrollViewListener scrollViewListener) {
this.scrollViewListener = scrollViewListener;
}
@Override
protected void onScrollChanged(int x, int y, int oldx, int oldy) {
super.onScrollChanged(x, y, oldx, oldy);
if (scrollViewListener != null) {
scrollViewListener.onScrollChanged(this, x, y, oldx, oldy);
}
}
public interface ScrollViewListener {
void onScrollChanged(ObservableScrollView scrollView, int x, int y, int oldx, int oldy);
}
}
6、完整实现代码如下
item_function_content_first.xml、 item_function_content_second.xml、item_function_content_third.xml、item_function_content_fourth.xml的布局代码基本是一样,不过需要注意的是:最后一层加了一个有高度的空布局
item_function_content_first.xml
item_function_content_second.xml
item_function_content_third.xml
item_function_content_fourth.xml
主布局代码:tab_main_funtion_fragment.xml
主界面实现代码:tab_main_funtion_fragment.xml
public class TabMainFuntionFragment extends Fragment implements ObservableScrollView.ScrollViewListener{
private static final String TAG = TabMainFuntionFragment.class.getSimpleName();
/**
* requestCode——读写外部存储权限
*/
private static final int REQUEST_CODE_STORAGE = 0x02;
private static final int REQUEST_CODE_STORAGE_VOICE = 0x05;
private View homeRootView;
private GridView mGv01, mGv02, mGv03, mGv04;
private TextView tvSsCard;
private Context mContext;
private ApplyCardParam applyCardParam;
private String accountId;
private String accountName;
private FrameLayout wrapperFl;
private EnhanceTabLayout tabLayout;
private ObservableScrollView scrollView;
private LinearLayout containerLl;
private boolean firstAlreadyInflated = true;
private ViewGroup firstFloorVg;
private ViewGroup secondFloorVg;
private ViewGroup thirdFloorVg;
private ViewGroup fourthFloorVg;
private int secondFloorVgPositionDistance;//第二层滑动至顶部的距离
private int thirdFloorVgPositionDistance;
private int fourthFloorVgPositionDistance;
private int currentPosition = 0;
private boolean tabInterceptTouchEventTag = true;//标志位,用来区分是点击了tab还是手动滑动scrollview
private String url = "";
private String title = "";
private int paddingRight;
private int paddingLeft;
private View headView;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle
savedInstanceState) {
LogUtils.d("onCreateView=============");
homeRootView = inflater.inflate(R.layout.tab_main_funtion_fragment, container, false);
mContext = getActivity();
initViews(homeRootView);
initListeners();
initSSCardBusinessListene();
initLaborRelations();
initpersonnelTalent();
initemploymentBusiness();
return homeRootView;
}
private void setFunctionIndexFromHomeFragment(){
MainActivity activity = (MainActivity) getActivity();
boolean isOnclickFunc = activity.isOnclickFunc;
int funcIndex = activity.funcIndex;
currentPosition = funcIndex;
LogUtils.d("setFunctionIndexFromHomeFragment========currentPosition============="+currentPosition);
LogUtils.d("isOnclickFunc============="+isOnclickFunc);
LogUtils.d("funcIndex============="+funcIndex);
smoothScrollByPositon(currentPosition);
}
private void setHomeFragmentFunctionIndex(int position){
MainActivity activity = (MainActivity) getActivity();
activity.funcIndex = position;
currentPosition = position;
}
private void initViews(View view) {
headView = (View)view.findViewById(R.id.head_view);
wrapperFl = (FrameLayout)view.findViewById(R.id.wrapperFl);
tabLayout = (EnhanceTabLayout)view.findViewById(R.id.tabLayout);
scrollView = (ObservableScrollView)view.findViewById(R.id.scrollView);
containerLl = (LinearLayout)view.findViewById(R.id.containerLl);
tabLayout.addTab("社会保险");
tabLayout.addTab("劳动关系");
tabLayout.addTab("人事人才");
tabLayout.addTab("就业创业");
firstFloorVg = (ViewGroup) LayoutInflater.from(getActivity()).inflate(R.layout.item_function_content_first, null);
secondFloorVg = (ViewGroup) LayoutInflater.from(getActivity()).inflate(R.layout.item_function_content_second, null);
thirdFloorVg = (ViewGroup) LayoutInflater.from(getActivity()).inflate(R.layout.item_function_content_third, null);
fourthFloorVg = (ViewGroup) LayoutInflater.from(getActivity()).inflate(R.layout.item_function_content_fourth, null);
fourthFloorVg.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
containerLl.addView(firstFloorVg);
containerLl.addView(secondFloorVg);
containerLl.addView(thirdFloorVg);
containerLl.addView(fourthFloorVg);
mGv01 = (GridView)firstFloorVg.findViewById(R.id.gv_home_ss_card);
mGv02 = (GridView)secondFloorVg.findViewById(R.id.gv_home_labor_relations);
mGv03 = (GridView)thirdFloorVg.findViewById(R.id.gv_home_personnel_talent);
mGv04 = (GridView)fourthFloorVg.findViewById(R.id.gv_home_employment_business);
}
private void initListeners() {
wrapperFl.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
LogUtils.d("wrapperFl onTouch");
tabInterceptTouchEventTag = true;//让tab来处理滑动
return false;
}
});
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
currentPosition = tab.getPosition();
if(!tabInterceptTouchEventTag){//手动滑动页面时则不再次处理滑动
return;
}
scrollView.computeScroll();
smoothScrollByPositon(currentPosition);
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
scrollView.setScrollViewListener(this);
scrollView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
LogUtils.d("scrollView onTouch");
tabInterceptTouchEventTag = false;//让scrollview处理滑动
return false;
}
});
}
private void smoothScrollByPositon(int currentPosition){
LogUtils.d("smoothScrollByPositon===============");
switch (currentPosition) {
case 0:
scrollView.smoothScrollTo(0, 0);
tabLayout.getTabLayout().getTabAt(0).select();
setHomeFragmentFunctionIndex(0);
break;
case 1:
scrollView.smoothScrollTo(0, secondFloorVgPositionDistance);
tabLayout.getTabLayout().getTabAt(1).select();
setHomeFragmentFunctionIndex(1);
break;
case 2:
scrollView.smoothScrollTo(0, thirdFloorVgPositionDistance);
tabLayout.getTabLayout().getTabAt(2).select();
setHomeFragmentFunctionIndex(2);
break;
case 3:
scrollView.smoothScrollTo(0, fourthFloorVgPositionDistance);
tabLayout.getTabLayout().getTabAt(3).select();
setHomeFragmentFunctionIndex(3);
break;
default:
break;
}
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
LogUtils.d("setUserVisibleHint=============");
LogUtils.d("setUserVisibleHint=============isVisibleToUser========"+isVisibleToUser);
try {
if (isVisibleToUser){
if (firstAlreadyInflated) {//获取各层离screen顶部的位置以及计算滑动值相应顶部所需要的距离
firstAlreadyInflated = false;
int[] firstFloorVgPosition = new int[2];
int[] secondFloorVgPosition = new int[2];
int[] thirdFloorVgPosition = new int[2];
int[] fourthFloorVgPosition = new int[2];
firstFloorVg.getLocationOnScreen(firstFloorVgPosition);
secondFloorVg.getLocationOnScreen(secondFloorVgPosition);
thirdFloorVg.getLocationOnScreen(thirdFloorVgPosition);
fourthFloorVg.getLocationOnScreen(fourthFloorVgPosition);
int firstFloorVgPositionAnchor = firstFloorVgPosition[1];
int secondFloorVgPositionAnchor = secondFloorVgPosition[1];
int thirdFloorVgPositionAnchor = thirdFloorVgPosition[1];
int fourthFloorVgPositionAnchor = fourthFloorVgPosition[1];
Log.d(TAG, "第一层距离屏幕的firstFloorVgPosition[0]距离是:" + firstFloorVgPosition[0]);
Log.d(TAG, "第一层距离屏幕的距离是:" + firstFloorVgPosition[1]);
Log.d(TAG, "第一层距离屏幕的secondFloorVgPosition[0]距离是:" + secondFloorVgPosition[0]);
Log.d(TAG, "第二层距离屏幕的距离是:" + secondFloorVgPosition[1]);
Log.d(TAG, "第一层距离屏幕的thirdFloorVgPosition[0]距离是:" + thirdFloorVgPosition[0]);
Log.d(TAG, "第三层距离屏幕的距离是:" + thirdFloorVgPosition[1]);
Log.d(TAG, "第一层距离屏幕的fourthFloorVgPosition[0]距离是:" + fourthFloorVgPosition[0]);
Log.d(TAG, "第四层距离屏幕的距离是:" + fourthFloorVgPosition[1]);
secondFloorVgPositionDistance = secondFloorVgPositionAnchor - firstFloorVgPositionAnchor;
thirdFloorVgPositionDistance = thirdFloorVgPositionAnchor - firstFloorVgPositionAnchor;
fourthFloorVgPositionDistance = fourthFloorVgPositionAnchor - firstFloorVgPositionAnchor;
Log.d(TAG, "secondFloorVgPositionDistance距离是:" + secondFloorVgPositionDistance);
Log.d(TAG, "thirdFloorVgPositionDistance距离是:" + thirdFloorVgPositionDistance);
Log.d(TAG, "fourthFloorVgPositionDistance距离是:" + fourthFloorVgPositionDistance);
}
setFunctionIndexFromHomeFragment();
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onScrollChanged(ObservableScrollView scrollView, int x, int y, int oldx, int oldy) {
Log.d(TAG, "onScrollChanged=====================");
Log.d(TAG, "onScrollChanged===========currentPosition=========="+currentPosition);
Log.d(TAG, "onScrollChanged============tabInterceptTouchEventTag========="+tabInterceptTouchEventTag);
if (tabInterceptTouchEventTag) {//让tab来处理滑动
return;
}
Log.d(TAG, "当前scrollView的位置——>" + y);
if (y < secondFloorVgPositionDistance) {
if (currentPosition != 0) {
scrollView.computeScroll();
tabLayout.getTabLayout().getTabAt(0).select();
setHomeFragmentFunctionIndex(0);
}
} else if (y < thirdFloorVgPositionDistance) {
if (currentPosition != 1) {
scrollView.computeScroll();
tabLayout.getTabLayout().getTabAt(1).select();
setHomeFragmentFunctionIndex(1);
}
} else if (y < fourthFloorVgPositionDistance) {
if (currentPosition != 2) {
scrollView.computeScroll();
tabLayout.getTabLayout().getTabAt(2).select();
setHomeFragmentFunctionIndex(2);
}
} else {
Log.d(TAG, "onScrollChanged==================currentPosition====================="+currentPosition);
if (currentPosition != 3) {
scrollView.computeScroll();
tabLayout.getTabLayout().getTabAt(3).select();
setHomeFragmentFunctionIndex(3);
}
}
}
//社保服务
private void initSSCardBusinessListene() {
final String[] arrNames = getResources().getStringArray(R.array.funtion_ss_card_business);
int[] arrIcons = ViewUtils.getArrayDrawable(getActivity(), R.array.funtion_ss_card_business_icons);
if (arrNames.length > 0) {
HomeOptionAdapter adapter = new HomeOptionAdapter(getActivity(), arrIcons, arrNames);
mGv01.setAdapter(adapter);
}
mGv01.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView> parent, View view, int position, long id) {
//to do
}
});
}
//劳动关系
private void initLaborRelations() {
String[] arrNames = getResources().getStringArray(R.array.funtion_ss_labor_relations);
int[] arrIcons = ViewUtils.getArrayDrawable(getActivity(), R.array.funtion_ss_labor_relations_icons);
if (arrNames.length > 0) {
HomeOptionAdapter adapter = new HomeOptionAdapter(getActivity(), arrIcons, arrNames);
mGv02.setAdapter(adapter);
}
mGv02.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView> adapterView, View view, int position, long l) {
//to do
}
});
}
//人事人才
private void initpersonnelTalent() {
String[] arrNames = getResources().getStringArray(R.array.funtion_ss_personnel_talent);
int[] arrIcons = ViewUtils.getArrayDrawable(getActivity(), R.array.funtion_ss_personnel_talent_icons);
if (arrNames.length > 0) {
HomeOptionAdapter adapter = new HomeOptionAdapter(getActivity(), arrIcons, arrNames);
mGv03.setAdapter(adapter);
}
mGv03.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView> adapterView, View view, int position, long l) {
//to do
}
});
}
//就业创业
private void initemploymentBusiness() {
String[] arrNames = getResources().getStringArray(R.array.funtion_ss_employment_business);
int[] arrIcons = ViewUtils.getArrayDrawable(getActivity(), R.array.funtion_ss_employment_business_icons);
if (arrNames.length > 0) {
HomeOptionAdapter adapter = new HomeOptionAdapter(getActivity(), arrIcons, arrNames);
mGv04.setAdapter(adapter);
}
mGv04.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView> adapterView, View view, int position, long l) {
//to do
}
});
}
@Override
public void onResume() {
super.onResume();
LogUtils.d("onResume======================");
ViewGroup.LayoutParams params = headView.getLayoutParams();
LogUtils.d("params.height======================"+params.height);
LogUtils.d("params.width======================"+params.width);
int mStatusBarHeight = getStatusBarHeight();
LogUtils.d("mStatusBarHeight======================"+mStatusBarHeight);
params.height = mStatusBarHeight;
headView.setLayoutParams(params);
}
private int getStatusBarHeight() {
Resources resources = getActivity().getResources();
int resourceId = resources.getIdentifier("status_bar_height", "dimen","android");
int height = resources.getDimensionPixelSize(resourceId);
return height;
}
@Override
public void onPause() {
super.onPause();
LogUtils.d("onPause======================");
}
}
应该涉及到了ViewPager两个Fragment之间的切换和通信,如下所示:
通过TabMainFuntionFragment和 TabMainHomeFragment 它们的依赖容器 MainActivity,实现值传递,配置如下所示:
TabMainFuntionFragment.java
private void setFunctionIndexFromHomeFragment(){
MainActivity activity = (MainActivity) getActivity();
boolean isOnclickFunc = activity.isOnclickFunc;
int funcIndex = activity.funcIndex;
currentPosition = funcIndex;
LogUtils.d("setFunctionIndexFromHomeFragment========currentPosition============="+currentPosition);
LogUtils.d("isOnclickFunc============="+isOnclickFunc);
LogUtils.d("funcIndex============="+funcIndex);
smoothScrollByPositon(currentPosition);
}
TabMainHomeFragment.java
private void jumpToTabMainFunctionFragment(int position){
LogUtils.d("jumpToTabMainFunctionFragment===================");
MainActivity activity = (MainActivity) getActivity();
activity.funcIndex = position;
activity.isOnclickFunc = true;
LogUtils.d("activity.funcIndex==================="+activity.funcIndex);
LogUtils.d("activity.isOnclickFunc==================="+activity.isOnclickFunc);
activity.mViewPager.setCurrentItem(1);
}
MainActivity.java
public int funcIndex = 0;
public boolean isOnclickFunc = false;
7、参考博文如下
https://www.2cto.com/kf/201803/731497.html
https://www.jianshu.com/p/30128dcfedd4