8000 GitHub - goodsfile/LwBaseLib: 芦苇科技Android基础框架库
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

goodsfile/LwBaseLib

 
 

Repository files navigation

LwBaseLib

芦苇科技Android基础框架库

  • Dialog

    待添加

  • Popup

    Popup弹窗是一个非常易用,并且自定义性比较高的对系统PopupWindow的封装。通过链式调用可一行代码快速实现Popup,也可以通过使用预创建好的Popup实现同类型弹窗,避免重复代码。

    1. 基本使用

      • Popup的基础文件只有 BasePopupXGravityYGravity 三个,其中后两者主要是控制弹窗展示的方向,所有Popup的实现和控制都在 BasePopup 中。在按照自己需求创建Popup时,需要继承 BasePopup ,并传入必要的 Context 信息。

      • 为了方便直接使用,在基础库中已经创建了一个基础的通用自定义Popup—— CustomPopup ,下面通过示例,看一下如何通过调用CustomPopup 创建一个功能完整的Popup:

        CustomPopup.newInstance(this)//创建实例,传入Context
                .setContentView(R.layout.market_popup_invite_guild)//设置弹窗布局xml文件
                .setWidth(ScreenUtils.getScreenWidth() / 3 * 2)//设定宽度 
                .setBackgroundDimEnable(true)//设定打开弹窗时背景变暗
                .setFocusAndOutsideEnable(true)//点击Popup之外的地方可关掉Popup
                .setOnViewListener((view, popup) -> {
                    EditText etApplyText = view.findViewById(R.id.et_invite_text);
                    //... 此处省略 对View中的控件进行处理
                    popup.dismiss();//关闭弹窗
                    });
                })
        				.showAtLocation(getView(), Gravity.CENTER);//居中显示Popup
      • 在项目中,为了处理同样类型的弹窗,可以通过继承 BasePopup 创建特定类型的Popup。比如最常用的确认弹窗,包含确认、取消、关闭三个按钮,以及顶部标题栏,描述栏等内容。下面举例如何封装一个通用的确认弹窗Popup:

        public class ConfirmPopup extends BasePopup<ConfirmPopup> {
            private Context mContext;
            private Callback mCallback;
            private View.OnClickListener mOnCancelListener;
            private View.OnClickListener mOnConfirmListener;
            private CharSequence mTitleText;
            private CharSequence mDescribeText;
            private CharSequence mCancelText;
            private CharSequence mConfirmText;
            private int mCancelColor;
            private int mConfirmColor;
        
            private ConfirmPopup(Context context) {
                this.mContext = context;
                setContext(mContext);
            }
        
            public static ConfirmPopup newInstance(Context context) {
                return new ConfirmPopup(context);
            }
        
            @Override
            protected void initAttributes() {
                setContentView(R.layout.base_popup_confirm);//设置布局xml文件
                setBackgroundDimEnable(true)//设定打开弹窗时背景变暗
                setFocusAndOutsideEnable(true)//点击Popup之外的地方可关掉Popup
                setWidth(ScreenUtils.getScreenWidth() / 3 * 2)//设定宽度 
            }
        
            @Override
            protected void initViews(View view, ConfirmPopup popup) {
                TextView tvTitle = view.findViewById(R.id.tv_title);
                TextView tvDescribe = view.findViewById(R.id.tv_describe);
                TextView tvConfirm = view.findViewById(R.id.tv_confirm);
                TextView tvCancel = view.findViewById(R.id.tv_cancel);
                if (mCallback != null) {
                    tvConfirm.setOnClickListener(v -> mCallback.onClick(this));
                } else if (mOnConfirmListener != null) {
                    tvConfirm.setOnClickListener(mOnConfirmListener);
                }
                if (mOnCancelListener != null) {
                    tvCancel.setOnClickListener(mOnCancelListener);
                } else {
                    tvCancel.setOnClickListener(v -> popup.dismiss());//添加默认取消按钮监听
                }
                if (mTitleText != null) {
                    tvTitle.setText(mTitleText);
                }
                if (mDescribeText != null) {
                    tvDescribe.setText(mDescribeText);
                }
                if (mConfirmText != null) {
                    tvConfirm.setText(mConfirmText);
                }
                if (mCancelText != null) {
                    tvCancel.setText(mCancelText);
                }
                if (mCancelColor != 0) {
                    tvConfirm.setTextColor(mCancelColor);
                }
                if (mConfirmColor != 0) {
                    tvConfirm.setTextColor(mConfirmColor);
                }
            }
        		//设置取消按钮监听
            public ConfirmPopup setOnCancelClickListener(View.OnClickListener onCancelListener) {
                mOnCancelListener = onCancelListener;
                return this;
            }
            //设置确认按钮监听
            public ConfirmPopup setOnConfirmClickListener(View.OnClickListener onConfirmListener) {
                mOnConfirmListener = onConfirmListener;
                return this;
            }
            //设置标题文字
            public ConfirmPopup setTitleText(CharSequence titleText) {
                mTitleText = titleText;
                return this;
            }
            //设置描述文字
            public ConfirmPopup setDescribeText(CharSequence describeText) {
                mDescribeText = describeText;
                return this;
            }
            //设置取消按钮文字
            public ConfirmPopup setCancelText(CharSequence cancelText) {
                mCancelText = cancelText;
                return this;
            }
            //设置确认按钮文字
            public ConfirmPopup setConfirmText(CharSequence confirmText) {
                mConfirmText = confirmText;
                return this;
            }
            //省去了所有文字设置以资源方式的重载方法
            //设置确认按钮文字颜色
            public ConfirmPopup setConfirmColor(@ColorRes int confirmColorRes) {
                mConfirmColor = ContextCompat.getColor(mContext, confirmColorRes);
                return this;
            }
            //设置取消按钮文字颜色
            public ConfirmPopup setCancelColor(@ColorRes int cancelColorRes) {
                mCancelColor = ContextCompat.getColor(mContext, cancelColorRes);
                return this;
            }
            //设置确认按钮监听(callback方式)
            public ConfirmPopup setOnConfirmCallback(Callback callback) {
                mCallback = callback;
                return this;
            }
        		
            public interface Callback {
                void onClick(ConfirmPopup popup);
            }
        }

        使用例子:

        ConfirmPopup.newInstance(getContext())
                .setTitleText(R.string.user_bind_weixin)//设置标题字段
                .setDescribeText(R.string.user_bind_wexin_text)//设置描述字段
                .setConfirmText(R.string.user_bind)//设置确认按钮字段
                .setOnDismissListener(() -> {//设置Popup关闭时的监听
                    //...省略操作
                })
                .setOnConfirmCallback(popup -> {//设置确认按钮点击操作
                    //...省略操作
                    popup.dismiss();
                })
                .showAtLocation(getView(), Gravity.CENTER);//居中显示Popup
      • 以上两种Popup的使用方法中,第一种直接通过 CustomPopup 完全自定义创建一个Popup对象,优势是使用快捷,除了布局文件不会再创建其他内容。第二种通过调用预先创建好的Popup,优点则是具有了可复用性,且如果自定义方法足够详细,在调用时也能更加方便,减少代码量。

    2. Popup所有Api使用介绍

      方法名 传参类型 功能 说明
      setContext Context 传入Context 必要参数
      setContentView @LayoutRes int 、View 传入View 必要参数
      setWidth int 设置宽度 默认为ContentView根布局宽度
      setHeight int 设置高度 默认为ContentView根布局高 8000
      setAnchorView View 设置锚点View 以该View作为锚点进行布局
      setYGravity @YGravity int 设置Y轴方向 在Y轴上相对锚点的位置
      setXGravity @XGravity int 设置X轴方向 在X轴上相对锚点的位置
      setOffsetY int Y轴的偏移量 在Y轴上相对锚点的位置偏移量
      setOffsetX int Y轴的偏移量 在X轴上相对锚点的位置偏移量
      setAnimationStyle @StyleRes int 设置动画 弹窗打开和关闭的动画
      setEnterTransition Transition 进场动画 弹窗打开的动画
      setExitTransition Transition 退场动画 弹窗关闭的动画
      setFocusable boolean 是否可以获取焦点 默认为true
      setOutsideTouchable boolean 是否点击Popup以外区域关闭Popup 默认为true
      setTouchable boolean Popup是否可触摸 默认为true,false情况下点击直接关闭
      setFocusAndOutsideEnable boolean 设置获取焦点+点击外部取消 默认为true
      setBackgroundDimEnable boolean 弹出pop时,背景是否变暗 默认为true
      setDimValue float 设置背景变暗时透明度 默认为0.7f
      setDimColor @ColorInt int 设置背景变暗颜色 默认为黑色
      setDimView ViewGroup 设置背景变暗的View
      setInputMethodMode int 设置输入法的操作模式
      setSoftInputMode int 设置输入法的操作模式
      setNeedReMeasureWH boolean 是否重新测量宽高 默认为true
      showAtLocation View,int 按照位置显示Popup
      showAtAnchorView View,@YGravity int,@XGravity int 根据锚点显示Popup
      setOnDismissListener OnDismissListener 设置Popup关闭的监听 监听 Popup关闭的事件
      setOnRealWHAlreadyListener OnRealWHAlreadyListener 设置真实宽高获取成功监听 用于获取准确的Popup宽高
      dismiss 关闭Popup
  • RecyclerView相关

    实际是 鸡汤程序员gminibird根据MultiType封装而来,核心思想是使用Binder替代Adapter来处理RecyclerView复杂布局的编写。在熟练后,使用非常方便且快速。

    1. 基础使用

      Step 1. 创建一个 class,它将是你的数据类型或 Java bean / model. 对这个类的内容没有任何限制。示例如下:

      public class Category {
      
          @NonNull public final String text;
      
          public Category(@NonNull String text) {
              this.text = text;
          }
      }

      Step 2. 创建一个 class 继承 ItemViewBinder.

      ItemViewBinder 是个抽象类,其中 onCreateViewHolder 方法用于生产你的 Item View Holder, onBindViewHolder 用于绑定数据到 Views. 一般一个 ItemViewBinder 类在内存中只会有一个实例对象,MultiType 内部将复用这个 binder 对象来生产所有相关的 item views 和绑定数据。示例:

      public class CategoryViewBinder extends LwItemBinder<Category> {
      
          @Override
          protected View getView(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent) {
              return inflater.inflate(R.layout.item_category, parent, false);
          }
      
          @Override
          protected void onBind(@NonNull LwViewHolder holder, @NonNull Category category) {
              holder.category.setText(category.text);
          }
      }

      Step 3. 在 ActivityFragment 中加入 RecyclerViewList 并注册你的类型,示例:

      public class MainActivity extends AppCompatActivity {
      
          private LwAdapter adapter;
          /* Items 等同于 ArrayList<Object> */
          private Items items;
      
          @Override 
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
              RecyclerView recyclerView = (RecyclerView) findViewById(R.id.list);
      				recyclerView.setLayoutManager(new LinearLayoutManager(this));
            
              adapter = new LwAdapter(items);
              /* 注册类型和 View 的对应关系 */
              adapter.register(Category.class, new CategoryViewBinder());
              adapter.register(Song.class, new SongViewBinder());
              recyclerView.setAdapter(adapter);
      
              /* 模拟加载数据,也可以稍后再加载,然后使用
               * adapter.notifyDataSetChanged() 刷新列表 */
              items = new Items();
              for (int i = 0; i < 20; i++) {
                  items.add(new Category("Songs"));
                  items.add(new Song("小艾大人", R.drawable.avatar_dakeet));
                  items.add(new Song("许岑", R.drawable.avatar_cen));
              }
              adapter.addAll(items);
              adapter.notifyDataSetChanged();
          }
      }

      在Binder的创建中, getViewonBind 分别对应 RecyclerView 中的 onCreateViewHolderonBindViewHolder 方法。

    2. 复杂布局的Item实现

      直接参考作者的文章:

      ItemDecoration深入解析与实战(一)——源码分析

      ItemDecoration深入解析与实战(二)—— 实际运用

  • 权限获取Permission

    RxPermissions 是基于 RxJava 开发的用于帮助 在Android 6.0 中处理运行时权限检测的框架。在 Android 6.0 中增加了对危险权限的动态申请,而不是像 Android 6.0 之前的默认全部获取的方式。

    详细介绍——RxPermissions 源码解析之举一反三

    使用方式:

    RxPermissions 的使用方式有两种

    方式 1:

    RxPermissions rxPermissions = new RxPermissions(MainActivity.this);
            rxPermissions
                    .request(Manifest.permission.READ_EXTERNAL_STORAGE,
                            Manifest.permission.WRITE_EXTERNAL_STORAGE)//这里填写所需要的权限
                    .subscribe(new Consumer<Boolean>() {
                        @Override
                        public void accept(Boolean aBoolean) throws Exception {
                            if (aBoolean) {
                                // 通过
                            }else{
                                // 拒绝
                            }
                        }
                    });
    

    方式 2:结合 RxBinding 来使用

    RxPermissions rxPermissions = new RxPermissions(MainActivity.this);
    // Must be done during an initialization phase like onCreate
    RxView.clicks(findViewById(R.id.enableCamera))
        .compose(rxPermissions.ensure(Manifest.permission.CAMERA))
        .subscribe(granted -> {
            // R.id.enableCamera has been clicked
        });
  • 事件订阅及接收Rxbus

    目前在Base库中,已经较为完善的封装了一套Rxbus框架,主要通过观察者模式处理应用程序间各个组件的通信,或者组件与组建之间的数据传递。

    基础使用:

    举例页面A中做了一个操作,需要更改页面B中的一个UI,贴出代码展示如何通过Rxbus实现:

    页面A:

    RxBus.getInstance().post(new SimpleEvent(SimpleEvent.FLAG_CHANGE_UI));

    在页面B中接受事件:

    RxBus.getInstance().register(this)
            .ofType(SimpleEvent.class)
            .subscribe(simpleEvent -> {
                if (simpleEvent.getFlag() == SimpleEvent.FLAG_CHANGE_UI) {
                    //..省略修改UI操作
                }
            }, throwable -> ToastUtils.showShort(throwable.getMessage()));

    其中用到的示例Event:

    public class SimpleEvent extends BaseEvent {
    
        /**
         * 修改UI
         */
        public static final int FLAG_CHANGE_UI = 0;
    
        public FindEvent(int flag) {
            super(flag, null);
        }
    
        public FindEvent(int flag, Object content) {
            super(flag, content);
        }
    }
    
  • 简单返回事件传递SimpleForResult

    是对Activity中startActivityForResult功能进行的封装,通过观察者模式可以更方便地实现其功能,避免调用 startActivity 时,需要 onActivityResult 处理的类。

    简单示例:

    在A页面中打开页面B,并传入Extra数据。

    /**
     * 微信号未绑定手机号情况下跳转手机绑定
     * 绑定完后授权登录微信
     */
    public void goToBindPhone(String jsonKey) {
        Intent intent = new Intent(LoginActivity.this, BindPhoneActivity.class);
        intent.putExtra("jsonKey", jsonKey);
        new SimpleForResult(this).startForResult(intent,
                (requestCode, resultCode, data) -> {
                    if (resultCode == RESULT_OK) {
                        onAuthorizeSuccess();//授权登录成功
                    }
                });
    }

    在B页面中,执行完成操作后,设置 setResultRESULT_OK ,关闭B页面Activity返回A页面,A页面判断 resultCode ,code相同则执行操作。

    /**
     * 绑定成功回调
     */
    public void onBindPhoneSuccess() {
        setResult(RESULT_OK);
        finish();
    }
  • 通用标题栏TitleBar

    TitleBar是一个可自定义性强,使用简单的通用标题栏框架,在xml和java代码中都能控制,可在application中全局设置文字属性等内容。

    1. 常用方式

      xml中直接使用:

      <com.luwei.ui.view.TitleBar
          android:id="@+id/titleBar"
          android:layout_width="match_parent"
          android:layout_height="wrap_content" />

      需要注意的是,每个标题栏都需要设置标题,可以在manifest中设置android:label属性:

      <activity android:name=".activity.TitleBarAcitivity"
          android:label="通用标题栏"/>

      或者通过app:titleText属性设置标题,如果不需要显示则直接设为app:titleText=""

    2. 全局设置

      在app中可以进行全局属性设置,示例如下:

      public class MyApplication extends Application {
          @Override
          public void onCreate() {
              super.onCreate();
      
              TitleBar.getConfig()
                      .setTitleTextColor(Color.RED)
                      .setTitleTextSize(20)
                      .setBackGroundColor(Color.GRAY);
          }
      }
    3. 所有API方法

      方法名 说明
      setTitleText 设置标题文字,也可以在manifest中设置label属性
      setTitleTextColor 设置标题文字颜色
      setTitleTextSize 设置标题文字大小
      setLeftImage 单独设置标题栏左部图片
      setLeftText 设置标题栏左部文字(如果设置了LeftImage,则只显示Image)
      setLeftTextColor 设置标题栏左部文字颜色
      setLeftTextSize 设置标题栏左部文字大小
      setLeftDrawableLeft 配合左部文字使用,将图片放置到文字的左侧
      setLeftDrawableRight 配合左部文字使用,将图片放置到文字的右侧
      setLeftDrawablePadding 设置图片相距文字的间隔
      setRightImage 设置标题栏右部图片
      setRightText 设置标题栏右部文字(如果设置了RightImage,则只显示Image)
      s 57A7 etRightTextColor 设置标题栏右部文字颜色
      setRightTextSize 设置标题栏右部文字大小
      setRightDrawableLeft 配合右部文字使用,将图片放置到文字的左侧
      setRightDrawableRight 配合右部文字使用,将图片放置到文字的右侧
      setRightDrawablePadding 设置图片相距文字的间隔
      setBackGroundColor 设置标题蓝背景颜色
      setLeftClickListener 设置左部区域点击事件回调
      setRightClickListener 设置右部区域点击事件回调
      setTitleClickListener 设置中间标题区域点击事件回调
  • 倒计时按钮控件TimerButton

    是一个专门处理倒计时的小UI控件,可以设置倒计时的时间,倒计时结束的回调等。

    使用方式:

    <com.luwei.base.widget.TimerButton
        android:id="@+id/timerbutton"
        android:layout_width="100dp"
        android:layout_height="27dp"
        android:background="@drawable/user_selector_enabled_f92b2b_else_cccccc_13"
        android:gravity="center"
        android:text="@string/user_sent_code"
        android:textColor="@drawable/user_selector_enabled_f92b2b_else_ffffff"
        android:textSize="12sp"          
        app:finishedText="@string/user_resent_code"//倒计时结束时的文段
        app:formatText="%ds"//倒计时秒数的显示格式,比如是xxs还是xx秒,x分x秒等
        app:time="60" //倒计时的秒数/>
    mTimerbutton.setCallback(new TimerButton.Callback() {
        @Override
        public void onFinish(TimerButton button) {
            button.setEnabled(true);
        }
    
        @Override
        public void onTick(TimerButton button, long millisUntilFinished) {
    
        }
    });

    API

    方法名 功能
    isStated 返回是否开启倒计时的布尔值
    resetStatus 恢复倒计时为最初状态
    start 开启倒计时
    stop 停止倒计时
    setCallback 设置倒计时监听,包含结束时监听和在倒计时中的监听
    setFormatText 设置倒计时读秒文字格式
    setFinishedText 设置倒计时结束文字
    setStartedColor 设置倒计时启动后的文字颜色
    setStartedBackground 设置倒计时启动后的背景颜色
    setTime 设置倒计时秒数
  • 图片预览ImagePreview

    待补充

  • 图片选择ImageSelector

    一个简单的图片选择控件,可以单选、多选、以及打开摄像头拍摄新照片。

    打开图片需要获取手机存储权限,可以使用了base库内的RxPermission来获取权限,打开图片选择Activity中需要用到startForResult,这里通过前面封装的SimpleForResult来实现。

    打开图库有几种方式:

    1. onActivityResult中处理图片选择结果

      public void openImageSelect() {
              // todo:打开摄像头、读写权限
              // todo:在 AndroidManifest.xml 中添加  <activity android:name="me.nereo.image_selector.MultiImageSelectorActivity"/>
              MultiImageSelector.create(this)
                      .single()
                      .showCamera(true)
                      .start(this, REQUEST_SELECT_CODE);
          }
    2. 选择单个图片、无需在onActivityResult中处理图片选择结果

      public void openImageSelect2() {
          // todo:打开摄像头、读写权限
          // todo:在 AndroidManifest.xml 中添加  <activity android:name="me.nereo.image_selector.MultiImageSelectorActivity"/>
        simpleForResult.startForResult(PictureIntentHelper.getSelectSingleImageIntent(this, false))
                  .subscribe(resultInfo -> {
                      if (resultInfo.getResultCode() == RESULT_OK) {
                          List<String> urls = resultInfo.getData().getStringArrayListExtra(MultiImageSelectorActivity.EXTRA_RESULT);
                          if (urls != null && urls.size() > 0) {
                              mHeadUrl = urls.get(0);
                              ImageLoaderUtils.getInstance().loadCircleImage(this, ivHeader, mHeadUrl);
                          }
                      }
                  });
      }
    3. 选择多个图片

      public void openImageSelect3() {
          // todo:打开摄像头、读写权限
          // todo:在 AndroidManifest.xml 中添加  <activity android:name="me.nereo.image_selector.MultiImageSelectorActivity"/>
          simpleForResult.startForResult(PictureIntentHelper.getSelectMultiImageIntent(this, false,3))
                  .subscribe(resultInfo -> {
                      if (resultInfo.getResultCode() == RESULT_OK) {
                          List<String> urls = resultInfo.getData().getStringArrayListExtra(MultiImageSelectorActivity.EXTRA_RESULT);
                          if (urls != null && urls.size() > 0) {
                              mHeadUrl = urls.get(0);
                              ImageLoaderUtils.getInstance().loadCircleImage(this, ivHeader, mHeadUrl);
                          }
                      }
                  });
      }
    4. 打开摄像头拍摄照片并裁减

    private void openCamera() {
        try {
            mTmpFile = FileUtils.createTmpFile(this);
        } catch (IOException e) {
            e.printStackTrace();
        }
        simpleForResult.startForResult(PictureIntentHelper.getOpenCameraIntent(this, mTmpFile))
                .subscribe((resultInfo -> {
                    if (resultInfo.getResultCode() == RESULT_OK) {
                        mHeadUrl = mTmpFile.getAbsolutePath();
                        ImageLoaderUtils.getInstance().loadCircleImage(this, ivHeader, mHeadUrl);
                        // 裁剪(如果没有要求可裁剪,也可以不要)
                        startPictureZoom(mTmpFile);
                    }
                }));
    }
    
    public void startPictureZoom(File srcFile) {
        try {
            mZoomOutFile = FileUtils.createTmpFile(this);
        } catch (IOException e) {
            e.printStackTrace();
        }
        simpleForResult.startForResult(PictureIntentHelper.getPhotoZoomIntent(this, srcFile, mZoomOutFile))
                .subscribe(resultInfo -> {
                    if (mZoomOutFile != null && mZoomOutFile.exists()) {
                        mHeadUrl = mZoomOutFile.getAbsolutePath();
                        ImageLoaderUtils.getInstance().loadCircleImage(this, ivHeader, mHeadUrl);
                        Log.i(TAG, "startPictureZoom: ");
                    }
                });
    }
  • 横幅广告Banner

    待添加

  • 友盟分享集成

    待补充完善,可以先查看Android 友盟社会化分享的集成与封装

About

芦苇科技Android基础框架库

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Java 100.0%
0