一个应用程序里面有多个activity和不同的对话框窗体,在我脑海深处的记忆力,对话框的使用一直都是new 出不同的dialog实例然后调用show 、dismiss方法,而弹出视图的控件监听很多时候都是在用CallBack回调函数处理,并且弹出视图获取控件基本都是(xxx)converView.findbyid..我开始发现我做的每个项目都这么写类似代码,于是乎开始了我的思考:一个应用只new一个dialog或者PopupWindow实例?不同的dialog显示可以不可以用类似FragmentManage管理?弹出视图的控件获取能不能更简单一点?于是乎一个简单的demo原型就出来了。
这是一个简单的筛选demo,模拟数据类MenuData.java是由android studio插件GsonFormat生成,对生成的set get进行了简单的修改,这里就不贴详细代码了,下面是生成代码类和GsonFormat使用的效果图。
import java.util.List;
/**
* Created by LanYan on 2015/8/27.
*/
public class MenuData {
/**
* sortLIst : [{"count":"2345","sortId":"2004748","sortType":"1","sortName":"预付卡商户"},{"count":"2345","sortId":"2004748","sortType":"1","sortName":"预付卡商户"},{"count":"2345","sortId":"2004748","sortType":"1","sortName":"预付卡商户"}]
* cityId : 30000534
* checkAreaId : 23423423
* cityName : 成都
* checkSmartId : 234242342
* checkSortName : 预付卡商户
* checkSortId : 2342e544
* checkSmartName : 天天折扣
* checkAreaName :
* checkTypeName : 美食
* searchName :
* smartList : [{"smartName":"天天半价","smartId":"2004748"},{"smartName":"天天折扣","smartId":"2004748"},{"smartName":"预付卡商户","smartId":"2004748"}]
* areaList : [{"parentId":"10003","count":"32453","childList":[{"childId":"1000031","childName":"盐市口"},{"childId":"1000032","childName":"春熙路"}],"parentName":"锦江"},{"parentId":"10003","count":"32453","childList":[{"childId":"1000031","childName":"盐市口"},{"childId":"1000032","childName":"春熙路"}],"parentName":"锦江"}]
* checkTypeId : 234234
* typeList : [{"parentId":"10003","count":"32453","childList":[{"childId":"1000031","childName":"盐市口"},{"childId":"1000032","childName":"春熙路"}],"parentName":"锦江"},{"parentId":"10003","count":"32453","childList":[{"childId":"1000031","childName":"盐市口"},{"childId":"1000032","childName":"春熙路"}],"parentName":"锦江"}]
*/
private List<SortLIstEntity> sortLIst;
private String cityId;
private String checkAreaId;
private String cityName;
private String checkSmartId;
private String checkSortName;
private String checkSortId;
private String checkSmartName;
private String checkAreaName;
private String checkTypeName;
private String searchName;
private List<SmartListEntity> smartList;
private List<AreaListEntity> areaList;
private String checkTypeId;
private List<TypeListEntity> typeList;
.........................此处省略.................................
@Override
public String toString() {
return "MenuData [sortLIst=" + sortLIst + ", cityId=" + cityId
+ ", checkAreaId=" + checkAreaId + ", cityName=" + cityName
+ ", checkSmartId=" + checkSmartId + ", checkSortName="
+ checkSortName + ", checkSortId=" + checkSortId
+ ", checkSmartName=" + checkSmartName + ", checkAreaName="
+ checkAreaName + ", checkTypeName=" + checkTypeName
+ ", searchName=" + searchName + ", smartList=" + smartList
+ ", areaList=" + areaList + ", checkTypeId=" + checkTypeId
+ ", typeList=" + typeList + "]";
}
}
下面是一个FilterPopupWindow 对PopupWindow类操作的封装:
public class FilterPopupWindow {
private static FilterPopupWindow mFilterPopupWindow;
private PopupWindow mPopupWindow;
public PopupWindow getmPopupWindow() {
return mPopupWindow;
}
public void setmPopupWindow(PopupWindow mPopupWindow) {
this.mPopupWindow = mPopupWindow;
}
private FilterPopupWindow(){
}
public static FilterPopupWindow getInstance(){
if(mFilterPopupWindow==null){
synchronized (FilterPopupWindow.class) {
if(mFilterPopupWindow==null){
mFilterPopupWindow=new FilterPopupWindow();
}
}
}
return mFilterPopupWindow;
}
public PopupWindow onCreatePopupWindow(Activity mActivity,View view){
WindowManager manager=(WindowManager) mActivity.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics=new DisplayMetrics();
manager.getDefaultDisplay().getMetrics(outMetrics);
int mWidth=outMetrics.widthPixels;
int mHeight=outMetrics.heightPixels;
mPopupWindow=new PopupWindow(mActivity);
mPopupWindow.setWidth(mWidth);
mPopupWindow.setHeight(mHeight);
mPopupWindow.setContentView(view);
mPopupWindow.setAnimationStyle(R.style.FilterPopupWindow);
mPopupWindow.setBackgroundDrawable(new ColorDrawable(Color.parseColor("#00000000")));
mPopupWindow.setFocusable(false);
mPopupWindow.setOutsideTouchable(false);
mPopupWindow.update();
return mPopupWindow;
}
public void showPopupWindow(Activity mActivity,int position,View anchor,OnPopupWindowListener mOnPopupWindowListener){
if(mPopupWindow==null){
View mView=FilterView.getInstance().getDecorView(mActivity,position,mOnPopupWindowListener);
mPopupWindow=FilterPopupWindow.getInstance().onCreatePopupWindow(mActivity,mView);
}
if(mPopupWindow!=null&&!mPopupWindow.isShowing()){
FilterView.getInstance().setFragmentWithPosition(position);
mPopupWindow.showAsDropDown(anchor);
}else if(mPopupWindow!=null&&mPopupWindow.isShowing()){
FilterView.getInstance().setFragmentWithPosition(position);
}
}
public void dismissPopupWindow(Activity mActivity){
if(mPopupWindow!=null&&mPopupWindow.isShowing()){
mPopupWindow.dismiss();
}
}
public boolean isShowing(){
if(mPopupWindow!=null){
return mPopupWindow.isShowing();
}else{
return false;
}
}
}
下面是一个不太理想的Fragment的管理模式却是我需要的模式FilterView.java,通过setFragmentWithPosition控制Fragment的显示和隐藏,FramLayout静态加载Fragment,在不同场景加载不同弹出视图,用FragmentManage管理,通过replace方法替换最好。
import java.util.ArrayList;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.FrameLayout;
import com.lanyan.data.DataHelper;
import com.lanyan.filter.R;
import com.lanyan.interfaces.OnPopupWindowListener;
import com.lidroid.xutils.ViewUtils;
import com.lidroid.xutils.view.annotation.ViewInject;
@SuppressLint({ "InflateParams", "ClickableViewAccessibility" })
public class FilterView {
private static FilterView mFilterView;
private View mView;
ArrayList<BasicFilterFragment> mListFragments=new ArrayList<BasicFilterFragment>();
@ViewInject(R.id.filter_cancel)
private View mCancel;
@ViewInject(R.id.framgent_parent_filter)
private FrameLayout mFramLayout;
private FilterView(){
}
public static FilterView getInstance() {
if (mFilterView == null) {
synchronized (DataHelper.class) {
if (mFilterView == null) {
mFilterView = new FilterView();
}
}
}
return mFilterView;
}
public View getDecorView(final Activity mActivity,final int position,
final OnPopupWindowListener mOnPopupWindowListener) {
if(mView==null){
mView=mActivity.getLayoutInflater().inflate(R.layout.fragment_filter, null);
ViewUtils.inject(this,mView);
mCancel.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
mOnPopupWindowListener.onCancel();
return false;
}
});
}
return mView;
}
public void setFragmentWithPosition(int position){
for (int i = 0; i < 4; i++) {
if(i==position){
mFramLayout.getChildAt(i).setVisibility(View.VISIBLE);
}else{
mFramLayout.getChildAt(i).setVisibility(View.INVISIBLE);
}
}
}
}
当Fragment加载Dialog视图后控件的引用可以更简单的想Activity一样获取控件,这里采用的是xutils第三方开源项目的注解模块的功能。
import java.util.ArrayList;
import java.util.List;
import android.widget.ListView;
import com.lanyan.adapter.AreaChildAdapter;
import com.lanyan.adapter.AreaParentAdapter;
import com.lanyan.adapter.ListAdapter.OnItemCheckListener;
import com.lanyan.data.MenuData;
import com.lanyan.data.MenuData.AreaListEntity;
import com.lanyan.data.MenuData.AreaListEntity.ChildListEntity;
import com.lanyan.filter.R;
import com.lidroid.xutils.view.annotation.ViewInject;
public class AreaFragment extends BasicFilterFragment{
@ViewInject(R.id.parentListView)
ListView mParentListView;
@ViewInject(R.id.childListView)
ListView mChildListView;
List<AreaListEntity> mList=new ArrayList<MenuData.AreaListEntity>();
private AreaParentAdapter parentAdapter;
private AreaChildAdapter childAdapter;
@Override
public int getCurrentView() {
// TODO Auto-generated method stub
return R.layout.filter_area;
}
@Override
protected void initView() {
// TODO Auto-generated method stub
super.initView();
mList=mActivity.mMenuData.getAreaList();
if(mList.size()>0&&mList.get(0).getChildList().size()>0){
initialized();
}
}
private void initialized() {
}
.....................此处省略........................
}
以前我们dialog的回调监听通过接口实现,那么现在这个同样可以,不过这里使用的原理相同,不过是直接通过activity调引用方法块。实例如下:
childAdapter.setOnItemCheckListener(new OnItemCheckListener<MenuData.AreaListEntity.ChildListEntity>() {
@Override
public void onChecked(ChildListEntity result) {
mActivity.onCancel();
mActivity.onAreaChanged(result);
}
});
这里的mActivity来自于Fragment基类的getActivity类型强转,这个转换只适合该demo,不同的activity应该强转不同的类型这个操作需要放到自身Fragment里面。 这里的链级列表筛选的适配器继承自超级基类ListAdapter,该类是对BaseAdapter进行了简单的继承封装。
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
/**
*
* @param <T>
*/
public abstract class ListAdapter<T> extends BaseAdapter {
public LayoutInflater inflater=null;
protected List<T> list;
protected Activity context;
public List<T> getList() {
return list;
}
public void setList(List<T> list) {
if(list==null){
list=new ArrayList<T>();
}
this.list = list;
}
/***
* 刷新
* @param newList
*/
public void onRefersh(List<T> newList){
if(newList!=null&&newList.size()>0){
this.setList(newList);
this.notifyDataSetChanged();
}else{
list=new ArrayList<T>();
this.notifyDataSetChanged();
}
}
/***
* 加载跟多
* @param newList
*/
public void onLoadMore(List<T> newList){
if(newList!=null&&newList.size()>0){
for (int i = 0; i < newList.size(); i++) {
list.add(newList.get(i));
}
this.notifyDataSetChanged();
}
}
/**
* 移除某一项
* @param t
*/
public void removeItem(T t){
if(t!=null){
list.remove(t);
this.notifyDataSetChanged();
}
}
/**
* 移除多项
* @param t
*/
public void removeListItem(List<T> newList){
if(newList!=null&&newList.size()>0){
for(T t:newList){
if(list.contains(t)){
list.remove(t);
}
}
this.notifyDataSetChanged();
}
}
public ListAdapter(Activity mcontext,List<T> list){
this.context=mcontext;
this.inflater=LayoutInflater.from(context);
this.setList(list);
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return list.size();
}
@Override
public T getItem(int position) {
// TODO Auto-generated method stub
return list.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
int layout=setContentView();
if(convertView==null){
convertView=inflater.inflate(layout, null);
}
initialized(convertView,getItem(position),onItemCheckListener);
return convertView;
}
public abstract int setContentView();
public abstract void initialized(View view,T result,OnItemCheckListener<T> listener);
public interface OnItemCheckListener<T>{
void onChecked(T result);
}
private OnItemCheckListener<T> onItemCheckListener;
public OnItemCheckListener<T> getOnItemCheckListener() {
return onItemCheckListener;
}
public void setOnItemCheckListener(OnItemCheckListener<T> onItemCheckListener) {
this.onItemCheckListener = onItemCheckListener;
}
}
从此Adapter的使用就简单化了配合ViewHolder使用实例如下
import java.util.List;
import android.app.Activity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.LinearLayout;
import com.lanyan.data.MenuData.AreaListEntity;
import com.lanyan.data.MenuData.AreaListEntity.ChildListEntity;
import com.lanyan.filter.R;
public class AreaChildAdapter extends ListAdapter<AreaListEntity.ChildListEntity> {
public AreaChildAdapter(Activity mcontext, List<ChildListEntity> list) {
super(mcontext, list);
// TODO Auto-generated constructor stub
}
@Override
public int setContentView() {
// TODO Auto-generated method stub
return R.layout.popupwindow_area_child;
}
@Override
public void initialized(
View view,
final ChildListEntity result,
final com.lanyan.adapter.ListAdapter.OnItemCheckListener<ChildListEntity> listener) {
// TODO Auto-generated method stub
ViewHolder.setTextView(view, R.id.child, result.getChildName());
LinearLayout mLayout=ViewHolder.get(view, R.id.parent_layout);
mLayout.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(listener!=null){
listener.onChecked(result);
}
}
});
}
}
流式布局和ListView的适配器参考资料来自鸿洋的博客:http://blog.youkuaiyun.com/lmj623565791?viewmode=contents,下面是demo相关源码链级:http://download.youkuaiyun.com/detail/analyzesystem/9069827