Compare commits

..

2 Commits

Author SHA1 Message Date
nail
f54e65c601 Merge branch 'master' of https://git.jindashengwl.cn/androidOne/qianyanAndroid 2026-03-28 19:19:05 +08:00
nail
0c3bc88a29 修改首页 2026-03-28 19:18:53 +08:00
53 changed files with 3850 additions and 51 deletions

View File

@@ -166,7 +166,7 @@ android {
// } // }
oss { oss {
applicationId "com.xuebiping.bolizhuzi" applicationId "com.xuebiping.bolizhuzi"
buildConfigField "boolean", "IS_DEV", "false" buildConfigField "boolean", "IS_DEV", "true"
buildConfigField "String", "PRIVACY", '"/index/about/siyuPrivacy.html"' buildConfigField "String", "PRIVACY", '"/index/about/siyuPrivacy.html"'
buildConfigField "String", "AGREEMENT", '"/index/about/siyuAgreement.html"' buildConfigField "String", "AGREEMENT", '"/index/about/siyuAgreement.html"'
buildConfigField "String", "VIP_AGREEMENT", '"/index/about/siyuVipAgreement.html"' buildConfigField "String", "VIP_AGREEMENT", '"/index/about/siyuVipAgreement.html"'
@@ -348,6 +348,7 @@ android {
implementation project(path: ':storage') implementation project(path: ':storage')
implementation project(path: ':yunxinkit') implementation project(path: ':yunxinkit')
implementation project(':faceunity') implementation project(':faceunity')
implementation project(':magicindicator')
//EventBus //EventBus
implementation 'de.greenrobot:eventbus:2.4.0' implementation 'de.greenrobot:eventbus:2.4.0'
implementation 'com.tencent.mm.opensdk:wechat-sdk-android-without-mta:6.8.0' implementation 'com.tencent.mm.opensdk:wechat-sdk-android-without-mta:6.8.0'
@@ -398,6 +399,9 @@ android {
implementation 'com.devzld:expandlayout:1.0.0' implementation 'com.devzld:expandlayout:1.0.0'
implementation 'io.github.lucksiege:pictureselector:v3.11.2' implementation 'io.github.lucksiege:pictureselector:v3.11.2'
implementation 'com.github.Dimezis:BlurView:version-3.1.0' implementation 'com.github.Dimezis:BlurView:version-3.1.0'
implementation "com.scwang.smartrefresh:SmartRefreshLayout:1.1.0-x"
implementation "com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.6" //3.0.2更换了很多API
} }
} }

View File

@@ -0,0 +1,18 @@
{
"version": 2,
"artifactType": {
"type": "APK",
"kind": "Directory"
},
"applicationId": "com.xuebiping.bolizhuzi",
"variantName": "ossRelease",
"elements": [
{
"type": "SINGLE",
"filters": [],
"versionCode": 1,
"versionName": "1.0.0",
"outputFile": "siyu_v1.0.0_oss_release.apk"
}
]
}

Binary file not shown.

View File

@@ -136,7 +136,7 @@ public class DynamicsAdapter extends BaseAdapter {
public View getView(int i, View view, ViewGroup viewGroup) { public View getView(int i, View view, ViewGroup viewGroup) {
Holder holder = null; Holder holder = null;
if (null == view) { if (null == view) {
view = View.inflate(mContext, R.layout.item_dynamic_list1, null); view = View.inflate(mContext, R.layout.item_dynamic_list, null);
holder = initView(view); holder = initView(view);
} else { } else {
holder = (Holder) view.getTag(R.id.tag_second); holder = (Holder) view.getTag(R.id.tag_second);
@@ -155,7 +155,7 @@ public class DynamicsAdapter extends BaseAdapter {
holder.newPeopleImageView.setVisibility(View.GONE); holder.newPeopleImageView.setVisibility(View.GONE);
holder.realPeopleImageView.setVisibility(View.GONE); holder.realPeopleImageView.setVisibility(View.GONE);
holder.tv_see_count.setText("已有"+bean.getLike_count()+"次浏览"); // holder.tv_see_count.setText("已有"+bean.getLike_count()+"次浏览");
if (bean.getGender() == 1) { if (bean.getGender() == 1) {
holder.realPeopleImageView.setVisibility(View.VISIBLE); holder.realPeopleImageView.setVisibility(View.VISIBLE);

View File

@@ -0,0 +1,29 @@
package com.xuebiping.bolizhuzi.controller.main.adapter;
import android.content.Context;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.viewholder.BaseViewHolder;
import com.facebook.drawee.view.SimpleDraweeView;
import com.xuebiping.bolizhuzi.R;
import com.xuebiping.bolizhuzi.model.main.LookMeBean;
import com.xuebiping.bolizhuzi.utils.StrU;
import org.jetbrains.annotations.NotNull;
public class MainLookMeAdapter extends BaseQuickAdapter<LookMeBean, BaseViewHolder> {
private Context mContext;
public MainLookMeAdapter(int layoutResId, Context context) {
super(layoutResId);
this.mContext = context;
}
@Override
protected void convert(@NotNull BaseViewHolder baseViewHolder, LookMeBean lookMeBean) {
SimpleDraweeView list_photo = baseViewHolder.getView(R.id.list_photo);
list_photo.setImageURI(StrU.getResourcePath(lookMeBean.getAvatar_url(), mContext));
}
}

View File

@@ -0,0 +1,40 @@
package com.xuebiping.bolizhuzi.controller.main.adapter;
import android.content.Context;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.titles.ColorTransitionPagerTitleView;
/**
* 带颜色渐变和缩放的指示器标题
* 博客: http://hackware.lucode.net
* Created by hackware on 2016/6/26.
*/
public class ScaleTransitionPagerTitleView extends ColorTransitionPagerTitleView {
private float mMinScale = 0.75f;
public ScaleTransitionPagerTitleView(Context context) {
super(context);
}
@Override
public void onEnter(int index, int totalCount, float enterPercent, boolean leftToRight) {
super.onEnter(index, totalCount, enterPercent, leftToRight); // 实现颜色渐变
setScaleX(mMinScale + (1.0f - mMinScale) * enterPercent);
setScaleY(mMinScale + (1.0f - mMinScale) * enterPercent);
}
@Override
public void onLeave(int index, int totalCount, float leavePercent, boolean leftToRight) {
super.onLeave(index, totalCount, leavePercent, leftToRight); // 实现颜色渐变
setScaleX(1.0f + (mMinScale - 1.0f) * leavePercent);
setScaleY(1.0f + (mMinScale - 1.0f) * leavePercent);
}
public float getMinScale() {
return mMinScale;
}
public void setMinScale(float minScale) {
mMinScale = minScale;
}
}

View File

@@ -0,0 +1,23 @@
package com.xuebiping.bolizhuzi.model.main;
public class LookMeBean {
private String id;
private String avatar_url;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getAvatar_url() {
return avatar_url;
}
public void setAvatar_url(String avatar_url) {
this.avatar_url = avatar_url;
}
}

View File

@@ -0,0 +1,17 @@
package com.xuebiping.bolizhuzi.model.main;
import java.util.ArrayList;
import java.util.List;
public class LookMeListBean {
private List<LookMeBean> list = new ArrayList<>();
public List<LookMeBean> getList() {
return list;
}
public void setList(List<LookMeBean> list) {
this.list = list;
}
}

View File

@@ -31,7 +31,7 @@ public class DynamicDetailTwoActivity extends BaseActivity {
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dynamic_detail_two); setContentView(R.layout.activity_dynamic_detail_two);
bean = getIntent().getParcelableExtra("bean"); bean = (DynamicsItemBean) getIntent().getSerializableExtra("bean");
mImageList.add(bean); mImageList.add(bean);
setTitleName("动态详情"); setTitleName("动态详情");

View File

@@ -178,15 +178,15 @@ public class RecentDynamicFragment extends Fragment {
@Override @Override
public void onDetailClicked(int position, String id) { public void onDetailClicked(int position, String id) {
detailPosition = position; detailPosition = position;
/*Intent intent = new Intent(getContext(), DynamicDetailActivity.class); Intent intent = new Intent(getContext(), DynamicDetailActivity.class);
intent.putExtra("dynamic_id", id); intent.putExtra("dynamic_id", id);
intent.putExtra("dynamic_from", 0); intent.putExtra("dynamic_from", 0);
startActivity(intent);*/
DynamicsItemBean itemBean = mAdapter.getmDynamicsItemList().get(position);
Intent intent = new Intent(getContext(), DynamicDetailTwoActivity.class);
intent.putExtra("bean", (Parcelable) itemBean);
startActivity(intent); startActivity(intent);
// DynamicsItemBean itemBean = mAdapter.getmDynamicsItemList().get(position);
// Intent intent = new Intent(getContext(), DynamicDetailTwoActivity.class);
// intent.putExtra("bean", itemBean);
// startActivity(intent);
} }
}); });

View File

@@ -0,0 +1,89 @@
package com.xuebiping.bolizhuzi.view.main;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.scwang.smartrefresh.layout.SmartRefreshLayout;
import com.scwang.smartrefresh.layout.api.RefreshLayout;
import com.scwang.smartrefresh.layout.listener.OnRefreshLoadMoreListener;
import com.xuebiping.bolizhuzi.R;
import com.xuebiping.bolizhuzi.controller.main.adapter.MainLookMeAdapter;
import com.xuebiping.bolizhuzi.model.main.LookMeBean;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
public class LookMeFragment extends Fragment implements OnRefreshLoadMoreListener {
private View v;
private SmartRefreshLayout mSmart_refresh;
private RecyclerView mRv_recommend_list;
private MainLookMeAdapter mMainLookMeAdapter;
private int mPage = 1;
private List<LookMeBean> mData = new ArrayList<>();
@Nullable
@org.jetbrains.annotations.Nullable
@Override
public View onCreateView(@NonNull @NotNull LayoutInflater inflater, @Nullable @org.jetbrains.annotations.Nullable ViewGroup container, @Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) {
v = inflater.inflate(R.layout.fragment_look_me, container, false);
initView(v);
getData(mPage);
return v;
}
private void initView(View v) {
mSmart_refresh = v.findViewById(R.id.smart_refresh);
mRv_recommend_list = v.findViewById(R.id.rv_recommend_list);
mRv_recommend_list.setLayoutManager(new LinearLayoutManager(getActivity()));
mMainLookMeAdapter = new MainLookMeAdapter(R.layout.item_main_look_me, getActivity());
mRv_recommend_list.setAdapter(mMainLookMeAdapter);
mSmart_refresh.setOnRefreshLoadMoreListener(this);
}
private void getData(int page) {
for (int i = 0; i < 10; i++) {
LookMeBean lookMeBean = new LookMeBean();
lookMeBean.setId(i + "");
lookMeBean.setAvatar_url("uploads/admin/202403/25/04cf409ab9148f11c0052bb254b5c155.jpg");
mData.add(lookMeBean);
}
finishFresh();
mMainLookMeAdapter.setList(mData);
}
public void finishFresh() {
mSmart_refresh.finishLoadMore();
mSmart_refresh.finishRefresh();
}
@Override
public void onLoadMore(@NonNull @NotNull RefreshLayout refreshLayout) {
mPage++;
getData(mPage);
}
@Override
public void onRefresh(@NonNull @NotNull RefreshLayout refreshLayout) {
mPage = 1;
getData(mPage);
}
}

View File

@@ -168,7 +168,7 @@ public class MainActivity extends BaseActivity implements DemoHelper.AppIdsUpdat
private LuckFragment luckFragment; private LuckFragment luckFragment;
private SwipeCardFragment swipeCardFragment; private SwipeCardFragment swipeCardFragment;
private DynamicViewPagerFragment mDynamicViewPagerFragment; private DynamicViewPagerFragment mDynamicViewPagerFragment;
private MainRecommendFragment mMainRecommendFragment; private MainRecommend2Fragment mMainRecommendFragment;
private MainMessageFragment mMainMessageFragment; private MainMessageFragment mMainMessageFragment;
private SettingFragment mSettingFragment; private SettingFragment mSettingFragment;
private Disposable mDisposable; private Disposable mDisposable;
@@ -280,27 +280,27 @@ public class MainActivity extends BaseActivity implements DemoHelper.AppIdsUpdat
} }
} }
@Override // @Override
protected void onNewIntent(Intent intent) { // protected void onNewIntent(Intent intent) {
super.onNewIntent(intent); // super.onNewIntent(intent);
boolean isFormTask = intent.getBooleanExtra("isFormTask", false); // boolean isFormTask = intent.getBooleanExtra("isFormTask", false);
boolean isMain = intent.getBooleanExtra("isMain", false); // boolean isMain = intent.getBooleanExtra("isMain", false);
if (isFormTask) { // if (isFormTask) {
mBottomTab.change(1); // mBottomTab.change(1);
} // }
if (isMain) { // if (isMain) {
int marketStatus = NoClearSPUtils.getInt(this, Constans.MARKET_STATUS, 0); // int marketStatus = NoClearSPUtils.getInt(this, Constans.MARKET_STATUS, 0);
if (marketStatus == 0 || SPUtils.getInt(this, ConsUser.TYPE) == 2) { // if (marketStatus == 0 || SPUtils.getInt(this, ConsUser.TYPE) == 2) {
mBottomTab.change(0); // mBottomTab.change(0);
} else { // } else {
if (UserManager.getUserInfo().isWomen()) { // if (UserManager.getUserInfo().isWomen()) {
mBottomTab.change(0); // mBottomTab.change(0);
} else { // } else {
mBottomTab.change(2); // mBottomTab.change(2);
} // }
} // }
} // }
} // }
/** /**
* 调起使用这个会弹出hms 下载框 * 调起使用这个会弹出hms 下载框
@@ -876,9 +876,9 @@ public class MainActivity extends BaseActivity implements DemoHelper.AppIdsUpdat
if (position == currentPosition) { //第二次点击 if (position == currentPosition) { //第二次点击
if (position == 0) { if (position == 0) {
if (isOne) { if (isOne) {
if (null != mMainRecommendFragment) { // if (null != mMainRecommendFragment) {
mMainRecommendFragment.clickRefresh(); // mMainRecommendFragment.clickRefresh();
} // }
} }
isOne = true; isOne = true;
} else if (position == 1) { } else if (position == 1) {
@@ -888,9 +888,9 @@ public class MainActivity extends BaseActivity implements DemoHelper.AppIdsUpdat
} }
} else if (position == 0) { //重新点击回来,检测版本更新 } else if (position == 0) { //重新点击回来,检测版本更新
checkUpdate(); checkUpdate();
if (null != mMainRecommendFragment) { // if (null != mMainRecommendFragment) {
mMainRecommendFragment.RefreshFragment(); // mMainRecommendFragment.RefreshFragment();
} // }
} else if (position == 3) { } else if (position == 3) {
// MaleToast.showMessage(MainActivity.this,"点击了消息"); // MaleToast.showMessage(MainActivity.this,"点击了消息");
getGreet(); getGreet();
@@ -1060,7 +1060,7 @@ public class MainActivity extends BaseActivity implements DemoHelper.AppIdsUpdat
mDynamicViewPagerFragment = new DynamicViewPagerFragment(); mDynamicViewPagerFragment = new DynamicViewPagerFragment();
} }
if (mMainRecommendFragment == null) { if (mMainRecommendFragment == null) {
mMainRecommendFragment = new MainRecommendFragment(); mMainRecommendFragment = new MainRecommend2Fragment();
} }
if (mMainMessageFragment == null) { if (mMainMessageFragment == null) {
mMainMessageFragment = new MainMessageFragment(); mMainMessageFragment = new MainMessageFragment();
@@ -1069,24 +1069,25 @@ public class MainActivity extends BaseActivity implements DemoHelper.AppIdsUpdat
mSettingFragment = new SettingFragment(); mSettingFragment = new SettingFragment();
} }
mBottomTab.addTab(mMainRecommendFragment);
mBottomTab.addTab(mDynamicViewPagerFragment);
if (marketStatus == 0 || SPUtils.getInt(this, ConsUser.TYPE) == 2) { if (marketStatus == 0 || SPUtils.getInt(this, ConsUser.TYPE) == 2) {
mBottomTab.addTab(swipeCardFragment); mBottomTab.addTab(swipeCardFragment);
} else { } else {
mBottomTab.addTab(luckFragment); mBottomTab.addTab(luckFragment);
} }
mBottomTab.addTab(mDynamicViewPagerFragment);
mBottomTab.addTab(mMainRecommendFragment);
mBottomTab.addTab(mMainMessageFragment); mBottomTab.addTab(mMainMessageFragment);
mBottomTab.addTab(mSettingFragment); mBottomTab.addTab(mSettingFragment);
if (marketStatus == 0 || SPUtils.getInt(this, ConsUser.TYPE) == 2) { mBottomTab.change(0);
mBottomTab.change(0); // if (marketStatus == 0 || SPUtils.getInt(this, ConsUser.TYPE) == 2) {
} else { // mBottomTab.change(0);
if (UserManager.getUserInfo().isWomen()) { // } else {
mBottomTab.change(0); // if (UserManager.getUserInfo().isWomen()) {
} else { // mBottomTab.change(0);
mBottomTab.change(2); // } else {
} // mBottomTab.change(2);
} // }
// }
} }
// //
// @Override // @Override

View File

@@ -0,0 +1,267 @@
package com.xuebiping.bolizhuzi.view.main;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Typeface;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.fragment.app.Fragment;
import androidx.viewpager.widget.ViewPager;
import com.fengliyan.uikit.UiUtils;
import com.fengliyan.uikit.toast.MaleToast;
import com.xuebiping.bolizhuzi.R;
import com.xuebiping.bolizhuzi.controller.main.adapter.MainViewPagerAdapter;
import com.xuebiping.bolizhuzi.controller.main.adapter.ScaleTransitionPagerTitleView;
import net.lucode.hackware.magicindicator.MagicIndicator;
import net.lucode.hackware.magicindicator.ViewPagerHelper;
import net.lucode.hackware.magicindicator.buildins.UIUtil;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.CommonNavigator;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.abs.CommonNavigatorAdapter;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.abs.IPagerIndicator;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.abs.IPagerTitleView;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.indicators.LinePagerIndicator;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.titles.CommonPagerTitleView;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.titles.SimplePagerTitleView;
import java.util.ArrayList;
import java.util.List;
public class MainRecommend2Fragment extends Fragment implements View.OnClickListener {
private View v;
private RelativeLayout mRl_home_search;
private LinearLayout mLl_select;
private MagicIndicator mMagicIndicator;
private ViewPager mMainViewPager;
private MainViewPagerAdapter mViewPagerAdapter;
private List<Fragment> mChannelFragments = new ArrayList<>();
private List<String> mDataList = new ArrayList<>();
private int mIndex = 1;
private LookMeFragment mLookMeFragment;
private RecommendFragment1 mLookMeFragment1;
private DefaultRecommendFragment mLookMeFragment2;
private MainRecommendActiveFragment mLookMeFragment3;
private MainRecommendPeopleFragment mLookMeFragment4;
private MainRecommendCityFragment mLookMeFragment5;
private LookMeFragment mLookMeFragment6;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
v = inflater.inflate(R.layout.fragment_main_recommend2, container, false);
initView(v);
return v;
}
private void initView(View v) {
mLl_select = v.findViewById(R.id.ll_select);
mRl_home_search = v.findViewById(R.id.rl_home_search);
mMagicIndicator = v.findViewById(R.id.magic_indicator);
mMainViewPager = v.findViewById(R.id.main_view_pager);
mLl_select.setOnClickListener(this);
mRl_home_search.setOnClickListener(this);
mLookMeFragment = new LookMeFragment();
mLookMeFragment1 = new RecommendFragment1();
mLookMeFragment2 = new DefaultRecommendFragment();
mLookMeFragment3 = new MainRecommendActiveFragment();
mLookMeFragment4 = new MainRecommendPeopleFragment();
mLookMeFragment5 = new MainRecommendCityFragment();
mLookMeFragment6 = new LookMeFragment();
mChannelFragments.add(mLookMeFragment);
mChannelFragments.add(mLookMeFragment1);
mChannelFragments.add(mLookMeFragment2);
mChannelFragments.add(mLookMeFragment3);
mChannelFragments.add(mLookMeFragment4);
mChannelFragments.add(mLookMeFragment5);
mChannelFragments.add(mLookMeFragment6);
mViewPagerAdapter = new MainViewPagerAdapter(getChildFragmentManager(),
mChannelFragments);
mMainViewPager.setAdapter(mViewPagerAdapter);
initMagicIndicator();
mMainViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
// if (position == 3) {
// isReClick = true;
// mIv_more_city.setVisibility(View.VISIBLE);
// } else {
// isReClick = false;
// mIv_more_city.setVisibility(View.INVISIBLE);
// }
//
mIndex = position;
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
mViewPagerAdapter.notifyDataSetChanged();
mMainViewPager.setCurrentItem(mIndex);
}
private void initMagicIndicator() {
mDataList.clear();
mDataList.add("看过我");
mDataList.add("推荐");
mDataList.add("语聊");
mDataList.add("新人");
mDataList.add("五星");
mDataList.add("四星");
mDataList.add("三星");
CommonNavigator commonNavigator = new CommonNavigator(getActivity());
commonNavigator.setAdapter(new CommonNavigatorAdapter() {
@Override
public int getCount() {
return mDataList == null ? 0 : mDataList.size();
}
@Override
public IPagerTitleView getTitleView(Context context, final int index) {
SimplePagerTitleView simplePagerTitleView = new ScaleTransitionPagerTitleView(context);
simplePagerTitleView.setText(mDataList.get(index));
simplePagerTitleView.setTextSize(20);
simplePagerTitleView.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//加粗
simplePagerTitleView.setNormalColor(Color.parseColor("#33000000"));
simplePagerTitleView.setSelectedColor(Color.parseColor("#000000"));
simplePagerTitleView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// if (isReClick && index == 3) {
// Intent intent = new Intent(getActivity(), CityPickerActivity.class);
// startActivityForResult(intent, RECOMMEND_CHANGE_CITY_REQUEST);
// } else {
// mMainViewPager.setCurrentItem(index);
// }
Log.d("nail", "onClick: " + index);
mMainViewPager.setCurrentItem(index);
}
});
return simplePagerTitleView;
// CommonPagerTitleView commonPagerTitleView = new CommonPagerTitleView(getActivity());
// commonPagerTitleView.setContentView(R.layout.main_pager_title_layout);
//
// // 初始化
// ImageView iv_selected = (ImageView) commonPagerTitleView.findViewById(R.id.iv_selected);
// ImageView iv_no_selected = (ImageView) commonPagerTitleView.findViewById(R.id.iv_no_selected);
// final TextView titleText = (TextView) commonPagerTitleView.findViewById(R.id.title_text);
// titleText.setText(mDataList.get(index));
// commonPagerTitleView.setPadding(UIUtil.dip2px(context, 5),
// UIUtil.dip2px(context, 0),
// UIUtil.dip2px(context, 5),
// UIUtil.dip2px(context, 0));
//
// commonPagerTitleView.setOnPagerTitleChangeListener(new CommonPagerTitleView.OnPagerTitleChangeListener() {
//
// @Override
// public void onSelected(int index, int totalCount) {
// titleText.setTextSize(16);
// titleText.setTextColor(Color.parseColor("#ffffff"));
// titleText.setTypeface(Typeface.DEFAULT_BOLD);
// iv_selected.setVisibility(View.VISIBLE);
// iv_no_selected.setVisibility(View.INVISIBLE);
// }
//
// @Override
// public void onDeselected(int index, int totalCount) {
// titleText.setTextSize(16);
// titleText.setTextColor(Color.parseColor("#33000000"));
// titleText.setTypeface(Typeface.DEFAULT);
// iv_selected.setVisibility(View.INVISIBLE);
// iv_no_selected.setVisibility(View.VISIBLE);
// }
//
// @Override
// public void onLeave(int index, int totalCount, float leavePercent, boolean leftToRight) {
// // rl_title_bg.setScaleX(1.3f + (0.8f - 1.3f) * leavePercent);
// //rl_title_bg.setScaleY(1.3f + (0.8f - 1.3f) * leavePercent);
// }
//
// @Override
// public void onEnter(int index, int totalCount, float enterPercent, boolean leftToRight) {
// // rl_title_bg.setScaleX(0.8f + (1.3f - 0.8f) * enterPercent);
// // rl_title_bg.setScaleY(0.8f + (1.3f - 0.8f) * enterPercent);
// }
// });
//
// commonPagerTitleView.setOnClickListener(new View.OnClickListener() {
// @Override
// public void onClick(View v) {
// if (isReClick && index == 3) {
// Intent intent = new Intent(getActivity(), CityPickerActivity.class);
// startActivityForResult(intent, RECOMMEND_CHANGE_CITY_REQUEST);
// } else {
// mMainViewPager.setCurrentItem(index);
// }
// mMainViewPager.setCurrentItem(index);
// }
// });
//
// return commonPagerTitleView;
}
@Override
public IPagerIndicator getIndicator(Context context) {
// LinePagerIndicator indicator = new LinePagerIndicator(context);
// indicator.setMode(LinePagerIndicator.MODE_WRAP_CONTENT);
// indicator.setLineHeight(UIUtil.dip2px(context, 10));
// indicator.setLineWidth(UIUtil.dip2px(context, 20));
// indicator.setRoundRadius(UIUtil.dip2px(context, 0));
// indicator.setStartInterpolator(new AccelerateInterpolator());
// indicator.setEndInterpolator(new DecelerateInterpolator(2.0f));
// indicator.setColors(getResources().getColor(R.color.yellow_ffd33e));
// indicator.setYOffset(UIUtil.dip2px(context, 10));
// indicator.setXOffset(0);
LinePagerIndicator indicator = new LinePagerIndicator(context);
indicator.setColors(getResources().getColor(R.color.yellow_ffd33e));
indicator.setLineHeight(UIUtil.dip2px(context, 10));
indicator.setMode(LinePagerIndicator.MODE_WRAP_CONTENT);
return null;
}
});
mMagicIndicator.setNavigator(commonNavigator);
ViewPagerHelper.bind(mMagicIndicator, mMainViewPager);
}
@Override
public void onClick(View view) {
if (view == mRl_home_search) {
MaleToast.showMessage(getActivity(), "搜索");
}else if (view == mLl_select) {
MaleToast.showMessage(getActivity(), "筛选");
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 647 B

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#6CE4B7"/>
<corners android:radius="@dimen/dp16"/>
</shape>

View File

@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:viewBindingIgnore="true">
<LinearLayout
android:id="@+id/ll_content_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.scwang.smartrefresh.layout.SmartRefreshLayout
android:id="@+id/smart_refresh"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="visible">
<com.scwang.smartrefresh.layout.header.ClassicsHeader
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:srlEnableLastTime="false" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="@+id/rl_no_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="@dimen/dp100"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone">
<ImageView
android:layout_width="@dimen/dp150"
android:layout_height="@dimen/dp88"
android:src="@mipmap/icon_img_no_black" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp5"
android:text="暂无数据"
android:textColor="@color/three_text"
android:textSize="13sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_recommend_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="@dimen/dp_10" />
</LinearLayout>
</LinearLayout>
<com.scwang.smartrefresh.layout.footer.ClassicsFooter
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.scwang.smartrefresh.layout.SmartRefreshLayout>
</LinearLayout>
</LinearLayout>

View File

@@ -0,0 +1,65 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/rl_head"
android:layout_marginTop="24dp"
android:layout_width="match_parent"
android:layout_height="@dimen/dp48">
<LinearLayout
android:id="@+id/ll_select"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="筛选"
android:textColor="#ffe472ed"
android:textSize="13sp"
/>
<ImageView
android:layout_marginLeft="5dp"
android:layout_gravity="center_vertical"
android:src="@drawable/ic_main_select_man_and_woman"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<net.lucode.hackware.magicindicator.MagicIndicator
android:id="@+id/magic_indicator"
android:layout_width="1000dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_gravity="center_vertical" />
<RelativeLayout
android:id="@+id/rl_home_search"
android:layout_alignParentRight="true"
android:layout_width="@dimen/dp44"
android:layout_height="match_parent">
<ImageView
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_home_search" />
</RelativeLayout>
</LinearLayout>
<androidx.viewpager.widget.ViewPager
android:id="@+id/main_view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/rl_head" />
</RelativeLayout>

View File

@@ -0,0 +1,108 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:fresco="http://schemas.android.com/apk/res-auto">
<LinearLayout
android:layout_marginTop="@dimen/dp10"
android:layout_marginBottom="@dimen/dp10"
android:layout_marginLeft="@dimen/dp16"
android:layout_marginRight="@dimen/dp16"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RelativeLayout
android:layout_width="@dimen/dp50"
android:layout_height="@dimen/dp50">
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/list_photo"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerVertical="true"
fresco:roundAsCircle="true" />
<RelativeLayout
android:id="@+id/rl_online_bg"
android:layout_width="@dimen/dp30"
android:layout_height="@dimen/dp16"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@drawable/look_me_online_bg">
<TextView
android:id="@+id/tv_online"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="在线"
android:textColor="@color/white"
android:textSize="10sp" />
</RelativeLayout>
</RelativeLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="center_vertical"
android:layout_marginLeft="@dimen/dp12"
android:orientation="vertical">
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="瑞恩 Rain"
android:textColor="@color/one_text"
android:textSize="15sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tv_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp6"
android:text="1小时前在线"
android:textColor="@color/three_text"
android:textSize="12sp" />
</LinearLayout>
<LinearLayout
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="共 "
android:textColor="@color/three_text"
android:textSize="14sp"
/>
<TextView
android:id="@+id/tv_visit_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1次"
android:textColor="@color/yellow_ffd33e"
android:textSize="14sp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=" 访问"
android:textColor="@color/three_text"
android:textSize="14sp"
/>
</LinearLayout>
</LinearLayout>
</RelativeLayout>

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -0,0 +1,20 @@
apply plugin: 'com.android.library'
android {
compileSdkVersion 28
defaultConfig {
minSdkVersion 21
targetSdkVersion 28
}
buildTypes {
release {
minifyEnabled false
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
}

View File

@@ -0,0 +1 @@
<manifest package="net.lucode.hackware.magicindicator" />

View File

@@ -0,0 +1,162 @@
package net.lucode.hackware.magicindicator;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.os.Build;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Interpolator;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.model.PositionData;
import java.util.ArrayList;
import java.util.List;
/**
* 使得MagicIndicator在FragmentContainer中使用
* Created by hackware on 2016/9/4.
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class FragmentContainerHelper {
private List<MagicIndicator> mMagicIndicators = new ArrayList<MagicIndicator>();
private ValueAnimator mScrollAnimator;
private int mLastSelectedIndex;
private int mDuration = 150;
private Interpolator mInterpolator = new AccelerateDecelerateInterpolator();
private Animator.AnimatorListener mAnimatorListener = new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
dispatchPageScrollStateChanged(ScrollState.SCROLL_STATE_IDLE);
mScrollAnimator = null;
}
};
private ValueAnimator.AnimatorUpdateListener mAnimatorUpdateListener = new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float positionOffsetSum = (Float) animation.getAnimatedValue();
int position = (int) positionOffsetSum;
float positionOffset = positionOffsetSum - position;
if (positionOffsetSum < 0) {
position = position - 1;
positionOffset = 1.0f + positionOffset;
}
dispatchPageScrolled(position, positionOffset, 0);
}
};
public FragmentContainerHelper() {
}
public FragmentContainerHelper(MagicIndicator magicIndicator) {
mMagicIndicators.add(magicIndicator);
}
/**
* IPagerIndicator支持弹性效果的辅助方法
*
* @param positionDataList
* @param index
* @return
*/
public static PositionData getImitativePositionData(List<PositionData> positionDataList, int index) {
if (index >= 0 && index <= positionDataList.size() - 1) { // 越界后返回假的PositionData
return positionDataList.get(index);
} else {
PositionData result = new PositionData();
PositionData referenceData;
int offset;
if (index < 0) {
offset = index;
referenceData = positionDataList.get(0);
} else {
offset = index - positionDataList.size() + 1;
referenceData = positionDataList.get(positionDataList.size() - 1);
}
result.mLeft = referenceData.mLeft + offset * referenceData.width();
result.mTop = referenceData.mTop;
result.mRight = referenceData.mRight + offset * referenceData.width();
result.mBottom = referenceData.mBottom;
result.mContentLeft = referenceData.mContentLeft + offset * referenceData.width();
result.mContentTop = referenceData.mContentTop;
result.mContentRight = referenceData.mContentRight + offset * referenceData.width();
result.mContentBottom = referenceData.mContentBottom;
return result;
}
}
public void handlePageSelected(int selectedIndex) {
handlePageSelected(selectedIndex, true);
}
public void handlePageSelected(int selectedIndex, boolean smooth) {
if (mLastSelectedIndex == selectedIndex) {
return;
}
if (smooth) {
if (mScrollAnimator == null || !mScrollAnimator.isRunning()) {
dispatchPageScrollStateChanged(ScrollState.SCROLL_STATE_SETTLING);
}
dispatchPageSelected(selectedIndex);
float currentPositionOffsetSum = mLastSelectedIndex;
if (mScrollAnimator != null) {
currentPositionOffsetSum = (Float) mScrollAnimator.getAnimatedValue();
mScrollAnimator.cancel();
mScrollAnimator = null;
}
mScrollAnimator = new ValueAnimator();
mScrollAnimator.setFloatValues(currentPositionOffsetSum, selectedIndex); // position = selectedIndex, positionOffset = 0.0f
mScrollAnimator.addUpdateListener(mAnimatorUpdateListener);
mScrollAnimator.addListener(mAnimatorListener);
mScrollAnimator.setInterpolator(mInterpolator);
mScrollAnimator.setDuration(mDuration);
mScrollAnimator.start();
} else {
dispatchPageSelected(selectedIndex);
if (mScrollAnimator != null && mScrollAnimator.isRunning()) {
dispatchPageScrolled(mLastSelectedIndex, 0.0f, 0);
}
dispatchPageScrollStateChanged(ScrollState.SCROLL_STATE_IDLE);
dispatchPageScrolled(selectedIndex, 0.0f, 0);
}
mLastSelectedIndex = selectedIndex;
}
public void setDuration(int duration) {
mDuration = duration;
}
public void setInterpolator(Interpolator interpolator) {
if (interpolator == null) {
mInterpolator = new AccelerateDecelerateInterpolator();
} else {
mInterpolator = interpolator;
}
}
public void attachMagicIndicator(MagicIndicator magicIndicator) {
mMagicIndicators.add(magicIndicator);
}
private void dispatchPageSelected(int pageIndex) {
for (MagicIndicator magicIndicator : mMagicIndicators) {
magicIndicator.onPageSelected(pageIndex);
}
}
private void dispatchPageScrollStateChanged(int state) {
for (MagicIndicator magicIndicator : mMagicIndicators) {
magicIndicator.onPageScrollStateChanged(state);
}
}
private void dispatchPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
for (MagicIndicator magicIndicator : mMagicIndicators) {
magicIndicator.onPageScrolled(position, positionOffset, positionOffsetPixels);
}
}
}

