1.SelectRecyclerVie:RecycleView封装类,多选单选,同RecyclerView的用法一样
-
效果图
第一步:导包:
compile 'cn.yc:YCRecycleViewLib:1.1'
第二步:设置适配器(注:适配器继承SelectRecyclerViewAdapter)
private void initRecycleView() {
selectView.setLayoutManager(new GridLayoutManager(this, 4));
adapter = new SelectFollowAdapter(this, lists);
selectView.setAdapter(adapter);
//下划线
SpaceViewItemLine itemDecoration = new SpaceViewItemLine(SizeUtils.dp2px(5));
itemDecoration.setPaddingEdgeSide(false);
itemDecoration.setPaddingStart(false);
itemDecoration.setPaddingHeaderFooter(false);
selectView.addItemDecoration(itemDecoration);
}
2.CommonTabLayout: //导航栏,可用于主页的底部导航
(用ViewPager和CommonTabLayout实现底部导航)
- 使用的额外方法
// commonTabLayout.showDot(1);//显示红点,参数代表哪个导航显示
// commonTabLayout.showMsg(1,1);//放qq、微信显示有几条未读信息,第一个参数是需要显示的底部位置,第二个蚕食是显示的条数
// commonTabLayout.setMsgMargin(1, 2, 2); //显示红点信息位置
// commonTabLayout.hideMsg(1);//隐藏未读消息,参数代表哪个导航隐藏
第一步:导包:
compile 'com.flyco.tablayout:FlycoTabLayout_Lib:2.1.0@aar'
第二步:布局引用
<com.flyco.tablayout.CommonTabLayout
android:id="@+id/ctl_table"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#90ffffff"
tl:tl_iconHeight="23dp"
tl:tl_iconWidth="23dp"
tl:tl_indicator_color="#2C97DE"
tl:tl_indicator_height="0dp"
tl:tl_textSelectColor="#2C97DE"
tl:tl_textUnselectColor="#66000000"
tl:tl_textsize="12sp"
tl:tl_underline_color="#DDDDDD"
tl:tl_underline_height="1dp"/>
第三步:在res/values目录下新加arrays.xml文件,将首页底部导航的选中与未选择的图片和文字以分组的形式写进去
<!--首页底部导航栏的标题,未选中时-->
<integer-array name="main_tab_un_select">
<item name="tab_home">@drawable/tab_home_unselect</item>
<item name="tab_find">@drawable/tab_speech_unselect</item>
<item name="tab_data">@drawable/tab_contact_unselect</item>
<item name="tab_me">@drawable/tab_more_unselect</item>
</integer-array>
<!--首页底部导航栏的标题,选中时-->
<integer-array name="main_tab_select">
<item name="tab_home">@drawable/tab_home_select</item>
<item name="tab_find">@drawable/tab_speech_select</item>
<item name="tab_data">@drawable/tab_contact_select</item>
<item name="tab_me">@drawable/tab_more_select</item>
</integer-array>
<!--首页底部导航栏文字-->
<string-array name="main_title">
<item>首页</item>
<item>数据</item>
<item>工具</item>
<item>更多</item>
</string-array>
第三步:定义实体类用于存放arrays xml中的资源:
(实体类实现CustomTabEntity 接口)
public class TabEntity implements CustomTabEntity {
public String title;
public int selectedIcon;
public int unSelectedIcon;
public TabEntity(String title, int selectedIcon, int unSelectedIcon) {
this.title = title;
this.selectedIcon = selectedIcon;
this.unSelectedIcon = unSelectedIcon;
}
@Override
public String getTabTitle() {
return title;
}
@Override
public int getTabSelectedIcon() {
return selectedIcon;
}
@Override
public int getTabUnselectedIcon() {
return unSelectedIcon;
}
}
第四步:获取arrays xml文件下的资源:
public ArrayList<CustomTabEntity> getTabEntity() {
ArrayList<CustomTabEntity> mTabEntities = new ArrayList<>();
TypedArray mIconUnSelectIds = activity.getResources().obtainTypedArray(R.array.main_tab_un_select);
TypedArray mIconSelectIds = activity.getResources().obtainTypedArray(R.array.main_tab_select);
String[] mainTitles = activity.getResources().getStringArray(R.array.main_title);
for (int i = 0; i < mainTitles.length; i++) {
int unSelectId = mIconUnSelectIds.getResourceId(i, R.drawable.tab_home_unselect);
int selectId = mIconSelectIds.getResourceId(i, R.drawable.tab_home_select);
mTabEntities.add(new TabEntity(mainTitles[i],selectId , unSelectId));
}
mIconUnSelectIds.recycle();
mIconSelectIds.recycle();
return mTabEntities;
}
第五步:设置底部导航以及初始化ViewPager:
ArrayList<CustomTabEntity> mTabEntities = presenter.getTabEntity();
(CommonTabLayout) ctlTable.setTabData(mTabEntities);
/**
* 初始化ViewPager数据
*/
private void initViewPager() {
List<Fragment> fragments = new ArrayList<>();
HomeFragment homeFragment = new HomeFragment();
FindFragment findFragment = new FindFragment();
DataFragment otherFragment = new DataFragment();
MeFragment meFragment = new MeFragment();
fragments.add(homeFragment);
fragments.add(findFragment);
fragments.add(otherFragment);
fragments.add(meFragment);
BasePagerAdapter adapter = new BasePagerAdapter(getSupportFragmentManager(), fragments);
vpHome.setAdapter(adapter);
vpHome.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
ctlTable.setCurrentTab(position);
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
vpHome.setOffscreenPageLimit(4);
vpHome.setCurrentItem(0);
}
public class BasePagerAdapter extends FragmentPagerAdapter {
private List<?> mFragment;
private List<String> mTitleList;
/**
* 普通,主页使用
*/
public BasePagerAdapter(FragmentManager fm, List<?> mFragment) {
super(fm);
this.mFragment = mFragment;
}
/**
* 接收首页传递的标题
*/
public BasePagerAdapter(FragmentManager fm, List<?> mFragment, List<String> mTitleList) {
super(fm);
this.mFragment = mFragment;
this.mTitleList = mTitleList;
}
@Override
public Fragment getItem(int position) {
return (Fragment) mFragment.get(position);
}
@Override
public int getCount() {
return mFragment.size();
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
super.destroyItem(container, position, object);
}
/**
* 首页显示title,每日推荐等..
* 若有问题,移到对应单独页面
*/
@Override
public CharSequence getPageTitle(int position) {
if (mTitleList != null) {
return mTitleList.get(position);
} else {
return "";
}
}
public void addFragmentList(List<?> fragment) {
this.mFragment.clear();
this.mFragment = null;
this.mFragment = fragment;
notifyDataSetChanged();
}
}
3.滑动卡片的效果
-
效果图
第一步:导包:
compile 'cn.yc:YCCardViewLib:1.2'
第二步:布局文件
<?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">
<com.ns.yc.yccardviewlib.CardViewLayout
android:id="@+id/cardview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
第三步:实现效果(pictures是图片地址集合)
private void initCardVioew(CardViewLayout cardView) {
cardView.setAdapter(new CardViewLayout.Adapter() {
@Override
public int getLayoutId() {
return R.layout.card_item;
}
@Override
public void bindView(View view, int index) {
ViewHolder holder = (ViewHolder) view.getTag();
if (holder == null) {
holder = new ViewHolder();
holder.imageView = (ImageView) view.findViewById(R.id.image);
view.setTag(holder);
}
if (pictures.size() > 0) {
loadImgByPicassoWithRound(CardViewActivity.this, pictures.get(index), 6, R.mipmap.ic_launcher, holder.imageView);
}
}
@Override
public int getItemCount() {
return pictures.size();
}
class ViewHolder {
ImageView imageView;
}
});
}
4.跑马灯效果(可以自动显示不同的标题)
第一步:自定义view
public class MarqueeView extends ViewFlipper {
private Context mContext;
private List<? extends CharSequence> notices;
private boolean isSetAnimDuration = false;
private OnItemClickListener onItemClickListener;
private int interval = 2000;
private int animDuration = 500;
private int textSize = 14;
private int textColor = 0xffffffff;
private boolean singleLine = false;
private int gravity = Gravity.LEFT | Gravity.CENTER_VERTICAL;
private static final int TEXT_GRAVITY_LEFT = 0, TEXT_GRAVITY_CENTER = 1, TEXT_GRAVITY_RIGHT = 2;
public MarqueeView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs, 0);
}
private void init(Context context, AttributeSet attrs, int defStyleAttr) {
this.mContext = context;
if (notices == null) {
notices = new ArrayList<>();
}
TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.MarqueeViewStyle, defStyleAttr, 0);
interval = typedArray.getInteger(R.styleable.MarqueeViewStyle_mvInterval, interval);
isSetAnimDuration = typedArray.hasValue(R.styleable.MarqueeViewStyle_mvAnimDuration);
singleLine = typedArray.getBoolean(R.styleable.MarqueeViewStyle_mvSingleLine, false);
animDuration = typedArray.getInteger(R.styleable.MarqueeViewStyle_mvAnimDuration, animDuration);
if (typedArray.hasValue(R.styleable.MarqueeViewStyle_mvTextSize)) {
textSize = (int) typedArray.getDimension(R.styleable.MarqueeViewStyle_mvTextSize, textSize);
textSize = px2sp(mContext, textSize);
}
textColor = typedArray.getColor(R.styleable.MarqueeViewStyle_mvTextColor, textColor);
int gravityType = typedArray.getInt(R.styleable.MarqueeViewStyle_mvGravity, TEXT_GRAVITY_LEFT);
switch (gravityType) {
case TEXT_GRAVITY_CENTER:
gravity = Gravity.CENTER;
break;
case TEXT_GRAVITY_RIGHT:
gravity = Gravity.RIGHT | Gravity.CENTER_VERTICAL;
break;
}
typedArray.recycle();
setFlipInterval(interval);
}
// 根据公告字符串启动轮播
public void startWithText(final String notice) {
if (TextUtils.isEmpty(notice)) return;
getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
getViewTreeObserver().removeGlobalOnLayoutListener(this);
startWithFixedWidth(notice, getWidth());
}
});
}
// 根据公告字符串列表启动轮播
public void startWithList(List<? extends CharSequence> notices) {
setNotices(notices);
start();
}
// 根据宽度和公告字符串启动轮播
private void startWithFixedWidth(String notice, int width) {
int noticeLength = notice.length();
int dpW = px2dip(mContext, width);
int limit = dpW / textSize;
if (dpW == 0) {
throw new RuntimeException("Please set MarqueeView width !");
}
List list = new ArrayList();
if (noticeLength <= limit) {
list.add(notice);
} else {
int size = noticeLength / limit + (noticeLength % limit != 0 ? 1 : 0);
for (int i = 0; i < size; i++) {
int startIndex = i * limit;
int endIndex = ((i + 1) * limit >= noticeLength ? noticeLength : (i + 1) * limit);
list.add(notice.substring(startIndex, endIndex));
}
}
notices.addAll(list);
start();
}
// 启动轮播
public boolean start() {
if (notices == null || notices.size() == 0) return false;
removeAllViews();
resetAnimation();
for (int i = 0; i < notices.size(); i++) {
final TextView textView = createTextView(notices.get(i), i);
final int finalI = i;
textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (onItemClickListener != null) {
onItemClickListener.onItemClick(finalI, textView);
}
}
});
addView(textView);
}
if (notices.size() > 1) {
startFlipping();
} else {
stopFlipping();
}
return true;
}
private void resetAnimation(){
clearAnimation();
Animation animIn = AnimationUtils.loadAnimation(mContext, R.anim.anim_marquee_in);
if (isSetAnimDuration) animIn.setDuration(animDuration);
setInAnimation(animIn);
Animation animOut = AnimationUtils.loadAnimation(mContext, R.anim.anim_marquee_out);
if (isSetAnimDuration) animOut.setDuration(animDuration);
setOutAnimation(animOut);
}
// 创建ViewFlipper下的TextView
private TextView createTextView(CharSequence text, int position) {
TextView tv = new TextView(mContext);
tv.setGravity(gravity);
tv.setText(text);
tv.setTextColor(textColor);
tv.setTextSize(textSize);
tv.setSingleLine(singleLine);
tv.setTag(position);
return tv;
}
public int getPosition() {
return (int) getCurrentView().getTag();
}
public List<? extends CharSequence> getNotices() {
return notices;
}
public void setNotices(List<? extends CharSequence> notices) {
this.notices = notices;
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
public interface OnItemClickListener {
void onItemClick(int position, TextView textView);
}
// 将px值转换为dip或dp值,保证尺寸大小不变
public int px2dip(Context context, float pxValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
// 将dip或dp值转换为px值,保证尺寸大小不变
public int dip2px(Context context, float dipValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dipValue * scale + 0.5f);
}
// 将px值转换为sp值,保证文字大小不变
public int px2sp(Context context, float pxValue) {
final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (pxValue / fontScale + 0.5f);
}
}
第二步:布局引用
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="horizontal"
android:padding="10dp"
android:gravity="center_vertical"
android:background="@android:color/white">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/holo_red_dark"
android:textSize="20sp"
android:textStyle="bold"
android:text="精选"/>
<View
android:layout_width="5dp"
android:layout_height="25dp"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:layout_marginLeft="10dp"
android:background="@android:color/holo_red_dark"/>
<!--上下滚动TextView-->
<com.maindemo.vlayout.view.MarqueeView
android:id="@+id/marqueeView"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_gravity="center_vertical"
app:paddingStart="0dp"
app:mvAnimDuration="1000"
app:mvInterval="2000"
app:mvTextColor="#464C4E"
app:mvTextSize="16sp"
app:mvSingleLine="true"/>
</LinearLayout>
第三步:设置适配
marqueeView.startWithList(list);(list是数据集合)
//设置点击事件
marqueeView.setOnItemClickListener
5.阿里巴巴布局开源库VLayout(可以仿天猫淘宝的复杂布局)(mvp模式)
可以参照这个简书文章https://www.jianshu.com/p/067abf64ed40
第一步:导包
compile('com.alibaba.android:vlayout:1.2.2@aar') {
transitive = true
}
第二步:view层:主要是写一个接口,接口中写需要更新ui的操作的方法
public interface IView {
//设置轮播图
void setBanner(BannerView bannerView, List<String>pictures);
//设置九宫格的点击
void setClick(int position);
//设置跑马灯的点击
void setMarqueeClick(int position);
//设置查看更多的点击
void setTitleMoreClick(int position);
}
第三步:preserent层:定义一个接口,写需要初始化数据的操作方法;然后写一个实现类实现这个接口,重写相应方法,在具体方法中做相关请求数据的操作,同时在preserent的实现类中需要用构造方法将view引用过来,方便数据请求完后调用view接口的方法做更新ui的操作。
- 接口
public interface IVPresenter {
DelegateAdapter initRecycler( RecyclerView recyclerView);
BaseAdapter initBanner();
BaseAdapter initGvMenu();
BaseAdapter initMarquee();
BaseAdapter initTitle(String title);
}
- 实现类
public class IVPresenterImpl implements IVPresenter {
private IView iView;
private Context context;
public IVPresenterImpl(Context context, IView view) {
this.iView = view;
this.context = context;
}
/**
* 获取DelegateAdapter
*/
@Override
public DelegateAdapter initRecycler(RecyclerView recyclerView) {
//创建VirtualLayoutManager
VirtualLayoutManager virtualLayoutManager = new VirtualLayoutManager(context);
recyclerView.setLayoutManager(virtualLayoutManager);
//设置回收复用池大小(如果一屏内相同View个数比较多,需要设置一个合适的大小,放在来回滚动时重新创建view)
RecyclerView.RecycledViewPool pool = new RecyclerView.RecycledViewPool();
recyclerView.setRecycledViewPool(pool);
pool.setMaxRecycledViews(0, 20);
//设置适配器
DelegateAdapter delegateAdapter = new DelegateAdapter(virtualLayoutManager, true);
recyclerView.setAdapter(delegateAdapter);
return delegateAdapter;
}
/**
* 初始化轮播图
*/
@Override
public BaseAdapter initBanner() {
final List
<String> icons = new ArrayList<>();
icons.add("http://pic4.nipic.com/20091217/3885730_124701000519_2.jpg");
icons.add("http://img.zcool.cn/community/01711b59426ca1a8012193a31e5398.gif");
icons.add("http://img.taopic.com/uploads/allimg/120727/201995-120HG1030762.jpg");
icons.add("http://img.zcool.cn/community/0142135541fe180000019ae9b8cf86.jpg@1280w_1l_2o_100sh.png");
icons.add("http://news.cnhubei.com/ctjb/ctjbsgk/ctjb40/200808/W020080822221006461534.jpg");
icons.add("http://img.zcool.cn/community/01fd6756f3f8c732f875a944272b7b.jpg");
return new BaseAdapter(new LinearLayoutHelper(), 1, R.layout.banner, this, context, 1) {
@Override
public void onBindViewHolder(BaseViewHolder holder, int position) {
super.onBindViewHolder(holder, position);
//绑定数据
BannerView bannerView = holder.getView(R.id.banner);
iView.setBanner(bannerView, icons);
}
};
}
/**
* 初始化九宫格
*
* @return
*/
@Override
public BaseAdapter initGvMenu() {
final List<Integer> imagers = new ArrayList<>();
TypedArray iconArraty = context.getResources().obtainTypedArray(R.array.gv_menu);
final String[] textArray = context.getResources().getStringArray(R.array.text);
for (int i = 0; i < textArray.length; i++) {
imagers.add(iconArraty.getResourceId(i, R.mipmap.ic_category_2));
}
iconArraty.recycle();
GridLayoutHelper gridLayoutHelper = new GridLayoutHelper(4);
gridLayoutHelper.setPadding(0, 16, 0, 16);
gridLayoutHelper.setVGap(16);//控制子元素之间的垂直间距
gridLayoutHelper.setHGap(0);//控制子元素之间的水平间距
gridLayoutHelper.setBgColor(Color.WHITE);
return new BaseAdapter(gridLayoutHelper, imagers.size(), R.layout.gv_item, this, context, 2) {
@Override
public void onBindViewHolder(BaseViewHolder holder, final int position) {
super.onBindViewHolder(holder, position);
holder.setBackgroundRes(R.id.circle_image, imagers.get(position));
holder.setText(R.id.text, textArray[position]);
LinearLayout ll = holder.getView(R.id.ll);
ll.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
iView.setClick(position);
}
});
}
};
}
/**
* 初始化跑马灯效果
*
* @retur
*/
@Override
public BaseAdapter initMarquee() {
final List<String> titles = new ArrayList<>();
titles.add("1.坚持读书,写作,源于内心的动力!");
titles.add("2.欢迎订阅喜马拉雅听书!");
return new BaseAdapter(new LinearLayoutHelper(), 1, R.layout.marquee, this, context, 3) {
@Override
public void onBindViewHolder(BaseViewHolder holder, final int position) {
super.onBindViewHolder(holder, position);
MarqueeView marqueeView = holder.getView(R.id.marqueeView);
marqueeView.startWithList(titles);
marqueeView.setOnItemClickListener(new MarqueeView.OnItemClickListener() {
@Override
public void onItemClick(int position, TextView textView) {
iView.setMarqueeClick(position);
}
});
}
};
}
/**
* 初始化标题
*
* @return
*/
@Override
public BaseAdapter initTitle(final String title) {
return new BaseAdapter(new LinearLayoutHelper(), 1, R.layout.title, this, context, 4) {
@Override
public void onBindViewHolder(BaseViewHolder holder, final int position) {
super.onBindViewHolder(holder, position);
holder.setText(R.id.title, title);
holder.getView(R.id.more).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
iView.setTitleMoreClick(position);
}
});
}
};
}
第四步:activity做更新ui的操作,首先activity必须实现view层的接口,然后在activity中必须创建preserent层的对象,为了调用preserent层实现类的具体方法;
public class VLayoutActivity extends AppCompatActivity implements IView {
private RecyclerView recyclerView;
private IVPresenter presenter;
private BannerView bannerView;
//存放各个模块的适配器
List<DelegateAdapter.Adapter> mAdapter = new LinkedList<>();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_vlayout);
recyclerView = (RecyclerView) findViewById(R.id.recyclerview);
presenter = new IVPresenterImpl(this, this);
initRecyclerView();
}
private void initRecyclerView() {
//获取DelegateAdapter
DelegateAdapter delegateAdapter = presenter.initRecycler(recyclerView);
//初始化轮播图
BaseAdapter bannerAdapter = presenter.initBanner();
mAdapter.add(bannerAdapter);
//初始化九宫格
BaseAdapter gvMenuAdapter = presenter.initGvMenu();
mAdapter.add(gvMenuAdapter);
//初始化跑马灯效果
BaseAdapter marqueeAdapter = presenter.initMarquee();
mAdapter.add(marqueeAdapter);
//初始化标题
BaseAdapter titleAdapter = presenter.initTitle("豆瓣评分");
mAdapter.add(titleAdapter);
//初始化list
delegateAdapter.setAdapters(mAdapter);
}
/**
* 设置轮播图
*/
@Override
public void setBanner(BannerView bannerView, List<String> pictures) {
this.bannerView = bannerView;
bannerView.setHintGravity(2);//设置位置
bannerView.setAnimationDuration(1000);//设置viewPager滑动动画持续时间
bannerView.setPlayDelay(2000);//设置轮播时间
bannerView.setAdapter(new BannerAdapter(VLayoutActivity.this, pictures));
}
/**
* 九宫格点击事件
*
* @param position
*/
@Override
public void setClick(int position) {
Toast.makeText(this, "点击了" + position, Toast.LENGTH_SHORT).show();
}
/**
* 初始化跑马灯效果
*
* @param position
*/
@Override
public void setMarqueeClick(int position) {
Toast.makeText(this, "点击了" + position, Toast.LENGTH_SHORT).show();
}
/**
* 初始化标题
*
* @param position
*/
@Override
public void setTitleMoreClick(int position) {
Toast.makeText(this, "点击了标题", Toast.LENGTH_SHORT).show();
}
@Override
protected void onPause() {
super.onPause();
if (bannerView != null) {
bannerView.pause();
}
}
@Override
protected void onResume() {
super.onResume();
if (bannerView != null) {
bannerView.resume();
}
}
}