(1).會一點反射知識 可以看看我寫的反射
(2).會一點註解知識
(3).大致看下DialogFragment
推薦一個大佬寫的Android通用DialogFragment封裝 (我是在大佬的基礎上進行了一定程度的修改,因爲大佬寫的佈局是確定的,我給換成了RecyclerView)
(4).運行效果
(註解一下,偷懶直接把大佬的給註釋了,然後把自己寫的添上去)
(1).註解代碼
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; //這種類型的Annotations將被JVM保留,所以他們能在運行時被JVM或其他使用反射機制的代碼所讀取和使用. @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE}) /**用於描述類、接口(包括註解類型) 或enum聲明 Class, interface (including annotation type), or enum declaration */ public @interface ActivityFragmentInject { /** * 佈局Id */ int contentViewId() default -1; /** * 是否開啓EventBus */ boolean isOpenEventBus() default false; }
(2)BaseDialogFragment代碼
import android.content.Context; import android.os.Bundle; import android.support.annotation.FloatRange; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.DialogFragment; import android.support.v7.widget.Toolbar; import android.util.DisplayMetrics; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; import android.widget.TextView; import com.ycb.basedialog.R; import com.ycb.basedialog.annotation.ActivityFragmentInject; import butterknife.ButterKnife; import butterknife.Unbinder; /** * Created by asus on 2019/3/30. */ public abstract class BaseDialogFragment extends DialogFragment { /* *需要能自定義的功能 * 1.可以設置dialog的寬高 * 2.可以設置dialog的背景透明度 * 3.可以設置dialog的顯示位置 * 4.可以設置dialog的外邊距 * 5.可以自定義dialog的佈局 * 6.可以設置dialog的進出動畫 */ private int mMargin=0; //外邊距 private float mDimAmout=0.5f; //背景透明度 private boolean mShowBottomEnable=true;//是否顯示底部 private int mWidth,mHeight;//寬高 private int mContentViewId; //佈局id private int mAnimStyle=0; //進出動畫 private boolean mOutCancel=true;//點擊外部取消 private Context mContext; private View mView; private Unbinder unbinder; @Override public void onAttach(Context context) { super.onAttach(context); mContext=context; } @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); //設置BaseDialog的樣式 setStyle(DialogFragment.STYLE_NO_TITLE, R.style.BaseDialog); // mContentViewId = getLayoutId(); //獲取佈局Id } @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { if (null==mView){ //如果是指定類型註解類型則返回true if (getClass().isAnnotationPresent(ActivityFragmentInject.class)) { //通過反射獲取 反射對象的方法等 返回該類中與參數類型匹配的公有註解對象 ActivityFragmentInject annotation = getClass().getAnnotation(ActivityFragmentInject.class); //獲得佈局id mContentViewId = annotation.contentViewId(); } else { //這裏拋出了運行時異常 throw new RuntimeException("Class must add annotations of ActivityFragmentInitParams.class"); } mView =inflater.inflate(mContentViewId,container,false); } // convertView(BaseHolder,this); unbinder= ButterKnife.bind(this,mView); return mView; } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); initView(mView,savedInstanceState,this); } @Override public void onStart() { super.onStart(); initParams();//這個方法可以寫成抽象方法,在具體的dialog裏面進行具體的設置 當然這裏寫一個通用的也很好 } @Override public void onDestroyView() { super.onDestroyView(); unbinder.unbind(); } //初始化dialog private void initParams() { //因爲dialogfragment 也是一種特殊的window //爲什麼在這裏獲取可以看一下fragment 的生命週期 Window window = getDialog().getWindow(); if (window!=null){ WindowManager.LayoutParams params = window.getAttributes(); params.dimAmount=mDimAmout; if (mShowBottomEnable){ params.gravity= Gravity.BOTTOM; } //設置width if (mWidth==0){ params.width=getScreenWidth(mContext)-2*dp2px(mContext,mMargin); }else { params.width=dp2px(mContext,mWidth); } //設置height if (mHeight==0){ params.height=WindowManager.LayoutParams.WRAP_CONTENT; }else { params.height=dp2px(mContext,mHeight); } //設置動畫 if (mAnimStyle!=0){ window.setWindowAnimations(mAnimStyle); } //設置窗口的屬性 window.setAttributes(params); } setCancelable(mOutCancel); } //操作dialog佈局 protected abstract void initView(View mView, Bundle savedInstanceState, BaseDialogFragment dialog); //float 區間 在0——1 public void setDimAmout(@FloatRange(from = 0 ,to = 1 ) float mDimAmout) { this.mDimAmout = mDimAmout; } public void setShowBottomEnable(boolean mShowBottomEnable) { this.mShowBottomEnable = mShowBottomEnable; } public void setWidth(int mWidth) { this.mWidth = mWidth; } public void setHeight(int mHeight) { this.mHeight = mHeight; } public void setOutCancel(boolean mOutCancel) { this.mOutCancel = mOutCancel; } /** * 獲取屏幕寬度 * * @param context * @return */ public static int getScreenWidth(Context context) { DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); return displayMetrics.widthPixels; } public static int dp2px(Context context, float dipValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dipValue * scale + 0.5f); } protected void initToolbarMenu(Toolbar toolbar, TextView tvTitle, String title) { if (tvTitle != null && title != null) { tvTitle.setText(title); } if (toolbar != null) { toolbar.setTitle(""); toolbar.setNavigationIcon(R.drawable.ic_left); toolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { dismiss(); } }); } } }
(3).rvDialog代碼
import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.View; import android.widget.ImageView; import com.ycb.basedialog.R; import com.ycb.basedialog.annotation.ActivityFragmentInject; import java.util.ArrayList; import butterknife.BindView; /** * Created by asus on 2019/3/31. */ @ActivityFragmentInject(contentViewId = R.layout.rv_dialog) public class RvDialog extends BaseDialogFragment { @BindView(R.id.iv_close) ImageView mIvClose; @BindView(R.id.recy) RecyclerView mRecy; private OnSelectListener<String> mOnSelectListener; private ArrayList<String> mList = new ArrayList<>(); public static RvDialog newInstance(OnSelectListener<String> listener) { RvDialog dialog = new RvDialog(); dialog.setOnSelectListener(listener); return dialog; } @Override protected void initView(View mView, Bundle savedInstanceState, BaseDialogFragment dialog) { initData(); mIvClose.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { dismiss(); } }); mRecy.setAdapter(new SingeLayoutAdapter<String>(getContext(), mList, R.layout.item_affair_sel) { @Override protected void onBinds(BaseHolder holder, final String s, int position) { holder.setText(R.id.tv_sel, s); holder.getItemView().setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mOnSelectListener != null) { //實際上這個方法OnSelectListener<String> mOnSelectListener; //是在這裏執行的 傳出了String值 mOnSelectListener.onSelected(s); } dismiss(); } }); } }); mRecy.setLayoutManager(new LinearLayoutManager(getContext(),LinearLayoutManager.VERTICAL,false)); } private void initData() { for (int i = 0; i < 3; i++) { mList.add("嘿哈" + i); } } public void setOnSelectListener(OnSelectListener<String> mOnSelectListener) { this.mOnSelectListener = mOnSelectListener; } }
這裏還涉及了BaseAdapter的寫法 BaseAdapter封裝
(4).MainActivity裏面的點擊方法
public void showFriendClick(View view) { RvDialog.newInstance(new OnSelectListener<String>() { @Override public void onSelected(String select) { Toast.makeText(MainActivity.this,select,Toast.LENGTH_SHORT).show(); } }).show(getSupportFragmentManager(),"tag"); }
可以把BaseDialogFragment寫的更加簡潔一點,比如那個initParams可以寫成抽象方法在具體的dialog裏面寫,畢竟使用的是RecyclerView,可以通過LayoutManageer設置各種樣式,也可以在rvDialog裏面有網絡連接,顯示接口返回的數據,做成查看聊天詳情界面等都是可以的。