View File

@@ -0,0 +1,63 @@
package net.lucode.hackware.magicindicator;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;
import net.lucode.hackware.magicindicator.abs.IPagerNavigator;
/**
* 整个框架的入口,核心
* 博客: http://hackware.lucode.net
* Created by hackware on 2016/6/26.
*/
public class MagicIndicator extends FrameLayout {
private IPagerNavigator mNavigator;
public MagicIndicator(Context context) {
super(context);
}
public MagicIndicator(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (mNavigator != null) {
mNavigator.onPageScrolled(position, positionOffset, positionOffsetPixels);
}
}
public void onPageSelected(int position) {
if (mNavigator != null) {
mNavigator.onPageSelected(position);
}
}
public void onPageScrollStateChanged(int state) {
if (mNavigator != null) {
mNavigator.onPageScrollStateChanged(state);
}
}
public IPagerNavigator getNavigator() {
return mNavigator;
}
public void setNavigator(IPagerNavigator navigator) {
if (mNavigator == navigator) {
return;
}
if (mNavigator != null) {
mNavigator.onDetachFromMagicIndicator();
}
mNavigator = navigator;
removeAllViews();
if (mNavigator instanceof View) {
LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
addView((View) mNavigator, lp);
mNavigator.onAttachToMagicIndicator();
}
}
}

