Adapter设计模式-如何将Adapter设计模式运用到实际开
2020-04-11 本文已影响0人
_风听雨声
引言
适配器在生活中非常常见,如手机充电适配器、笔记本电脑电源适配器、电源转接插头...等等。手机充电适配器将家用220V电压转换成充电电压,两孔插座转换三孔插座,这些都是适配器在生活中直观的体现。在Android开发中,RecyclerView、ListView、ViewPager的Adapter都是运用了适配器的设计模式,是适配器模式运用的直观体现。
adapter.png
Adapter的作用
主要是起到转换的作用(对象适配器、类适配器)。比如RecyclreView,需要的是view,我们的数据是一个数据的List,我们需要将这个数据的List转换成一个个的itemView(View)给RecyclerView去addView。
简单示例.png
这个例子效果比较简单,有4个tab,区域、价格、户型、更多,点击时分别对应不同的选择菜单的container,假设每一个container内的样式都是不一样的,那么用适配器模式怎么去实现呢?
实现思路
1.创建MenuSelectorView,继承自LinearLayoutCompat(其他的ViewGroup也可以)
2.实例化Tab容器的layout、menu的Container布局、阴影的布局都添加进MenuSelectorView
private void initView() {
setOrientation(VERTICAL);
mTabLayout = new LinearLayoutCompat(getContext());
LinearLayoutCompat.LayoutParams tabLayoutParams = new LinearLayoutCompat.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
mTabLayout.setLayoutParams(tabLayoutParams);
addView(mTabLayout);
mMenuContainer = new FrameLayout(getContext());
addView(mMenuContainer);
mShadowView = new View(getContext());
mShadowView.setBackgroundColor(shadowColor);
mShadowView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
closeMenu();
}
});
mMenuContainer.addView(mShadowView);
mMenuLayout = new FrameLayout(getContext());
mMenuLayout.setBackgroundColor(Color.WHITE);
mMenuContainer.addView(mMenuLayout);
mMenuContainer.setVisibility(GONE);
}
3.在onMeasure方法获取控件宽高并设置给对应的layout
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int containerLayoutHeight = MeasureSpec.getSize(heightMeasureSpec);
FrameLayout.LayoutParams menuLayoutParams = (FrameLayout.LayoutParams) mMenuLayout.getLayoutParams();
menuViewHeight = containerLayoutHeight * 75 / 100;
menuLayoutParams.height = menuViewHeight;
mMenuLayout.setLayoutParams(menuLayoutParams);
}
4.定义抽象基类BaseAdapter,添加3个子类需要实现的抽象方法
public abstract View getTabView(int position, ViewGroup parent);
public abstract View getMenuView(int position, ViewGroup parent);
public abstract int getItemCount();
两个子类可以选择实现的方法(用于菜单切换时tab的状态切换)
public void menuOpen(int position, View tabView) {}
public void menuClose(int position, View tabView) {}
public static abstract class BaseAdapter {
public abstract View getTabView(int position, ViewGroup parent);
public abstract View getMenuView(int position, ViewGroup parent);
public abstract int getItemCount();
public void menuOpen(int position, View tabView) {
}
public void menuClose(int position, View tabView) {
}
}
5.定义setAdapter方法,接收BaseAdapter的实现类,并将adapter中的tabView和menuView添加到第二步已经定义好的容器
public void setAdapter(BaseAdapter adapter) {
this.mAdapter = adapter;
if (mAdapter != null) {
int itemCount = mAdapter.getItemCount();
for (int i = 0; i < itemCount; i++) {
View tabView = mAdapter.getTabView(i, this);
tabView.setTag(i);
mTabViews.add(tabView);
addTabView(tabView);
View menuView = mAdapter.getMenuView(i, this);
addMenuView(menuView);
}
}
}
6.创建menu打开和切换的方法,并加上动画
private void exChangeMenu(int clickPosition) {
mMenuLayout.getChildAt(mCurrentPosition).setVisibility(GONE);
mAdapter.menuClose(mCurrentPosition, mTabLayout.getChildAt(mCurrentPosition));
mCurrentPosition = clickPosition;
mMenuLayout.getChildAt(mCurrentPosition).setVisibility(VISIBLE);
mAdapter.menuOpen(mCurrentPosition, mTabLayout.getChildAt(mCurrentPosition));
}
private void addMenuView(View menuView) {
menuView.setVisibility(GONE);
mMenuLayout.addView(menuView);
}
private AnimatorSet openAnimatorSet;
public void openMenu() {
if (isAnimatorStarting) return;
if (openAnimatorSet == null) {
openAnimatorSet = new AnimatorSet();
ObjectAnimator openAnimator = ObjectAnimator.ofFloat(mMenuLayout, "translationY",
-menuViewHeight, 0);
ObjectAnimator shadowAlphaAnimator = ObjectAnimator.ofFloat(mShadowView, "alpha",
0f, 1f);
openAnimatorSet.playTogether(openAnimator, shadowAlphaAnimator);
openAnimatorSet.setDuration(ANIMATORDURATION);
openAnimatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
isMenuOpen = true;
isAnimatorStarting = false;
}
@Override
public void onAnimationStart(Animator animation) {
mShadowView.setVisibility(VISIBLE);
isAnimatorStarting = true;
}
});
}
openAnimatorSet.start();
}
private AnimatorSet closeAnimatorSet;
private void closeMenu() {
if (isAnimatorStarting) return;
if (closeAnimatorSet == null) {
closeAnimatorSet = new AnimatorSet();
ObjectAnimator openAnimator = ObjectAnimator.ofFloat(mMenuLayout, "translationY",
0, -menuViewHeight);
ObjectAnimator shadowAlphaAnimator = ObjectAnimator.ofFloat(mShadowView, "alpha",
1f, 0f);
closeAnimatorSet.playTogether(openAnimator, shadowAlphaAnimator);
closeAnimatorSet.setDuration(ANIMATORDURATION);
closeAnimatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
isAnimatorStarting = true;
}
@Override
public void onAnimationEnd(Animator animation) {
mShadowView.setVisibility(GONE);
isMenuOpen = false;
isAnimatorStarting = false;
}
});
}
closeAnimatorSet.start();
}
7.创建BaseAdapter子类,继承自BaseAdapter,实现对应的方法
public class MenuSelectorAdapter extends MenuSelectorView.BaseAdapter {
private String[] tabs = new String[]{"区域", "价格", "户型", "更多"};
private Context mContext;
private LayoutInflater mInflater;
public MenuSelectorAdapter(Context context) {
this.mContext = context;
mInflater = LayoutInflater.from(context);
}
@Override
public View getTabView(int position, ViewGroup parent) {
TextView tabView = new TextView(mContext);
tabView.setText(tabs[position]);
LinearLayoutCompat.LayoutParams tabParams = new LinearLayoutCompat.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
tabParams.weight = 1;
tabView.setLayoutParams(tabParams);
tabView.setPadding(dp2px(10), dp2px(10), dp2px(10), dp2px(10));
tabView.setTextColor(Color.BLACK);
tabView.setGravity(Gravity.CENTER);
return tabView;
}
@Override
public View getMenuView(int position, ViewGroup parent) {
TextView menuView = (TextView) mInflater.inflate(R.layout.layout_menu, parent, false);
menuView.setText(tabs[position]);
return menuView;
}
@Override
public int getItemCount() {
return tabs.length;
}
@Override
public void menuOpen(int position, View tabView) {
TextView tb = (TextView) tabView;
tb.setTextColor(Color.RED);
}
@Override
public void menuClose(int position, View tabView) {
TextView tb = (TextView) tabView;
tb.setTextColor(Color.BLACK);
}
private int dp2px(int dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, mContext.getResources().getDisplayMetrics());
}
}
8.将MenuSelectorView添加到布局文件,并将实例化好的BaseAdapter子类传入
public class MainActivity extends AppCompatActivity {
private MenuSelectorView mSelectorView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSelectorView = findViewById(R.id.menuSelectorView);
mSelectorView.setAdapter(new MenuSelectorAdapter(this));
}
}