说明:
- 下面的源码,由于androidx导致所有的类包名变了,如果你的工程不是androidx,自己改一下就行。
- 个人建议优先使用原生控件,既减少依赖,可靠性也更强。即使使用开源项目,也建议依赖源码,或者自己将源码做成jar包,这样一旦发现项目bug可以及时修正,而且可能有变态的需求自己也可以尝试修改。
- 开源项目,提高了开发效率,往往是作者对原生组件的封装,但是开源项目的封装往往扩展性难以满足变态的需求。
侧滑菜单
1.DrawerLayout
依赖: DrawerLayout存在于v4包中,我们只需要在xml配置即可
最新的v7是包含v4,直接依赖v7即可,注意androidx的包名变化。
implementation 'com.android.support:appcompat-v7:28.0.3'
基本用法
- 布局
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout android:id="@+id/drawer_layout"
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/holo_red_dark"/>
<RelativeLayout android:layout_gravity="end" android:fitsSystemWindows="true" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/holo_green_dark"/>
<RelativeLayout android:layout_gravity="start" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/holo_blue_bright"/>
</android.support.v4.widget.DrawerLayout>
DrawerLayout 的直接子布局layout_gravity属性指定了子布局的位置
有start、center、end,分别表示左中右的位置,不指定默认为center。
高级用法
- 解决冲突
通过setDrawerLockMode方法锁定与解锁DrawerLayout
坑
1.DrawerLayout不能滑动关闭的解决办法
https://blog.csdn.net/noobzsb/article/details/70597764
左侧布局要放到所有布局的最后
指示器
1.TabLayout
依赖: implementation 'com.android.support:design:28.0.0'
implementation 'com.android.support:support-v4:28.0.0' (ViewPager的依赖)
详细用法demo:https://www.cnblogs.com/JohnTsai/p/4715454.html
基本用法
照着上面的demo写,流水账我就不记了。
属性设置
https://blog.csdn.net/solo_two/article/details/52103988
- 绑定标题的2种方式
方式1:tab.addTab(mBinding.tab.newTab().setText("标题"));
方式2:pagerAdapter复写了getPageTitle方法返回标题,这样必需要求tab与viewpager的item个数一样。
动态添加标题:
tab.setTabsFromPagerAdapter(pagerAdapter);
tab.setupWithViewPager(wrapContentViewpager); /**动态添加需要这个方法刷新一下,不是动态的,一定不能加。*/
- 让TabItem宽度填满TabLayout
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
tabLayout.setTabMode(TabLayout.MODE_FIXED);
选中某一个tab
bottomFuntionTab.getTabAt(0).select()item背景颜色选择器设置
https://blog.csdn.net/u012045061/article/details/53423857
另外可以通过customview解决内容item的padding值
app:tabPaddingStart="10dp"
app:tabPaddingEnd="10dp"获取某一个tab的当前索引位置
@Override
public void onTabSelected(TabLayout.Tab tab) {
switchFragment(tab.getPosition());
}
修改文字图片间距或者修改item背景色,或者加消息提醒啥的。(自定义布局)
https://blog.csdn.net/zpswz/article/details/92834435设置tabItem文字选中与未选中的颜色
bottomTabLayout.setTabTextColors();
或者在xml里自定义风格
<!--样式-->
<style name="MyCustomTabLayout" parent="Widget.Design.TabLayout">
<item name="tabIndicatorColor">?attr/colorAccent</item>
<item name="tabIndicatorHeight">0dp</item>
<item name="tabPaddingStart">12dp</item>
<item name="tabTextColor">#aaa</item>
<item name="tabPaddingEnd">12dp</item>
<item name="tabSelectedTextColor">#f00</item>
</style>
与ViewPager绑定之后,如何添加icon
bottomTab.getTabAt(0).setIcon(R.drawable.video_tab);
icon与文字的距离如何调整
//www.greatytc.com/p/bfc77baf2a41
坑
Caused by: Java.lang.IllegalArgumentException: You need to use a Theme.AppCompat theme (or descendant) with the design library.
参照:https://blog.csdn.net/solo_two/article/details/52103988tab.setTabTextColors设置颜色,取消选中时颜色不正确的bug。
利用xml来完成:http://stackoverflow.com/questions/35597445/tablayouts-text-color-does-not-change-when-setting-the-selected-item-in-code
2.TabHost
TabHost 比较古老不支持滑动
http://blog.csdn.net/harvic880925/article/details/17120325
3.开源指针控件
1)MagicIndicator
https://github.com/hackware1993/MagicIndicator
//www.greatytc.com/p/2865812fed41/ (说明怎么和Viewpager联动)
属性设置
- 标题平分屏幕宽度的模式
commonNavigator.setAdjustMode(true);
底部导航栏
1.使用TabLayout来实现
https://www.cnblogs.com/wushanmanong/p/8878257.html
如果定制要求高,建议tab item使用customview。
2.BottomTabBar
https://blog.csdn.net/leehbhs/article/details/76572325
//www.greatytc.com/p/ade8485a16be
这个框架整体的属性封装都很全面,但是有一个缺点:扩展性太差,切换的页面只能是Fragment。
3.BottomTabLayout
https://github.com/stfalcon-studio/BottomTabLayout
比较大众的封装方法,通过继承RelatveLayout然后做的封装,一般都是通过LinearLayout。
作者之所以使用RelatveLayout,想必是因为Bubble功能。
美中不足的地方:
1)标题是通过menu来绑定的,无法动态添加。(但是一般也不会动态添加吧。)
2)TabItem的样式没法定制,icon与text的间距。
4.EasyNavigation
//www.greatytc.com/p/ce8e09cda486
带加号,可设置的属性非常多,但是也是将item和Fragment绑定了。
5.BottomNavigationView
google官方组件,但是不是特别好用。
轮播图
1.Android-ConvenientBanner
https://github.com/saiwu-bigkoo/Android-ConvenientBanner(可以自定义轮播图的视图,自定义图片加载库,扩展性超级强大。)
下拉刷新
-
非侵入式
https://github.com/scwang90/SmartRefreshLayout (github上start比较高)
https://github.com/nuptboyzhb/SuperSwipeRefreshLayout
http://www.open-open.com/lib/view/open1432883341879.html
https://github.com/huxq17/XRefreshView
PullToReresh
SwipeRefreshLayout
水滴刷新(只有刷新,没有加载更多。)
https://github.com/tuesda/CircleRefreshLayout
别人总结的
https://github.com/android-cjj/BeautifulRefreshLayout
下拉刷新的实现
https://www.open-open.com/lib/view/open1405735508406.html
我的项目用到过的:
1.SuperSwipeRefreshLayout
https://github.com/nuptboyzhb/SuperSwipeRefreshLayout
调用起来代码挺多,我适当的封装了一下:
RefreshHandler.java
/**
* 封装刷新和加载更多的操作
* author:Created by ZhangChen on 2016/8/3 0003.
* detail:
*/
public class RefreshHandler {
private SuperSwipeRefreshLayout swipeRefreshLayout;
// Header View
private ProgressBar progressBar;
private TextView textView;
private ImageView imageView;
// Footer View
private ProgressBar footerProgressBar;
private TextView footerTextView;
private ImageView footerImageView;
private OnActionListener onActionListener;
public RefreshHandler(SuperSwipeRefreshLayout swipeRefreshLayout) {
this.swipeRefreshLayout = swipeRefreshLayout;
initSwipeRefreshLayout( this.swipeRefreshLayout);
}
private void initSwipeRefreshLayout(SuperSwipeRefreshLayout swipeRefreshLayout) {
// init SuperSwipeRefreshLayout
swipeRefreshLayout.setHeaderViewBackgroundColor(Color.parseColor("#ECEFF1"));
swipeRefreshLayout.setFooterViewBackgroundColor(Color.parseColor("#ECEFF1"));
swipeRefreshLayout.setHeaderView(createHeaderView());// add headerView
swipeRefreshLayout.setFooterView(createFooterView());
swipeRefreshLayout.setTargetScrollWithLayout(true);
swipeRefreshLayout
.setOnPullRefreshListener(new SuperSwipeRefreshLayout.OnPullRefreshListener() {
@Override
public void onRefresh() {
textView.setText("正在刷新");
imageView.setVisibility(View.GONE);
progressBar.setVisibility(View.VISIBLE);
if(onActionListener != null){
onActionListener.onRefresh();
}
}
@Override
public void onPullDistance(int distance) {
// pull distance
}
@Override
public void onPullEnable(boolean enable) {
textView.setText(enable ? "松开刷新" : "下拉刷新");
imageView.setVisibility(View.VISIBLE);
imageView.setRotation(enable ? 180 : 0);
}
});
swipeRefreshLayout
.setOnPushLoadMoreListener(new SuperSwipeRefreshLayout.OnPushLoadMoreListener() {
@Override
public void onLoadMore() {
footerTextView.setText("正在加载...");
footerImageView.setVisibility(View.GONE);
footerProgressBar.setVisibility(View.VISIBLE);
if(onActionListener != null){
onActionListener.onLoadMore();
}
}
@Override
public void onPushEnable(boolean enable) {
footerTextView.setText(enable ? "松开加载" : "上拉加载");
footerImageView.setVisibility(View.VISIBLE);
footerImageView.setRotation(enable ? 0 : 180);
}
@Override
public void onPushDistance(int distance) {
}
});
}
private View createFooterView() {
View footerView = LayoutInflater.from(swipeRefreshLayout.getContext())
.inflate(R.layout.layout_footer, null);
footerProgressBar = (ProgressBar) footerView
.findViewById(R.id.footer_pb_view);
footerImageView = (ImageView) footerView
.findViewById(R.id.footer_image_view);
footerTextView = (TextView) footerView
.findViewById(R.id.footer_text_view);
footerProgressBar.setVisibility(View.GONE);
footerImageView.setVisibility(View.VISIBLE);
footerImageView.setImageResource(R.drawable.down_arrows_footer);
footerTextView.setText("上拉加载更多...");
return footerView;
}
private View createHeaderView() {
View headerView = LayoutInflater.from(swipeRefreshLayout.getContext())
.inflate(R.layout.layout_head, null);
progressBar = (ProgressBar) headerView.findViewById(R.id.pb_view);
textView = (TextView) headerView.findViewById(R.id.text_view);
textView.setText("下拉刷新");
imageView = (ImageView) headerView.findViewById(R.id.image_view);
imageView.setVisibility(View.VISIBLE);
imageView.setImageResource(R.drawable.down_arrows_footer);
progressBar.setVisibility(View.GONE);
return headerView;
}
public void finishRefresh(){
swipeRefreshLayout.setRefreshing(false);
progressBar.setVisibility(View.GONE);
}
public void finishLoadMore(){
footerImageView.setVisibility(View.VISIBLE);
footerProgressBar.setVisibility(View.GONE);
swipeRefreshLayout.setLoadMore(false);
}
public interface OnActionListener {
void onRefresh();
void onLoadMore();
}
public void setOnActionListener(OnActionListener onActionListener){
this.onActionListener = onActionListener;
}
}
怎么调用RefreshHandler
创建RefreshHandler
refreshHandler = new RefreshHandler(swipeRefreshLayout);
refreshHandler.setOnActionListener(this);
然后在合适的时候调用
refreshHandler.finishLoadMore();
refreshHandler.finishRefresh();
-
侵入式
列表适配器
1.easyrecyclerview
https://blog.csdn.net/qq_16430735/article/details/49341563?ref=myread
依赖: compile 'com.camnter.easyrecyclerview:easyrecyclerview:1.3'
0