View File

@@ -0,0 +1,170 @@
package net.lucode.hackware.magicindicator;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
/**
* 方便扩展IPagerNavigator的帮助类将ViewPager的3个回调方法转换成
* onSelected、onDeselected、onEnter等回调方便扩展
* 博客: http://hackware.lucode.net
* Created by hackware on 2016/6/26.
*/
public class NavigatorHelper {
private SparseBooleanArray mDeselectedItems = new SparseBooleanArray();
private SparseArray<Float> mLeavedPercents = new SparseArray<Float>();
private int mTotalCount;
private int mCurrentIndex;
private int mLastIndex;
private float mLastPositionOffsetSum;
private int mScrollState;
private boolean mSkimOver;
private NavigatorHelper.OnNavigatorScrollListener mNavigatorScrollListener;
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
float currentPositionOffsetSum = position + positionOffset;
boolean leftToRight = false;
if (mLastPositionOffsetSum <= currentPositionOffsetSum) {
leftToRight = true;
}
if (mScrollState != ScrollState.SCROLL_STATE_IDLE) {
if (currentPositionOffsetSum == mLastPositionOffsetSum) {
return;
}
int nextPosition = position + 1;
boolean normalDispatch = true;
if (positionOffset == 0.0f) {
if (leftToRight) {
nextPosition = position - 1;
normalDispatch = false;
}
}
for (int i = 0; i < mTotalCount; i++) {
if (i == position || i == nextPosition) {
continue;
}
Float leavedPercent = mLeavedPercents.get(i, 0.0f);
if (leavedPercent != 1.0f) {
dispatchOnLeave(i, 1.0f, leftToRight, true);
}
}
if (normalDispatch) {
if (leftToRight) {
dispatchOnLeave(position, positionOffset, true, false);
dispatchOnEnter(nextPosition, positionOffset, true, false);
} else {
dispatchOnLeave(nextPosition, 1.0f - positionOffset, false, false);
dispatchOnEnter(position, 1.0f - positionOffset, false, false);
}
} else {
dispatchOnLeave(nextPosition, 1.0f - positionOffset, true, false);
dispatchOnEnter(position, 1.0f - positionOffset, true, false);
}
} else {
for (int i = 0; i < mTotalCount; i++) {
if (i == mCurrentIndex) {
continue;
}
boolean deselected = mDeselectedItems.get(i);
if (!deselected) {
dispatchOnDeselected(i);
}
Float leavedPercent = mLeavedPercents.get(i, 0.0f);
if (leavedPercent != 1.0f) {
dispatchOnLeave(i, 1.0f, false, true);
}
}
dispatchOnEnter(mCurrentIndex, 1.0f, false, true);
dispatchOnSelected(mCurrentIndex);
}
mLastPositionOffsetSum = currentPositionOffsetSum;
}
private void dispatchOnEnter(int index, float enterPercent, boolean leftToRight, boolean force) {
if (mSkimOver || index == mCurrentIndex || mScrollState == ScrollState.SCROLL_STATE_DRAGGING || force) {
if (mNavigatorScrollListener != null) {
mNavigatorScrollListener.onEnter(index, mTotalCount, enterPercent, leftToRight);
}
mLeavedPercents.put(index, 1.0f - enterPercent);
}
}
private void dispatchOnLeave(int index, float leavePercent, boolean leftToRight, boolean force) {
if (mSkimOver || index == mLastIndex || mScrollState == ScrollState.SCROLL_STATE_DRAGGING || ((index == mCurrentIndex - 1 || index == mCurrentIndex + 1) && mLeavedPercents.get(index, 0.0f) != 1.0f) || force) {
if (mNavigatorScrollListener != null) {
mNavigatorScrollListener.onLeave(index, mTotalCount, leavePercent, leftToRight);
}
mLeavedPercents.put(index, leavePercent);
}
}
private void dispatchOnSelected(int index) {
if (mNavigatorScrollListener != null) {
mNavigatorScrollListener.onSelected(index, mTotalCount);
}
mDeselectedItems.put(index, false);
}
private void dispatchOnDeselected(int index) {
if (mNavigatorScrollListener != null) {
mNavigatorScrollListener.onDeselected(index, mTotalCount);
}
mDeselectedItems.put(index, true);
}
public void onPageSelected(int position) {
mLastIndex = mCurrentIndex;
mCurrentIndex = position;
dispatchOnSelected(mCurrentIndex);
for (int i = 0; i < mTotalCount; i++) {
if (i == mCurrentIndex) {
continue;
}
boolean deselected = mDeselectedItems.get(i);
if (!deselected) {
dispatchOnDeselected(i);
}
}
}
public void onPageScrollStateChanged(int state) {
mScrollState = state;
}
public void setNavigatorScrollListener(NavigatorHelper.OnNavigatorScrollListener navigatorScrollListener) {
mNavigatorScrollListener = navigatorScrollListener;
}
public void setSkimOver(boolean skimOver) {
mSkimOver = skimOver;
}
public int getTotalCount() {
return mTotalCount;
}
public void setTotalCount(int totalCount) {
mTotalCount = totalCount;
mDeselectedItems.clear();
mLeavedPercents.clear();
}
public int getCurrentIndex() {
return mCurrentIndex;
}
public int getScrollState() {
return mScrollState;
}
public interface OnNavigatorScrollListener {
void onEnter(int index, int totalCount, float enterPercent, boolean leftToRight);
void onLeave(int index, int totalCount, float leavePercent, boolean leftToRight);
void onSelected(int index, int totalCount);
void onDeselected(int index, int totalCount);
}
}

View File

@@ -0,0 +1,12 @@
package net.lucode.hackware.magicindicator;
/**
* 自定义滚动状态消除对ViewPager的依赖
* Created by hackware on 2016/8/27.
*/
public interface ScrollState {
int SCROLL_STATE_IDLE = 0;
int SCROLL_STATE_DRAGGING = 1;
int SCROLL_STATE_SETTLING = 2;
}

View File

@@ -0,0 +1,30 @@
package net.lucode.hackware.magicindicator;
import androidx.viewpager.widget.ViewPager;
/**
* 简化和ViewPager绑定
* Created by hackware on 2016/8/17.
*/
public class ViewPagerHelper {
public static void bind(final MagicIndicator magicIndicator, ViewPager viewPager) {
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
magicIndicator.onPageScrolled(position, positionOffset, positionOffsetPixels);
}
@Override
public void onPageSelected(int position) {
magicIndicator.onPageSelected(position);
}
@Override
public void onPageScrollStateChanged(int state) {
magicIndicator.onPageScrollStateChanged(state);
}
});
}
}

View File

@@ -0,0 +1,32 @@
package net.lucode.hackware.magicindicator.abs;
/**
* 抽象的ViewPager导航器
* 博客: http://hackware.lucode.net
* Created by hackware on 2016/6/26.
*/
public interface IPagerNavigator {
///////////////////////// ViewPager的3个回调
void onPageScrolled(int position, float positionOffset, int positionOffsetPixels);
void onPageSelected(int position);
void onPageScrollStateChanged(int state);
/////////////////////////
/**
* 当IPagerNavigator被添加到MagicIndicator时调用
*/
void onAttachToMagicIndicator();
/**
* 当IPagerNavigator从MagicIndicator上移除时调用
*/
void onDetachFromMagicIndicator();
/**
* ViewPager内容改变时需要先调用此方法自定义的IPagerNavigator应当遵守此约定
*/
void notifyDataSetChanged();
}

View File

@@ -0,0 +1,28 @@
package net.lucode.hackware.magicindicator.buildins;
/**
* 实现颜色渐变考虑到兼容性不使用内置的ArgbEvaluator
* 博客: http://hackware.lucode.net
* Created by hackware on 2016/6/26.
*/
public class ArgbEvaluatorHolder {
public static int eval(float fraction, int startValue, int endValue) {
int startA = (startValue >> 24) & 0xff;
int startR = (startValue >> 16) & 0xff;
int startG = (startValue >> 8) & 0xff;
int startB = startValue & 0xff;
int endA = (endValue >> 24) & 0xff;
int endR = (endValue >> 16) & 0xff;
int endG = (endValue >> 8) & 0xff;
int endB = endValue & 0xff;
int currentA = (startA + (int) (fraction * (endA - startA))) << 24;
int currentR = (startR + (int) (fraction * (endR - startR))) << 16;
int currentG = (startG + (int) (fraction * (endG - startG))) << 8;
int currentB = startB + (int) (fraction * (endB - startB));
return currentA | currentR | currentG | currentB;
}
}

View File

@@ -0,0 +1,19 @@
package net.lucode.hackware.magicindicator.buildins;
import android.content.Context;
/**
* 博客: http://hackware.lucode.net
* Created by hackware on 2016/6/26.
*/
public final class UIUtil {
public static int dip2px(Context context, double dpValue) {
float density = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * density + 0.5);
}
public static int getScreenWidth(Context context) {
return context.getResources().getDisplayMetrics().widthPixels;
}
}

View File

@@ -0,0 +1,309 @@
package net.lucode.hackware.magicindicator.buildins.circlenavigator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PointF;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import net.lucode.hackware.magicindicator.abs.IPagerNavigator;
import net.lucode.hackware.magicindicator.buildins.UIUtil;
import java.util.ArrayList;
import java.util.List;
/**
* 圆圈式的指示器
* 博客: http://hackware.lucode.net
* Created by hackware on 2016/6/26.
*/
public class CircleNavigator extends View implements IPagerNavigator {
private int mRadius;
private int mCircleColor;
private int mStrokeWidth;
private int mCircleSpacing;
private int mCurrentIndex;
private int mTotalCount;
private Interpolator mStartInterpolator = new LinearInterpolator();
private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private List<PointF> mCirclePoints = new ArrayList<PointF>();
private float mIndicatorX;
// 事件回调
private boolean mTouchable;
private OnCircleClickListener mCircleClickListener;
private float mDownX;
private float mDownY;
private int mTouchSlop;
private boolean mFollowTouch = true; // 是否跟随手指滑动
public CircleNavigator(Context context) {
super(context);
init(context);
}
private void init(Context context) {
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
mRadius = UIUtil.dip2px(context, 3);
mCircleSpacing = UIUtil.dip2px(context, 8);
mStrokeWidth = UIUtil.dip2px(context, 1);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
}
private int measureWidth(int widthMeasureSpec) {
int mode = MeasureSpec.getMode(widthMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int result = 0;
switch (mode) {
case MeasureSpec.EXACTLY:
result = width;
break;
case MeasureSpec.AT_MOST:
case MeasureSpec.UNSPECIFIED:
result = mTotalCount * mRadius * 2 + (mTotalCount - 1) * mCircleSpacing + getPaddingLeft() + getPaddingRight() + mStrokeWidth * 2;
break;
default:
break;
}
return result;
}
private int measureHeight(int heightMeasureSpec) {
int mode = MeasureSpec.getMode(heightMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
int result = 0;
switch (mode) {
case MeasureSpec.EXACTLY:
result = height;
break;
case MeasureSpec.AT_MOST:
case MeasureSpec.UNSPECIFIED:
result = mRadius * 2 + mStrokeWidth * 2 + getPaddingTop() + getPaddingBottom();
break;
default:
break;
}
return result;
}
@Override
protected void onDraw(Canvas canvas) {
mPaint.setColor(mCircleColor);
drawCircles(canvas);
drawIndicator(canvas);
}
private void drawCircles(Canvas canvas) {
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(mStrokeWidth);
for (int i = 0, j = mCirclePoints.size(); i < j; i++) {
PointF pointF = mCirclePoints.get(i);
canvas.drawCircle(pointF.x, pointF.y, mRadius, mPaint);
}
}
private void drawIndicator(Canvas canvas) {
mPaint.setStyle(Paint.Style.FILL);
if (mCirclePoints.size() > 0) {
canvas.drawCircle(mIndicatorX, (int) (getHeight() / 2.0f + 0.5f), mRadius, mPaint);
}
}
private void prepareCirclePoints() {
mCirclePoints.clear();
if (mTotalCount > 0) {
int y = (int) (getHeight() / 2.0f + 0.5f);
int centerSpacing = mRadius * 2 + mCircleSpacing;
int startX = mRadius + (int) (mStrokeWidth / 2.0f + 0.5f) + getPaddingLeft();
for (int i = 0; i < mTotalCount; i++) {
PointF pointF = new PointF(startX, y);
mCirclePoints.add(pointF);
startX += centerSpacing;
}
mIndicatorX = mCirclePoints.get(mCurrentIndex).x;
}
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (mFollowTouch) {
if (mCirclePoints.isEmpty()) {
return;
}
int currentPosition = Math.min(mCirclePoints.size() - 1, position);
int nextPosition = Math.min(mCirclePoints.size() - 1, position + 1);
PointF current = mCirclePoints.get(currentPosition);
PointF next = mCirclePoints.get(nextPosition);
mIndicatorX = current.x + (next.x - current.x) * mStartInterpolator.getInterpolation(positionOffset);
invalidate();
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (mTouchable) {
mDownX = x;
mDownY = y;
return true;
}
break;
case MotionEvent.ACTION_UP:
if (mCircleClickListener != null) {
if (Math.abs(x - mDownX) <= mTouchSlop && Math.abs(y - mDownY) <= mTouchSlop) {
float max = Float.MAX_VALUE;
int index = 0;
for (int i = 0; i < mCirclePoints.size(); i++) {
PointF pointF = mCirclePoints.get(i);
float offset = Math.abs(pointF.x - x);
if (offset < max) {
max = offset;
index = i;
}
}
mCircleClickListener.onClick(index);
}
}
break;
default:
break;
}
return super.onTouchEvent(event);
}
@Override
public void onPageSelected(int position) {
mCurrentIndex = position;
if (!mFollowTouch) {
mIndicatorX = mCirclePoints.get(mCurrentIndex).x;
invalidate();
}
}
@Override
public void onPageScrollStateChanged(int state) {
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
prepareCirclePoints();
}
@Override
public void onAttachToMagicIndicator() {
}
@Override
public void notifyDataSetChanged() {
prepareCirclePoints();
invalidate();
}
@Override
public void onDetachFromMagicIndicator() {
}
public int getRadius() {
return mRadius;
}
public void setRadius(int radius) {
mRadius = radius;
prepareCirclePoints();
invalidate();
}
public int getCircleColor() {
return mCircleColor;
}
public void setCircleColor(int circleColor) {
mCircleColor = circleColor;
invalidate();
}
public int getStrokeWidth() {
return mStrokeWidth;
}
public void setStrokeWidth(int strokeWidth) {
mStrokeWidth = strokeWidth;
invalidate();
}
public int getCircleSpacing() {
return mCircleSpacing;
}
public void setCircleSpacing(int circleSpacing) {
mCircleSpacing = circleSpacing;
prepareCirclePoints();
invalidate();
}
public Interpolator getStartInterpolator() {
return mStartInterpolator;
}
public void setStartInterpolator(Interpolator startInterpolator) {
mStartInterpolator = startInterpolator;
if (mStartInterpolator == null) {
mStartInterpolator = new LinearInterpolator();
}
}
public int getCircleCount() {
return mTotalCount;
}
public void setCircleCount(int count) {
mTotalCount = count; // 此处不调用invalidate让外部调用notifyDataSetChanged
}
public boolean isTouchable() {
return mTouchable;
}
public void setTouchable(boolean touchable) {
mTouchable = touchable;
}
public boolean isFollowTouch() {
return mFollowTouch;
}
public void setFollowTouch(boolean followTouch) {
mFollowTouch = followTouch;
}
public OnCircleClickListener getCircleClickListener() {
return mCircleClickListener;
}
public void setCircleClickListener(OnCircleClickListener circleClickListener) {
if (!mTouchable) {
mTouchable = true;
}
mCircleClickListener = circleClickListener;
}
public interface OnCircleClickListener {
void onClick(int index);
}
}

View File

@@ -0,0 +1,425 @@
package net.lucode.hackware.magicindicator.buildins.commonnavigator;
import android.content.Context;
import android.database.DataSetObserver;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import net.lucode.hackware.magicindicator.NavigatorHelper;
import net.lucode.hackware.magicindicator.R;
import net.lucode.hackware.magicindicator.ScrollState;
import net.lucode.hackware.magicindicator.abs.IPagerNavigator;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.abs.CommonNavigatorAdapter;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.abs.IMeasurablePagerTitleView;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.abs.IPagerIndicator;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.abs.IPagerTitleView;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.model.PositionData;
import java.util.ArrayList;
import java.util.List;
/**
* 通用的ViewPager指示器包含PagerTitle和PagerIndicator
* 博客: http://hackware.lucode.net
* Created by hackware on 2016/6/26.
*/
public class CommonNavigator extends FrameLayout implements IPagerNavigator, NavigatorHelper.OnNavigatorScrollListener {
private HorizontalScrollView mScrollView;
private LinearLayout mTitleContainer;
private LinearLayout mIndicatorContainer;
private IPagerIndicator mIndicator;
private CommonNavigatorAdapter mAdapter;
private NavigatorHelper mNavigatorHelper;
/**
* 提供给外部的参数配置
*/
/****************************************************/
private boolean mAdjustMode; // 自适应模式适用于数目固定的、少量的title
private boolean mEnablePivotScroll; // 启动中心点滚动
private float mScrollPivotX = 0.5f; // 滚动中心点 0.0f - 1.0f
private boolean mSmoothScroll = true; // 是否平滑滚动,适用于 !mAdjustMode && !mFollowTouch
private boolean mFollowTouch = true; // 是否手指跟随滚动
private int mRightPadding;
private int mLeftPadding;
private boolean mIndicatorOnTop; // 指示器是否在title上层默认为下层
private boolean mSkimOver; // 跨多页切换时,中间页是否显示 "掠过" 效果
private boolean mReselectWhenLayout = true; // PositionData准备好时是否重新选中当前页为true可保证在极端情况下指示器状态正确
/****************************************************/
// 保存每个title的位置信息为扩展indicator提供保障
private List<PositionData> mPositionDataList = new ArrayList<PositionData>();
private DataSetObserver mObserver = new DataSetObserver() {
@Override
public void onChanged() {
mNavigatorHelper.setTotalCount(mAdapter.getCount()); // 如果使用helper应始终保证helper中的totalCount为最新
init();
}
@Override
public void onInvalidated() {
// 没什么用,暂不做处理
}
};
public CommonNavigator(Context context) {
super(context);
mNavigatorHelper = new NavigatorHelper();
mNavigatorHelper.setNavigatorScrollListener(this);
}
@Override
public void notifyDataSetChanged() {
if (mAdapter != null) {
mAdapter.notifyDataSetChanged();
}
}
public boolean isAdjustMode() {
return mAdjustMode;
}
public void setAdjustMode(boolean is) {
mAdjustMode = is;
}
public CommonNavigatorAdapter getAdapter() {
return mAdapter;
}
public void setAdapter(CommonNavigatorAdapter adapter) {
if (mAdapter == adapter) {
return;
}
if (mAdapter != null) {
mAdapter.unregisterDataSetObserver(mObserver);
}
mAdapter = adapter;
if (mAdapter != null) {
mAdapter.registerDataSetObserver(mObserver);
mNavigatorHelper.setTotalCount(mAdapter.getCount());
if (mTitleContainer != null) { // adapter改变时应该重新init但是第一次设置adapter不用onAttachToMagicIndicator中有init
mAdapter.notifyDataSetChanged();
}
} else {
mNavigatorHelper.setTotalCount(0);
init();
}
}
private void init() {
removeAllViews();
View root;
if (mAdjustMode) {
root = LayoutInflater.from(getContext()).inflate(R.layout.pager_navigator_layout_no_scroll, this);
} else {
root = LayoutInflater.from(getContext()).inflate(R.layout.pager_navigator_layout, this);
}
mScrollView = (HorizontalScrollView) root.findViewById(R.id.scroll_view); // mAdjustMode为true时mScrollView为null
mTitleContainer = (LinearLayout) root.findViewById(R.id.title_container);
mTitleContainer.setPadding(mLeftPadding, 0, mRightPadding, 0);
mIndicatorContainer = (LinearLayout) root.findViewById(R.id.indicator_container);
if (mIndicatorOnTop) {
mIndicatorContainer.getParent().bringChildToFront(mIndicatorContainer);
}
initTitlesAndIndicator();
}
/**
* 初始化title和indicator
*/
private void initTitlesAndIndicator() {
for (int i = 0, j = mNavigatorHelper.getTotalCount(); i < j; i++) {
IPagerTitleView v = mAdapter.getTitleView(getContext(), i);
if (v instanceof View) {
View view = (View) v;
LinearLayout.LayoutParams lp;
if (mAdjustMode) {
lp = new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT);
lp.weight = mAdapter.getTitleWeight(getContext(), i);
} else {
lp = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
}
mTitleContainer.addView(view, lp);
}
}
if (mAdapter != null) {
mIndicator = mAdapter.getIndicator(getContext());
if (mIndicator instanceof View) {
LayoutParams lp = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
mIndicatorContainer.addView((View) mIndicator, lp);
}
}
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (mAdapter != null) {
preparePositionData();
if (mIndicator != null) {
mIndicator.onPositionDataProvide(mPositionDataList);
}
if (mReselectWhenLayout && mNavigatorHelper.getScrollState() == ScrollState.SCROLL_STATE_IDLE) {
onPageSelected(mNavigatorHelper.getCurrentIndex());
onPageScrolled(mNavigatorHelper.getCurrentIndex(), 0.0f, 0);
}
}
}
/**
* 获取title的位置信息为打造不同的指示器、各种效果提供可能
*/
private void preparePositionData() {
mPositionDataList.clear();
for (int i = 0, j = mNavigatorHelper.getTotalCount(); i < j; i++) {
PositionData data = new PositionData();
View v = mTitleContainer.getChildAt(i);
if (v != null) {
data.mLeft = v.getLeft();
data.mTop = v.getTop();
data.mRight = v.getRight();
data.mBottom = v.getBottom();
if (v instanceof IMeasurablePagerTitleView) {
IMeasurablePagerTitleView view = (IMeasurablePagerTitleView) v;
data.mContentLeft = view.getContentLeft();
data.mContentTop = view.getContentTop();
data.mContentRight = view.getContentRight();
data.mContentBottom = view.getContentBottom();
} else {
data.mContentLeft = data.mLeft;
data.mContentTop = data.mTop;
data.mContentRight = data.mRight;
data.mContentBottom = data.mBottom;
}
}
mPositionDataList.add(data);
}
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (mAdapter != null) {
mNavigatorHelper.onPageScrolled(position, positionOffset, positionOffsetPixels);
if (mIndicator != null) {
mIndicator.onPageScrolled(position, positionOffset, positionOffsetPixels);
}
// 手指跟随滚动
if (mScrollView != null && mPositionDataList.size() > 0 && position >= 0 && position < mPositionDataList.size()) {
if (mFollowTouch) {
int currentPosition = Math.min(mPositionDataList.size() - 1, position);
int nextPosition = Math.min(mPositionDataList.size() - 1, position + 1);
PositionData current = mPositionDataList.get(currentPosition);
PositionData next = mPositionDataList.get(nextPosition);
float scrollTo = current.horizontalCenter() - mScrollView.getWidth() * mScrollPivotX;
float nextScrollTo = next.horizontalCenter() - mScrollView.getWidth() * mScrollPivotX;
mScrollView.scrollTo((int) (scrollTo + (nextScrollTo - scrollTo) * positionOffset), 0);
} else if (!mEnablePivotScroll) {
// TODO 实现待选中项完全显示出来
}
}
}
}
public float getScrollPivotX() {
return mScrollPivotX;
}
public void setScrollPivotX(float scrollPivotX) {
mScrollPivotX = scrollPivotX;
}
@Override
public void onPageSelected(int position) {
if (mAdapter != null) {
mNavigatorHelper.onPageSelected(position);
if (mIndicator != null) {
mIndicator.onPageSelected(position);
}
}
}
@Override
public void onPageScrollStateChanged(int state) {
if (mAdapter != null) {
mNavigatorHelper.onPageScrollStateChanged(state);
if (mIndicator != null) {
mIndicator.onPageScrollStateChanged(state);
}
}
}
@Override
public void onAttachToMagicIndicator() {
init(); // 将初始化延迟到这里
}
@Override
public void onDetachFromMagicIndicator() {
}
public IPagerIndicator getPagerIndicator() {
return mIndicator;
}
public boolean isEnablePivotScroll() {
return mEnablePivotScroll;
}
public void setEnablePivotScroll(boolean is) {
mEnablePivotScroll = is;
}
@Override
public void onEnter(int index, int totalCount, float enterPercent, boolean leftToRight) {
if (mTitleContainer == null) {
return;
}
View v = mTitleContainer.getChildAt(index);
if (v instanceof IPagerTitleView) {
((IPagerTitleView) v).onEnter(index, totalCount, enterPercent, leftToRight);
}
}
@Override
public void onLeave(int index, int totalCount, float leavePercent, boolean leftToRight) {
if (mTitleContainer == null) {
return;
}
View v = mTitleContainer.getChildAt(index);
if (v instanceof IPagerTitleView) {
((IPagerTitleView) v).onLeave(index, totalCount, leavePercent, leftToRight);
}
}
public boolean isSmoothScroll() {
return mSmoothScroll;
}
public void setSmoothScroll(boolean smoothScroll) {
mSmoothScroll = smoothScroll;
}
public boolean isFollowTouch() {
return mFollowTouch;
}
public void setFollowTouch(boolean followTouch) {
mFollowTouch = followTouch;
}
public boolean isSkimOver() {
return mSkimOver;
}
public void setSkimOver(boolean skimOver) {
mSkimOver = skimOver;
mNavigatorHelper.setSkimOver(skimOver);
}
@Override
public void onSelected(int index, int totalCount) {
if (mTitleContainer == null) {
return;
}
View v = mTitleContainer.getChildAt(index);
if (v instanceof IPagerTitleView) {
((IPagerTitleView) v).onSelected(index, totalCount);
}
if (!mAdjustMode && !mFollowTouch && mScrollView != null && mPositionDataList.size() > 0) {
int currentIndex = Math.min(mPositionDataList.size() - 1, index);
PositionData current = mPositionDataList.get(currentIndex);
if (mEnablePivotScroll) {
float scrollTo = current.horizontalCenter() - mScrollView.getWidth() * mScrollPivotX;
if (mSmoothScroll) {
mScrollView.smoothScrollTo((int) (scrollTo), 0);
} else {
mScrollView.scrollTo((int) (scrollTo), 0);
}
} else {
// 如果当前项被部分遮挡,则滚动显示完全
if (mScrollView.getScrollX() > current.mLeft) {
if (mSmoothScroll) {
mScrollView.smoothScrollTo(current.mLeft, 0);
} else {
mScrollView.scrollTo(current.mLeft, 0);
}
} else if (mScrollView.getScrollX() + getWidth() < current.mRight) {
if (mSmoothScroll) {
mScrollView.smoothScrollTo(current.mRight - getWidth(), 0);
} else {
mScrollView.scrollTo(current.mRight - getWidth(), 0);
}
}
}
}
}
@Override
public void onDeselected(int index, int totalCount) {
if (mTitleContainer == null) {
return;
}
View v = mTitleContainer.getChildAt(index);
if (v instanceof IPagerTitleView) {
((IPagerTitleView) v).onDeselected(index, totalCount);
}
}
public IPagerTitleView getPagerTitleView(int index) {
if (mTitleContainer == null) {
return null;
}
return (IPagerTitleView) mTitleContainer.getChildAt(index);
}
public LinearLayout getTitleContainer() {
return mTitleContainer;
}
public int getRightPadding() {
return mRightPadding;
}
public void setRightPadding(int rightPadding) {
mRightPadding = rightPadding;
}
public int getLeftPadding() {
return mLeftPadding;
}
public void setLeftPadding(int leftPadding) {
mLeftPadding = leftPadding;
}
public boolean isIndicatorOnTop() {
return mIndicatorOnTop;
}
public void setIndicatorOnTop(boolean indicatorOnTop) {
mIndicatorOnTop = indicatorOnTop;
}
public boolean isReselectWhenLayout() {
return mReselectWhenLayout;
}
public void setReselectWhenLayout(boolean reselectWhenLayout) {
mReselectWhenLayout = reselectWhenLayout;
}
}

View File

@@ -0,0 +1,41 @@
package net.lucode.hackware.magicindicator.buildins.commonnavigator.abs;
import android.content.Context;
import android.database.DataSetObservable;
import android.database.DataSetObserver;
/**
* CommonNavigator适配器通过它可轻松切换不同的指示器样式
* 博客: http://hackware.lucode.net
* Created by hackware on 2016/6/26.
*/
public abstract class CommonNavigatorAdapter {
private final DataSetObservable mDataSetObservable = new DataSetObservable();
public abstract int getCount();
public abstract IPagerTitleView getTitleView(Context context, int index);
public abstract IPagerIndicator getIndicator(Context context);
public float getTitleWeight(Context context, int index) {
return 1;
}
public final void registerDataSetObserver(DataSetObserver observer) {
mDataSetObservable.registerObserver(observer);
}
public final void unregisterDataSetObserver(DataSetObserver observer) {
mDataSetObservable.unregisterObserver(observer);
}
public final void notifyDataSetChanged() {
mDataSetObservable.notifyChanged();
}
public final void notifyDataSetInvalidated() {
mDataSetObservable.notifyInvalidated();
}
}

View File

@@ -0,0 +1,16 @@
package net.lucode.hackware.magicindicator.buildins.commonnavigator.abs;
/**
* 可测量内容区域的指示器标题
* 博客: http://hackware.lucode.net
* Created by hackware on 2016/6/26.
*/
public interface IMeasurablePagerTitleView extends IPagerTitleView {
int getContentLeft();
int getContentTop();
int getContentRight();
int getContentBottom();
}

View File

@@ -0,0 +1,21 @@
package net.lucode.hackware.magicindicator.buildins.commonnavigator.abs;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.model.PositionData;
import java.util.List;
/**
* 抽象的viewpager指示器适用于CommonNavigator
* 博客: http://hackware.lucode.net
* Created by hackware on 2016/6/26.
*/
public interface IPagerIndicator {
void onPageScrolled(int position, float positionOffset, int positionOffsetPixels);
void onPageSelected(int position);
void onPageScrollStateChanged(int state);
void onPositionDataProvide(List<PositionData> dataList);
}

View File

@@ -0,0 +1,34 @@
package net.lucode.hackware.magicindicator.buildins.commonnavigator.abs;
/**
* 抽象的指示器标题适用于CommonNavigator
* 博客: http://hackware.lucode.net
* Created by hackware on 2016/6/26.
*/
public interface IPagerTitleView {
/**
* 被选中
*/
void onSelected(int index, int totalCount);
/**
* 未被选中
*/
void onDeselected(int index, int totalCount);
/**
* 离开
*
* @param leavePercent 离开的百分比, 0.0f - 1.0f
* @param leftToRight 从左至右离开
*/
void onLeave(int index, int totalCount, float leavePercent, boolean leftToRight);
/**
* 进入
*
* @param enterPercent 进入的百分比, 0.0f - 1.0f
* @param leftToRight 从左至右离开
*/
void onEnter(int index, int totalCount, float enterPercent, boolean leftToRight);
}

View File

@@ -0,0 +1,165 @@
package net.lucode.hackware.magicindicator.buildins.commonnavigator.indicators;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import net.lucode.hackware.magicindicator.FragmentContainerHelper;
import net.lucode.hackware.magicindicator.buildins.ArgbEvaluatorHolder;
import net.lucode.hackware.magicindicator.buildins.UIUtil;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.abs.IPagerIndicator;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.model.PositionData;
import java.util.Arrays;
import java.util.List;
/**
* 贝塞尔曲线ViewPager指示器带颜色渐变
* 博客: http://hackware.lucode.net
* Created by hackware on 2016/6/26.
*/
public class BezierPagerIndicator extends View implements IPagerIndicator {
private List<PositionData> mPositionDataList;
private float mLeftCircleRadius;
private float mLeftCircleX;
private float mRightCircleRadius;
private float mRightCircleX;
private float mYOffset;
private float mMaxCircleRadius;
private float mMinCircleRadius;
private Paint mPaint;
private Path mPath = new Path();
private List<Integer> mColors;
private Interpolator mStartInterpolator = new AccelerateInterpolator();
private Interpolator mEndInterpolator = new DecelerateInterpolator();
public BezierPagerIndicator(Context context) {
super(context);
init(context);
}
private void init(Context context) {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Paint.Style.FILL);
mMaxCircleRadius = UIUtil.dip2px(context, 3.5);
mMinCircleRadius = UIUtil.dip2px(context, 2);
mYOffset = UIUtil.dip2px(context, 1.5);
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawCircle(mLeftCircleX, getHeight() - mYOffset - mMaxCircleRadius, mLeftCircleRadius, mPaint);
canvas.drawCircle(mRightCircleX, getHeight() - mYOffset - mMaxCircleRadius, mRightCircleRadius, mPaint);
drawBezierCurve(canvas);
}
/**
* 绘制贝塞尔曲线
*
* @param canvas
*/
private void drawBezierCurve(Canvas canvas) {
mPath.reset();
float y = getHeight() - mYOffset - mMaxCircleRadius;
mPath.moveTo(mRightCircleX, y);
mPath.lineTo(mRightCircleX, y - mRightCircleRadius);
mPath.quadTo(mRightCircleX + (mLeftCircleX - mRightCircleX) / 2.0f, y, mLeftCircleX, y - mLeftCircleRadius);
mPath.lineTo(mLeftCircleX, y + mLeftCircleRadius);
mPath.quadTo(mRightCircleX + (mLeftCircleX - mRightCircleX) / 2.0f, y, mRightCircleX, y + mRightCircleRadius);
mPath.close(); // 闭合
canvas.drawPath(mPath, mPaint);
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (mPositionDataList == null || mPositionDataList.isEmpty()) {
return;
}
// 计算颜色
if (mColors != null && mColors.size() > 0) {
int currentColor = mColors.get(Math.abs(position) % mColors.size());
int nextColor = mColors.get(Math.abs(position + 1) % mColors.size());
int color = ArgbEvaluatorHolder.eval(positionOffset, currentColor, nextColor);
mPaint.setColor(color);
}
// 计算锚点位置
PositionData current = FragmentContainerHelper.getImitativePositionData(mPositionDataList, position);
PositionData next = FragmentContainerHelper.getImitativePositionData(mPositionDataList, position + 1);
float leftX = current.mLeft + (current.mRight - current.mLeft) / 2;
float rightX = next.mLeft + (next.mRight - next.mLeft) / 2;
mLeftCircleX = leftX + (rightX - leftX) * mStartInterpolator.getInterpolation(positionOffset);
mRightCircleX = leftX + (rightX - leftX) * mEndInterpolator.getInterpolation(positionOffset);
mLeftCircleRadius = mMaxCircleRadius + (mMinCircleRadius - mMaxCircleRadius) * mEndInterpolator.getInterpolation(positionOffset);
mRightCircleRadius = mMinCircleRadius + (mMaxCircleRadius - mMinCircleRadius) * mStartInterpolator.getInterpolation(positionOffset);
invalidate();
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
@Override
public void onPositionDataProvide(List<PositionData> dataList) {
mPositionDataList = dataList;
}
public float getMaxCircleRadius() {
return mMaxCircleRadius;
}
public void setMaxCircleRadius(float maxCircleRadius) {
mMaxCircleRadius = maxCircleRadius;
}
public float getMinCircleRadius() {
return mMinCircleRadius;
}
public void setMinCircleRadius(float minCircleRadius) {
mMinCircleRadius = minCircleRadius;
}
public float getYOffset() {
return mYOffset;
}
public void setYOffset(float yOffset) {
mYOffset = yOffset;
}
public void setColors(Integer... colors) {
mColors = Arrays.asList(colors);
}
public void setStartInterpolator(Interpolator startInterpolator) {
mStartInterpolator = startInterpolator;
if (mStartInterpolator == null) {
mStartInterpolator = new AccelerateInterpolator();
}
}
public void setEndInterpolator(Interpolator endInterpolator) {
mEndInterpolator = endInterpolator;
if (mEndInterpolator == null) {
mEndInterpolator = new DecelerateInterpolator();
}
}
}

View File

@@ -0,0 +1,210 @@
package net.lucode.hackware.magicindicator.buildins.commonnavigator.indicators;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.view.View;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import net.lucode.hackware.magicindicator.FragmentContainerHelper;
import net.lucode.hackware.magicindicator.buildins.ArgbEvaluatorHolder;
import net.lucode.hackware.magicindicator.buildins.UIUtil;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.abs.IPagerIndicator;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.model.PositionData;
import java.util.Arrays;
import java.util.List;
/**
* 直线viewpager指示器带颜色渐变
* 博客: http://hackware.lucode.net
* Created by hackware on 2016/6/26.
*/
public class LinePagerIndicator extends View implements IPagerIndicator {
public static final int MODE_MATCH_EDGE = 0; // 直线宽度 == title宽度 - 2 * mXOffset
public static final int MODE_WRAP_CONTENT = 1; // 直线宽度 == title内容宽度 - 2 * mXOffset
public static final int MODE_EXACTLY = 2; // 直线宽度 == mLineWidth
private int mMode; // 默认为MODE_MATCH_EDGE模式
// 控制动画
private Interpolator mStartInterpolator = new LinearInterpolator();
private Interpolator mEndInterpolator = new LinearInterpolator();
private float mYOffset; // 相对于底部的偏移量如果你想让直线位于title上方设置它即可
private float mLineHeight;
private float mXOffset;
private float mLineWidth;
private float mRoundRadius;
private Paint mPaint;
private List<PositionData> mPositionDataList;
private List<Integer> mColors;
private RectF mLineRect = new RectF();
public LinePagerIndicator(Context context) {
super(context);
init(context);
}
private void init(Context context) {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Paint.Style.FILL);
mLineHeight = UIUtil.dip2px(context, 3);
mLineWidth = UIUtil.dip2px(context, 10);
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawRoundRect(mLineRect, mRoundRadius, mRoundRadius, mPaint);
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (mPositionDataList == null || mPositionDataList.isEmpty()) {
return;
}
// 计算颜色
if (mColors != null && mColors.size() > 0) {
int currentColor = mColors.get(Math.abs(position) % mColors.size());
int nextColor = mColors.get(Math.abs(position + 1) % mColors.size());
int color = ArgbEvaluatorHolder.eval(positionOffset, currentColor, nextColor);
mPaint.setColor(color);
}
// 计算锚点位置
PositionData current = FragmentContainerHelper.getImitativePositionData(mPositionDataList, position);
PositionData next = FragmentContainerHelper.getImitativePositionData(mPositionDataList, position + 1);
float leftX;
float nextLeftX;
float rightX;
float nextRightX;
if (mMode == MODE_MATCH_EDGE) {
leftX = current.mLeft + mXOffset;
nextLeftX = next.mLeft + mXOffset;
rightX = current.mRight - mXOffset;
nextRightX = next.mRight - mXOffset;
} else if (mMode == MODE_WRAP_CONTENT) {
leftX = current.mContentLeft + mXOffset;
nextLeftX = next.mContentLeft + mXOffset;
rightX = current.mContentRight - mXOffset;
nextRightX = next.mContentRight - mXOffset;
} else { // MODE_EXACTLY
leftX = current.mLeft + (current.width() - mLineWidth) / 2;
nextLeftX = next.mLeft + (next.width() - mLineWidth) / 2;
rightX = current.mLeft + (current.width() + mLineWidth) / 2;
nextRightX = next.mLeft + (next.width() + mLineWidth) / 2;
}
mLineRect.left = leftX + (nextLeftX - leftX) * mStartInterpolator.getInterpolation(positionOffset);
mLineRect.right = rightX + (nextRightX - rightX) * mEndInterpolator.getInterpolation(positionOffset);
mLineRect.top = getHeight() - mLineHeight - mYOffset;
mLineRect.bottom = getHeight() - mYOffset;
invalidate();
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
@Override
public void onPositionDataProvide(List<PositionData> dataList) {
mPositionDataList = dataList;
}
public float getYOffset() {
return mYOffset;
}
public void setYOffset(float yOffset) {
mYOffset = yOffset;
}
public float getXOffset() {
return mXOffset;
}
public void setXOffset(float xOffset) {
mXOffset = xOffset;
}
public float getLineHeight() {
return mLineHeight;
}
public void setLineHeight(float lineHeight) {
mLineHeight = lineHeight;
}
public float getLineWidth() {
return mLineWidth;
}
public void setLineWidth(float lineWidth) {
mLineWidth = lineWidth;
}
public float getRoundRadius() {
return mRoundRadius;
}
public void setRoundRadius(float roundRadius) {
mRoundRadius = roundRadius;
}
public int getMode() {
return mMode;
}
public void setMode(int mode) {
if (mode == MODE_EXACTLY || mode == MODE_MATCH_EDGE || mode == MODE_WRAP_CONTENT) {
mMode = mode;
} else {
throw new IllegalArgumentException("mode " + mode + " not supported.");
}
}
public Paint getPaint() {
return mPaint;
}
public List<Integer> getColors() {
return mColors;
}
public void setColors(Integer... colors) {
mColors = Arrays.asList(colors);
}
public Interpolator getStartInterpolator() {
return mStartInterpolator;
}
public void setStartInterpolator(Interpolator startInterpolator) {
mStartInterpolator = startInterpolator;
if (mStartInterpolator == null) {
mStartInterpolator = new LinearInterpolator();
}
}
public Interpolator getEndInterpolator() {
return mEndInterpolator;
}
public void setEndInterpolator(Interpolator endInterpolator) {
mEndInterpolator = endInterpolator;
if (mEndInterpolator == null) {
mEndInterpolator = new LinearInterpolator();
}
}
}

View File

@@ -0,0 +1,102 @@
package net.lucode.hackware.magicindicator.buildins.commonnavigator.indicators;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.view.View;
import net.lucode.hackware.magicindicator.FragmentContainerHelper;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.abs.IPagerIndicator;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.model.PositionData;
import java.util.List;
/**
* 用于测试的指示器可用来检测自定义的IMeasurablePagerTitleView是否正确测量内容区域
* 博客: http://hackware.lucode.net
* Created by hackware on 2016/6/26.
*/
public class TestPagerIndicator extends View implements IPagerIndicator {
private Paint mPaint;
private int mOutRectColor;
private int mInnerRectColor;
private RectF mOutRect = new RectF();
private RectF mInnerRect = new RectF();
private List<PositionData> mPositionDataList;
public TestPagerIndicator(Context context) {
super(context);
init(context);
}
private void init(Context context) {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Paint.Style.STROKE);
mOutRectColor = Color.RED;
mInnerRectColor = Color.GREEN;
}
@Override
protected void onDraw(Canvas canvas) {
mPaint.setColor(mOutRectColor);
canvas.drawRect(mOutRect, mPaint);
mPaint.setColor(mInnerRectColor);
canvas.drawRect(mInnerRect, mPaint);
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (mPositionDataList == null || mPositionDataList.isEmpty()) {
return;
}
// 计算锚点位置
PositionData current = FragmentContainerHelper.getImitativePositionData(mPositionDataList, position);
PositionData next = FragmentContainerHelper.getImitativePositionData(mPositionDataList, position + 1);
mOutRect.left = current.mLeft + (next.mLeft - current.mLeft) * positionOffset;
mOutRect.top = current.mTop + (next.mTop - current.mTop) * positionOffset;
mOutRect.right = current.mRight + (next.mRight - current.mRight) * positionOffset;
mOutRect.bottom = current.mBottom + (next.mBottom - current.mBottom) * positionOffset;
mInnerRect.left = current.mContentLeft + (next.mContentLeft - current.mContentLeft) * positionOffset;
mInnerRect.top = current.mContentTop + (next.mContentTop - current.mContentTop) * positionOffset;
mInnerRect.right = current.mContentRight + (next.mContentRight - current.mContentRight) * positionOffset;
mInnerRect.bottom = current.mContentBottom + (next.mContentBottom - current.mContentBottom) * positionOffset;
invalidate();
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
@Override
public void onPositionDataProvide(List<PositionData> dataList) {
mPositionDataList = dataList;
}
public int getOutRectColor() {
return mOutRectColor;
}
public void setOutRectColor(int outRectColor) {
mOutRectColor = outRectColor;
}
public int getInnerRectColor() {
return mInnerRectColor;
}
public void setInnerRectColor(int innerRectColor) {
mInnerRectColor = innerRectColor;
}
}

View File

@@ -0,0 +1,161 @@
package net.lucode.hackware.magicindicator.buildins.commonnavigator.indicators;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.view.View;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import net.lucode.hackware.magicindicator.FragmentContainerHelper;
import net.lucode.hackware.magicindicator.buildins.UIUtil;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.abs.IPagerIndicator;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.model.PositionData;
import java.util.List;
/**
* 带有小尖角的直线指示器
* 博客: http://hackware.lucode.net
* Created by hackware on 2016/6/26.
*/
public class TriangularPagerIndicator extends View implements IPagerIndicator {
private List<PositionData> mPositionDataList;
private Paint mPaint;
private int mLineHeight;
private int mLineColor;
private int mTriangleHeight;
private int mTriangleWidth;
private boolean mReverse;
private float mYOffset;
private Path mPath = new Path();
private Interpolator mStartInterpolator = new LinearInterpolator();
private float mAnchorX;
public TriangularPagerIndicator(Context context) {
super(context);
init(context);
}
private void init(Context context) {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Paint.Style.FILL);
mLineHeight = UIUtil.dip2px(context, 3);
mTriangleWidth = UIUtil.dip2px(context, 14);
mTriangleHeight = UIUtil.dip2px(context, 8);
}
@Override
protected void onDraw(Canvas canvas) {
mPaint.setColor(mLineColor);
if (mReverse) {
canvas.drawRect(0, getHeight() - mYOffset - mTriangleHeight, getWidth(), getHeight() - mYOffset - mTriangleHeight + mLineHeight, mPaint);
} else {
canvas.drawRect(0, getHeight() - mLineHeight - mYOffset, getWidth(), getHeight() - mYOffset, mPaint);
}
mPath.reset();
if (mReverse) {
mPath.moveTo(mAnchorX - mTriangleWidth / 2, getHeight() - mYOffset - mTriangleHeight);
mPath.lineTo(mAnchorX, getHeight() - mYOffset);
mPath.lineTo(mAnchorX + mTriangleWidth / 2, getHeight() - mYOffset - mTriangleHeight);
} else {
mPath.moveTo(mAnchorX - mTriangleWidth / 2, getHeight() - mYOffset);
mPath.lineTo(mAnchorX, getHeight() - mTriangleHeight - mYOffset);
mPath.lineTo(mAnchorX + mTriangleWidth / 2, getHeight() - mYOffset);
}
mPath.close();
canvas.drawPath(mPath, mPaint);
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (mPositionDataList == null || mPositionDataList.isEmpty()) {
return;
}
// 计算锚点位置
PositionData current = FragmentContainerHelper.getImitativePositionData(mPositionDataList, position);
PositionData next = FragmentContainerHelper.getImitativePositionData(mPositionDataList, position + 1);
float leftX = current.mLeft + (current.mRight - current.mLeft) / 2;
float rightX = next.mLeft + (next.mRight - next.mLeft) / 2;
mAnchorX = leftX + (rightX - leftX) * mStartInterpolator.getInterpolation(positionOffset);
invalidate();
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
@Override
public void onPositionDataProvide(List<PositionData> dataList) {
mPositionDataList = dataList;
}
public int getLineHeight() {
return mLineHeight;
}
public void setLineHeight(int lineHeight) {
mLineHeight = lineHeight;
}
public int getLineColor() {
return mLineColor;
}
public void setLineColor(int lineColor) {
mLineColor = lineColor;
}
public int getTriangleHeight() {
return mTriangleHeight;
}
public void setTriangleHeight(int triangleHeight) {
mTriangleHeight = triangleHeight;
}
public int getTriangleWidth() {
return mTriangleWidth;
}
public void setTriangleWidth(int triangleWidth) {
mTriangleWidth = triangleWidth;
}
public Interpolator getStartInterpolator() {
return mStartInterpolator;
}
public void setStartInterpolator(Interpolator startInterpolator) {
mStartInterpolator = startInterpolator;
if (mStartInterpolator == null) {
mStartInterpolator = new LinearInterpolator();
}
}
public boolean isReverse() {
return mReverse;
}
public void setReverse(boolean reverse) {
mReverse = reverse;
}
public float getYOffset() {
return mYOffset;
}
public void setYOffset(float yOffset) {
mYOffset = yOffset;
}
}

View File

@@ -0,0 +1,149 @@
package net.lucode.hackware.magicindicator.buildins.commonnavigator.indicators;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.view.View;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import net.lucode.hackware.magicindicator.FragmentContainerHelper;
import net.lucode.hackware.magicindicator.buildins.UIUtil;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.abs.IPagerIndicator;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.model.PositionData;
import java.util.List;
/**
* 包裹住内容区域的指示器类似天天快报的切换效果需要和IMeasurablePagerTitleView配合使用
* 博客: http://hackware.lucode.net
* Created by hackware on 2016/6/26.
*/
public class WrapPagerIndicator extends View implements IPagerIndicator {
private int mVerticalPadding;
private int mHorizontalPadding;
private int mFillColor;
private float mRoundRadius;
private Interpolator mStartInterpolator = new LinearInterpolator();
private Interpolator mEndInterpolator = new LinearInterpolator();
private List<PositionData> mPositionDataList;
private Paint mPaint;
private RectF mRect = new RectF();
private boolean mRoundRadiusSet;
public WrapPagerIndicator(Context context) {
super(context);
init(context);
}
private void init(Context context) {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Paint.Style.FILL);
mVerticalPadding = UIUtil.dip2px(context, 6);
mHorizontalPadding = UIUtil.dip2px(context, 10);
}
@Override
protected void onDraw(Canvas canvas) {
mPaint.setColor(mFillColor);
canvas.drawRoundRect(mRect, mRoundRadius, mRoundRadius, mPaint);
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (mPositionDataList == null || mPositionDataList.isEmpty()) {
return;
}
// 计算锚点位置
PositionData current = FragmentContainerHelper.getImitativePositionData(mPositionDataList, position);
PositionData next = FragmentContainerHelper.getImitativePositionData(mPositionDataList, position + 1);
mRect.left = current.mContentLeft - mHorizontalPadding + (next.mContentLeft - current.mContentLeft) * mEndInterpolator.getInterpolation(positionOffset);
mRect.top = current.mContentTop - mVerticalPadding;
mRect.right = current.mContentRight + mHorizontalPadding + (next.mContentRight - current.mContentRight) * mStartInterpolator.getInterpolation(positionOffset);
mRect.bottom = current.mContentBottom + mVerticalPadding;
if (!mRoundRadiusSet) {
mRoundRadius = mRect.height() / 2;
}
invalidate();
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
@Override
public void onPositionDataProvide(List<PositionData> dataList) {
mPositionDataList = dataList;
}
public Paint getPaint() {
return mPaint;
}
public int getVerticalPadding() {
return mVerticalPadding;
}
public void setVerticalPadding(int verticalPadding) {
mVerticalPadding = verticalPadding;
}
public int getHorizontalPadding() {
return mHorizontalPadding;
}
public void setHorizontalPadding(int horizontalPadding) {
mHorizontalPadding = horizontalPadding;
}
public int getFillColor() {
return mFillColor;
}
public void setFillColor(int fillColor) {
mFillColor = fillColor;
}
public float getRoundRadius() {
return mRoundRadius;
}
public void setRoundRadius(float roundRadius) {
mRoundRadius = roundRadius;
mRoundRadiusSet = true;
}
public Interpolator getStartInterpolator() {
return mStartInterpolator;
}
public void setStartInterpolator(Interpolator startInterpolator) {
mStartInterpolator = startInterpolator;
if (mStartInterpolator == null) {
mStartInterpolator = new LinearInterpolator();
}
}
public Interpolator getEndInterpolator() {
return mEndInterpolator;
}
public void setEndInterpolator(Interpolator endInterpolator) {
mEndInterpolator = endInterpolator;
if (mEndInterpolator == null) {
mEndInterpolator = new LinearInterpolator();
}
}
}

View File

@@ -0,0 +1,41 @@
package net.lucode.hackware.magicindicator.buildins.commonnavigator.model;
/**
* 保存指示器标题的坐标
* 博客: http://hackware.lucode.net
* Created by hackware on 2016/6/26.
*/
public class PositionData {
public int mLeft;
public int mTop;
public int mRight;
public int mBottom;
public int mContentLeft;
public int mContentTop;
public int mContentRight;
public int mContentBottom;
public int width() {
return mRight - mLeft;
}
public int height() {
return mBottom - mTop;
}
public int contentWidth() {
return mContentRight - mContentLeft;
}
public int contentHeight() {
return mContentBottom - mContentTop;
}
public int horizontalCenter() {
return mLeft + width() / 2;
}
public int verticalCenter() {
return mTop + height() / 2;
}
}

View File

@@ -0,0 +1,191 @@
package net.lucode.hackware.magicindicator.buildins.commonnavigator.titles;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.view.View;
import net.lucode.hackware.magicindicator.buildins.UIUtil;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.abs.IMeasurablePagerTitleView;
/**
* 类似今日头条切换效果的指示器标题
* 博客: http://hackware.lucode.net
* Created by hackware on 2016/6/26.
*/
public class ClipPagerTitleView extends View implements IMeasurablePagerTitleView {
private String mText;
private int mTextColor;
private int mClipColor;
private boolean mLeftToRight;
private float mClipPercent;
private Paint mPaint;
private Rect mTextBounds = new Rect();
public ClipPagerTitleView(Context context) {
super(context);
init(context);
}
private void init(Context context) {
int textSize = UIUtil.dip2px(context, 16);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setTextSize(textSize);
int padding = UIUtil.dip2px(context, 10);
setPadding(padding, 0, padding, 0);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
measureTextBounds();
setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
}
private int measureWidth(int widthMeasureSpec) {
int mode = MeasureSpec.getMode(widthMeasureSpec);
int size = MeasureSpec.getSize(widthMeasureSpec);
int result = size;
switch (mode) {
case MeasureSpec.AT_MOST:
int width = mTextBounds.width() + getPaddingLeft() + getPaddingRight();
result = Math.min(width, size);
break;
case MeasureSpec.UNSPECIFIED:
result = mTextBounds.width() + getPaddingLeft() + getPaddingRight();
break;
default:
break;
}
return result;
}
private int measureHeight(int heightMeasureSpec) {
int mode = MeasureSpec.getMode(heightMeasureSpec);
int size = MeasureSpec.getSize(heightMeasureSpec);
int result = size;
switch (mode) {
case MeasureSpec.AT_MOST:
int height = mTextBounds.height() + getPaddingTop() + getPaddingBottom();
result = Math.min(height, size);
break;
case MeasureSpec.UNSPECIFIED:
result = mTextBounds.height() + getPaddingTop() + getPaddingBottom();
break;
default:
break;
}
return result;
}
@Override
protected void onDraw(Canvas canvas) {
int x = (getWidth() - mTextBounds.width()) / 2;
Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
int y = (int) ((getHeight() - fontMetrics.bottom - fontMetrics.top) / 2);
// 画底层
mPaint.setColor(mTextColor);
canvas.drawText(mText, x, y, mPaint);
// 画clip层
canvas.save();
if (mLeftToRight) {
canvas.clipRect(0, 0, getWidth() * mClipPercent, getHeight());
} else {
canvas.clipRect(getWidth() * (1 - mClipPercent), 0, getWidth(), getHeight());
}
mPaint.setColor(mClipColor);
canvas.drawText(mText, x, y, mPaint);
canvas.restore();
}
@Override
public void onSelected(int index, int totalCount) {
}
@Override
public void onDeselected(int index, int totalCount) {
}
@Override
public void onLeave(int index, int totalCount, float leavePercent, boolean leftToRight) {
mLeftToRight = !leftToRight;
mClipPercent = 1.0f - leavePercent;
invalidate();
}
@Override
public void onEnter(int index, int totalCount, float enterPercent, boolean leftToRight) {
mLeftToRight = leftToRight;
mClipPercent = enterPercent;
invalidate();
}
private void measureTextBounds() {
mPaint.getTextBounds(mText, 0, mText == null ? 0 : mText.length(), mTextBounds);
}
public String getText() {
return mText;
}
public void setText(String text) {
mText = text;
requestLayout();
}
public float getTextSize() {
return mPaint.getTextSize();
}
public void setTextSize(float textSize) {
mPaint.setTextSize(textSize);
requestLayout();
}
public int getTextColor() {
return mTextColor;
}
public void setTextColor(int textColor) {
mTextColor = textColor;
invalidate();
}
public int getClipColor() {
return mClipColor;
}
public void setClipColor(int clipColor) {
mClipColor = clipColor;
invalidate();
}
@Override
public int getContentLeft() {
int contentWidth = mTextBounds.width();
return getLeft() + getWidth() / 2 - contentWidth / 2;
}
@Override
public int getContentTop() {
Paint.FontMetrics metrics = mPaint.getFontMetrics();
float contentHeight = metrics.bottom - metrics.top;
return (int) (getHeight() / 2 - contentHeight / 2);
}
@Override
public int getContentRight() {
int contentWidth = mTextBounds.width();
return getLeft() + getWidth() / 2 + contentWidth / 2;
}
@Override
public int getContentBottom() {
Paint.FontMetrics metrics = mPaint.getFontMetrics();
float contentHeight = metrics.bottom - metrics.top;
return (int) (getHeight() / 2 + contentHeight / 2);
}
}

View File

@@ -0,0 +1,38 @@
package net.lucode.hackware.magicindicator.buildins.commonnavigator.titles;
import android.content.Context;
import net.lucode.hackware.magicindicator.buildins.ArgbEvaluatorHolder;
/**
* 两种颜色过渡的指示器标题
* 博客: http://hackware.lucode.net
* Created by hackware on 2016/6/26.
*/
public class ColorTransitionPagerTitleView extends SimplePagerTitleView {
public ColorTransitionPagerTitleView(Context context) {
super(context);
}
@Override
public void onLeave(int index, int totalCount, float leavePercent, boolean leftToRight) {
int color = ArgbEvaluatorHolder.eval(leavePercent, mSelectedColor, mNormalColor);
setTextColor(color);
}
@Override
public void onEnter(int index, int totalCount, float enterPercent, boolean leftToRight) {
int color = ArgbEvaluatorHolder.eval(enterPercent, mNormalColor, mSelectedColor);
setTextColor(color);
}
@Override
public void onSelected(int index, int totalCount) {
}
@Override
public void onDeselected(int index, int totalCount) {
}
}

View File

@@ -0,0 +1,143 @@
package net.lucode.hackware.magicindicator.buildins.commonnavigator.titles;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.abs.IMeasurablePagerTitleView;
/**
* 通用的指示器标题,子元素内容由外部提供,事件回传给外部
* 博客: http://hackware.lucode.net
* Created by hackware on 2016/7/3.
*/
public class CommonPagerTitleView extends FrameLayout implements IMeasurablePagerTitleView {
private OnPagerTitleChangeListener mOnPagerTitleChangeListener;
private ContentPositionDataProvider mContentPositionDataProvider;
public CommonPagerTitleView(Context context) {
super(context);
}
@Override
public void onSelected(int index, int totalCount) {
if (mOnPagerTitleChangeListener != null) {
mOnPagerTitleChangeListener.onSelected(index, totalCount);
}
}
@Override
public void onDeselected(int index, int totalCount) {
if (mOnPagerTitleChangeListener != null) {
mOnPagerTitleChangeListener.onDeselected(index, totalCount);
}
}
@Override
public void onLeave(int index, int totalCount, float leavePercent, boolean leftToRight) {
if (mOnPagerTitleChangeListener != null) {
mOnPagerTitleChangeListener.onLeave(index, totalCount, leavePercent, leftToRight);
}
}
@Override
public void onEnter(int index, int totalCount, float enterPercent, boolean leftToRight) {
if (mOnPagerTitleChangeListener != null) {
mOnPagerTitleChangeListener.onEnter(index, totalCount, enterPercent, leftToRight);
}
}
@Override
public int getContentLeft() {
if (mContentPositionDataProvider != null) {
return mContentPositionDataProvider.getContentLeft();
}
return getLeft();
}
@Override
public int getContentTop() {
if (mContentPositionDataProvider != null) {
return mContentPositionDataProvider.getContentTop();
}
return getTop();
}
@Override
public int getContentRight() {
if (mContentPositionDataProvider != null) {
return mContentPositionDataProvider.getContentRight();
}
return getRight();
}
@Override
public int getContentBottom() {
if (mContentPositionDataProvider != null) {
return mContentPositionDataProvider.getContentBottom();
}
return getBottom();
}
/**
* 外部直接将布局设置进来
*
* @param contentView
*/
public void setContentView(View contentView) {
setContentView(contentView, null);
}
public void setContentView(View contentView, FrameLayout.LayoutParams lp) {
removeAllViews();
if (contentView != null) {
if (lp == null) {
lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
}
addView(contentView, lp);
}
}
public void setContentView(int layoutId) {
View child = LayoutInflater.from(getContext()).inflate(layoutId, null);
setContentView(child, null);
}
public OnPagerTitleChangeListener getOnPagerTitleChangeListener() {
return mOnPagerTitleChangeListener;
}
public void setOnPagerTitleChangeListener(OnPagerTitleChangeListener onPagerTitleChangeListener) {
mOnPagerTitleChangeListener = onPagerTitleChangeListener;
}
public ContentPositionDataProvider getContentPositionDataProvider() {
return mContentPositionDataProvider;
}
public void setContentPositionDataProvider(ContentPositionDataProvider contentPositionDataProvider) {
mContentPositionDataProvider = contentPositionDataProvider;
}
public interface OnPagerTitleChangeListener {
void onSelected(int index, int totalCount);
void onDeselected(int index, int totalCount);
void onLeave(int index, int totalCount, float leavePercent, boolean leftToRight);
void onEnter(int index, int totalCount, float enterPercent, boolean leftToRight);
}
public interface ContentPositionDataProvider {
int getContentLeft();
int getContentTop();
int getContentRight();
int getContentBottom();
}
}

View File

@@ -0,0 +1,34 @@
package net.lucode.hackware.magicindicator.buildins.commonnavigator.titles;
import android.content.Context;
import android.view.View;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.abs.IPagerTitleView;
/**
* 空指示器标题用于只需要指示器而不需要title的需求
* 博客: http://hackware.lucode.net
* Created by hackware on 2016/6/26.
*/
public class DummyPagerTitleView extends View implements IPagerTitleView {
public DummyPagerTitleView(Context context) {
super(context);
}
@Override
public void onSelected(int index, int totalCount) {
}
@Override
public void onDeselected(int index, int totalCount) {
}
@Override
public void onLeave(int index, int totalCount, float leavePercent, boolean leftToRight) {
}
@Override
public void onEnter(int index, int totalCount, float enterPercent, boolean leftToRight) {
}
}

View File

@@ -0,0 +1,118 @@
package net.lucode.hackware.magicindicator.buildins.commonnavigator.titles;
import android.content.Context;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.text.TextUtils;
import android.view.Gravity;
import android.widget.TextView;
import net.lucode.hackware.magicindicator.buildins.UIUtil;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.abs.IMeasurablePagerTitleView;
/**
* 带文本的指示器标题
* 博客: http://hackware.lucode.net
* Created by hackware on 2016/6/26.
*/
public class SimplePagerTitleView extends TextView implements IMeasurablePagerTitleView {
protected int mSelectedColor;
protected int mNormalColor;
public SimplePagerTitleView(Context context) {
super(context, null);
init(context);
}
private void init(Context context) {
setGravity(Gravity.CENTER);
int padding = UIUtil.dip2px(context, 5);
setPadding(padding, 0, padding, 0);
setSingleLine();
setEllipsize(TextUtils.TruncateAt.END);
}
@Override
public void onSelected(int index, int totalCount) {
setTextColor(mSelectedColor);
}
@Override
public void onDeselected(int index, int totalCount) {
setTextColor(mNormalColor);
}
@Override
public void onLeave(int index, int totalCount, float leavePercent, boolean leftToRight) {
}
@Override
public void onEnter(int index, int totalCount, float enterPercent, boolean leftToRight) {
}
@Override
public int getContentLeft() {
Rect bound = new Rect();
String longestString = "";
if (getText().toString().contains("\n")) {
String[] brokenStrings = getText().toString().split("\\n");
for (String each : brokenStrings) {
if (each.length() > longestString.length()) longestString = each;
}
} else {
longestString = getText().toString();
}
getPaint().getTextBounds(longestString, 0, longestString.length(), bound);
int contentWidth = bound.width();
return getLeft() + getWidth() / 2 - contentWidth / 2;
}
@Override
public int getContentTop() {
Paint.FontMetrics metrics = getPaint().getFontMetrics();
float contentHeight = metrics.bottom - metrics.top;
return (int) (getHeight() / 2 - contentHeight / 2);
}
@Override
public int getContentRight() {
Rect bound = new Rect();
String longestString = "";
if (getText().toString().contains("\n")) {
String[] brokenStrings = getText().toString().split("\\n");
for (String each : brokenStrings) {
if (each.length() > longestString.length()) longestString = each;
}
} else {
longestString = getText().toString();
}
getPaint().getTextBounds(longestString, 0, longestString.length(), bound);
int contentWidth = bound.width();
return getLeft() + getWidth() / 2 + contentWidth / 2;
}
@Override
public int getContentBottom() {
Paint.FontMetrics metrics = getPaint().getFontMetrics();
float contentHeight = metrics.bottom - metrics.top;
return (int) (getHeight() / 2 + contentHeight / 2);
}
public int getSelectedColor() {
return mSelectedColor;
}
public void setSelectedColor(int selectedColor) {
mSelectedColor = selectedColor;
}
public int getNormalColor() {
return mNormalColor;
}
public void setNormalColor(int normalColor) {
mNormalColor = normalColor;
}
}

View File

@@ -0,0 +1,22 @@
package net.lucode.hackware.magicindicator.buildins.commonnavigator.titles.badge;
/**
* 角标的锚点
* Created by hackware on 2016/7/19.
*/
public enum BadgeAnchor {
LEFT,
TOP,
RIGHT,
BOTTOM,
CONTENT_LEFT,
CONTENT_TOP,
CONTENT_RIGHT,
CONTENT_BOTTOM,
CENTER_X,
CENTER_Y,
LEFT_EDGE_CENTER_X,
TOP_EDGE_CENTER_Y,
RIGHT_EDGE_CENTER_X,
BOTTOM_EDGE_CENTER_Y
}

View File

@@ -0,0 +1,221 @@
package net.lucode.hackware.magicindicator.buildins.commonnavigator.titles.badge;
import android.content.Context;
import android.view.View;
import android.widget.FrameLayout;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.abs.IMeasurablePagerTitleView;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.abs.IPagerTitleView;
/**
* 支持显示角标的title角标布局可自定义
* 博客: http://hackware.lucode.net
* Created by hackware on 2016/7/18.
*/
public class BadgePagerTitleView extends FrameLayout implements IMeasurablePagerTitleView {
private IPagerTitleView mInnerPagerTitleView;
private View mBadgeView;
private boolean mAutoCancelBadge = true;
private BadgeRule mXBadgeRule;
private BadgeRule mYBadgeRule;
public BadgePagerTitleView(Context context) {
super(context);
}
@Override
public void onSelected(int index, int totalCount) {
if (mInnerPagerTitleView != null) {
mInnerPagerTitleView.onSelected(index, totalCount);
}
if (mAutoCancelBadge) {
setBadgeView(null);
}
}
@Override
public void onDeselected(int index, int totalCount) {
if (mInnerPagerTitleView != null) {
mInnerPagerTitleView.onDeselected(index, totalCount);
}
}
@Override
public void onLeave(int index, int totalCount, float leavePercent, boolean leftToRight) {
if (mInnerPagerTitleView != null) {
mInnerPagerTitleView.onLeave(index, totalCount, leavePercent, leftToRight);
}
}
@Override
public void onEnter(int index, int totalCount, float enterPercent, boolean leftToRight) {
if (mInnerPagerTitleView != null) {
mInnerPagerTitleView.onEnter(index, totalCount, enterPercent, leftToRight);
}
}
public IPagerTitleView getInnerPagerTitleView() {
return mInnerPagerTitleView;
}
public void setInnerPagerTitleView(IPagerTitleView innerPagerTitleView) {
if (mInnerPagerTitleView == innerPagerTitleView) {
return;
}
mInnerPagerTitleView = innerPagerTitleView;
removeAllViews();
if (mInnerPagerTitleView instanceof View) {
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
addView((View) mInnerPagerTitleView, lp);
}
if (mBadgeView != null) {
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
addView(mBadgeView, lp);
}
}
public View getBadgeView() {
return mBadgeView;
}
public void setBadgeView(View badgeView) {
if (mBadgeView == badgeView) {
return;
}
mBadgeView = badgeView;
removeAllViews();
if (mInnerPagerTitleView instanceof View) {
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
addView((View) mInnerPagerTitleView, lp);
}
if (mBadgeView != null) {
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
addView(mBadgeView, lp);
}
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (mInnerPagerTitleView instanceof View && mBadgeView != null) {
int[] position = new int[14]; // 14种角标定位方式
View v = (View) mInnerPagerTitleView;
position[0] = v.getLeft();
position[1] = v.getTop();
position[2] = v.getRight();
position[3] = v.getBottom();
if (mInnerPagerTitleView instanceof IMeasurablePagerTitleView) {
IMeasurablePagerTitleView view = (IMeasurablePagerTitleView) mInnerPagerTitleView;
position[4] = view.getContentLeft();
position[5] = view.getContentTop();
position[6] = view.getContentRight();
position[7] = view.getContentBottom();
} else {
for (int i = 4; i < 8; i++) {
position[i] = position[i - 4];
}
}
position[8] = v.getWidth() / 2;
position[9] = v.getHeight() / 2;
position[10] = position[4] / 2;
position[11] = position[5] / 2;
position[12] = position[6] + (position[2] - position[6]) / 2;
position[13] = position[7] + (position[3] - position[7]) / 2;
// 根据设置的BadgeRule调整角标的位置
if (mXBadgeRule != null) {
int x = position[mXBadgeRule.getAnchor().ordinal()];
int offset = mXBadgeRule.getOffset();
int newLeft = x + offset;
mBadgeView.offsetLeftAndRight(newLeft - mBadgeView.getLeft());
}
if (mYBadgeRule != null) {
int y = position[mYBadgeRule.getAnchor().ordinal()];
int offset = mYBadgeRule.getOffset();
int newTop = y + offset;
mBadgeView.offsetTopAndBottom(newTop - mBadgeView.getTop());
}
}
}
@Override
public int getContentLeft() {
if (mInnerPagerTitleView instanceof IMeasurablePagerTitleView) {
return getLeft() + ((IMeasurablePagerTitleView) mInnerPagerTitleView).getContentLeft();
}
return getLeft();
}
@Override
public int getContentTop() {
if (mInnerPagerTitleView instanceof IMeasurablePagerTitleView) {
return ((IMeasurablePagerTitleView) mInnerPagerTitleView).getContentTop();
}
return getTop();
}
@Override
public int getContentRight() {
if (mInnerPagerTitleView instanceof IMeasurablePagerTitleView) {
return getLeft() + ((IMeasurablePagerTitleView) mInnerPagerTitleView).getContentRight();
}
return getRight();
}
@Override
public int getContentBottom() {
if (mInnerPagerTitleView instanceof IMeasurablePagerTitleView) {
return ((IMeasurablePagerTitleView) mInnerPagerTitleView).getContentBottom();
}
return getBottom();
}
public BadgeRule getXBadgeRule() {
return mXBadgeRule;
}
public void setXBadgeRule(BadgeRule badgeRule) {
if (badgeRule != null) {
BadgeAnchor anchor = badgeRule.getAnchor();
if (anchor != BadgeAnchor.LEFT
&& anchor != BadgeAnchor.RIGHT
&& anchor != BadgeAnchor.CONTENT_LEFT
&& anchor != BadgeAnchor.CONTENT_RIGHT
&& anchor != BadgeAnchor.CENTER_X
&& anchor != BadgeAnchor.LEFT_EDGE_CENTER_X
&& anchor != BadgeAnchor.RIGHT_EDGE_CENTER_X) {
throw new IllegalArgumentException("x badge rule is wrong.");
}
}
mXBadgeRule = badgeRule;
}
public BadgeRule getYBadgeRule() {
return mYBadgeRule;
}
public void setYBadgeRule(BadgeRule badgeRule) {
if (badgeRule != null) {
BadgeAnchor anchor = badgeRule.getAnchor();
if (anchor != BadgeAnchor.TOP
&& anchor != BadgeAnchor.BOTTOM
&& anchor != BadgeAnchor.CONTENT_TOP
&& anchor != BadgeAnchor.CONTENT_BOTTOM
&& anchor != BadgeAnchor.CENTER_Y
&& anchor != BadgeAnchor.TOP_EDGE_CENTER_Y
&& anchor != BadgeAnchor.BOTTOM_EDGE_CENTER_Y) {
throw new IllegalArgumentException("y badge rule is wrong.");
}
}
mYBadgeRule = badgeRule;
}
public boolean isAutoCancelBadge() {
return mAutoCancelBadge;
}
public void setAutoCancelBadge(boolean autoCancelBadge) {
mAutoCancelBadge = autoCancelBadge;
}
}

View File

@@ -0,0 +1,31 @@
package net.lucode.hackware.magicindicator.buildins.commonnavigator.titles.badge;
/**
* 角标的定位规则
* Created by hackware on 2016/7/19.
*/
public class BadgeRule {
private BadgeAnchor mAnchor;
private int mOffset;
public BadgeRule(BadgeAnchor anchor, int offset) {
mAnchor = anchor;
mOffset = offset;
}
public BadgeAnchor getAnchor() {
return mAnchor;
}
public void setAnchor(BadgeAnchor anchor) {
mAnchor = anchor;
}
public int getOffset() {
return mOffset;
}
public void setOffset(int offset) {
mOffset = offset;
}
}

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/scroll_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fadingEdge="none"
android:scrollbars="none">
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/indicator_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" />
<LinearLayout
android:id="@+id/title_container"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal" />
</FrameLayout>
</HorizontalScrollView>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/indicator_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" />
<LinearLayout
android:id="@+id/title_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" />
</FrameLayout>

View File

@@ -1 +1 @@
include ':app', ':customer', ':base', ':device', ':http', ':media', ':messaging', ':storage', ':uikit', ':location', ':citypicker', ':share', ':yunxinkit', ':faceunity' include ':app', ':customer', ':base', ':device', ':http', ':media', ':messaging', ':storage', ':uikit', ':location', ':citypicker', ':share', ':yunxinkit', ':faceunity',':magicindicator'

View File

@@ -81,6 +81,7 @@
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:visibility="gone"
android:id="@+id/bottom_tab_live_layout" android:id="@+id/bottom_tab_live_layout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"