精华内容
下载资源
问答
  • ToolBar封装

    2016-12-12 16:51:30
    实现ToolBar封装 1.更改主题  在Value文件夹中的style文件里修改主题为 style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> 2.创建一个帮助类,在该类中实现ToolBar封装 import ...

    实现ToolBar的封装

    1.更改主题

     在Value文件夹中的style文件里修改主题为

    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">

    2.创建一个帮助类,在该类中实现ToolBar的封装

    import android.content.Context;
    import android.support.v7.widget.Toolbar;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.FrameLayout;
    
    
    /**
     * Created by hatsune39 on 2016/12/12.
     * function:Toolbar的帮助类,把它做好后就不用做大修改,直接用即可
     */
    public class ToolBarHelp {
    
        //ToolBar帮助类的构造方法,方便用户自定义ToolBar,进行对象的初始化
        //layoutID:布局资源,context:上下文
    
    
        //上下文,把一个Xml布局资源转换成View的时候用到
        private Context context;
        //布局资源
        private FrameLayout contextView;
        //打气筒,为了转换成View对象
        private final LayoutInflater inflater;
        //用户传入的XML资源对象
        private View userView;
        //Toolbar的对象,通过getToolBar获取
        private Toolbar toolbar;
    
        public ToolBarHelp(Context context,int layoutID) {
            //传递上下文
            this.context = context;
            //因为普通类没有getInflater()方法可以调用,所以传递一个上下文,通过Layout.from()静态方法得到LayoutInfater的一个对象
            inflater = LayoutInflater.from(context);
            //初始化整个内容
            initContextView();
            //初始化用户自定义布局
            initUserView(layoutID);
            //初始化ToolBar对象
            initToolBar();
        }
    
        /**
         * 初始化整个布局内容
         */
        public void initContextView() {
            //创建一个布局作为视图的容器,视图容器的父容器
            contextView = new FrameLayout(context);
            //设置参数对象,定义宽高都是填充父窗体,
            //ctrl+q
            ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
            //把参数对象传递给视图容器
            contextView.setLayoutParams(params);
        }
    
        //初始化用户自定义的布局
        private void initUserView(int layoutID) {
            //把用户传递过来的XML布局资源转化为一个View对象
            userView = inflater.inflate(layoutID, null);
            //设置参数对象,定义宽高都是填充父窗体
            ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
            //把参数对象传递给视图容器
            userView.setLayoutParams(params);
        }
    
        private void initToolBar() {
            //把一个装有ToolBar的布局资源转换为一个View对象
            View inflate = inflater.inflate(R.layout.activity_tool_bar, contextView);
            //找到布局XML资源里的ToolBar,设置为全局变量
            toolbar = (Toolbar) inflate.findViewById(R.id.toolbar);
        }
    
        /**
         * 返回ToolBar的对象,方便用户对ToolBar的自定义
         * @return
         */
        public Toolbar getToolBar(){
            return toolbar;
        }
    
        /**
         * 获取默认的根布局对象,FrameLayout
         */
        public FrameLayout getContextView(){
            return contextView;
        }
    }

    3.创建一个ToolBar基类,哪个Activity有ToolBar,就继承该类

    import android.support.annotation.LayoutRes;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.support.v7.widget.Toolbar;
    import android.view.MenuItem;
    
    //自定义toolBar的Activity,那个Activity有ToolBar,就继承该类
    public class ToolBarActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    //        setContentView(R.layout.activity_bar_tool);
            //把加载布局的方法进行重写
        }
    
        //进行布局加载方法的复写
        @Override
        public void setContentView(@LayoutRes int layoutResID) {
            super.setContentView(layoutResID);
            //创建ToolBarHelp对象,传递参数,1.上下文 2.布局资源(就由继承ToolBarActivity的Activity去写)
            ToolBarHelp toolBarHelp = new ToolBarHelp(this, layoutResID);
            //获取封装好的ToolBar对象
            Toolbar toolBar = toolBarHelp.getToolBar();
            //设置ToolBarhelp类中默认指定的根容器
            setContentView(toolBarHelp.getContextView());
            //设置支持ToolBar
            setSupportActionBar(toolBar);
            //自定义一些ToolBar的个性化设置
            onCreateCustomToolbar(toolBar);
        }
    
        /**
         * 自定义一些ToolBar的个性设置,继承的Activity记得要对它进行复写
         * @param toolBar
         */
        public void onCreateCustomToolbar(Toolbar toolBar) {
    
        }
    
        //当用户点击菜单栏中的某一个选项时,会调用该方法,重写此方法,当点击左上方图标时,关闭Activity
        @Override
        public boolean onContextItemSelected(MenuItem item) {
            if (item.getItemId() == android.R.id.home){
                finish();
                return true;
            }
            return super.onContextItemSelected(item);
        }
    }

    布局文件中声明一个ToolBar,设置ID与Background即可.

    4.使用封装好的ToolBar

    package com.zhiyuan3g.toolbar;
    
    import android.support.annotation.LayoutRes;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.support.v7.widget.Toolbar;
    import android.view.MenuItem;
    
    //自定义toolBar的Activity,那个Activity有ToolBar,就继承该类
    public class ToolBarActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    //        setContentView(R.layout.activity_bar_tool);
            //把加载布局的方法进行重写
        }
    
        //进行布局加载方法的复写
        @Override
        public void setContentView(@LayoutRes int layoutResID) {
            super.setContentView(layoutResID);
            //创建ToolBarHelp对象,传递参数,1.上下文 2.布局资源(就由继承ToolBarActivity的Activity去写)
            ToolBarHelp toolBarHelp = new ToolBarHelp(this, layoutResID);
            //获取封装好的ToolBar对象
            Toolbar toolBar = toolBarHelp.getToolBar();
            //设置ToolBarhelp类中默认指定的根容器
            setContentView(toolBarHelp.getContextView());
            //设置支持ToolBar
            setSupportActionBar(toolBar);
            //自定义一些ToolBar的个性化设置
            onCreateCustomToolbar(toolBar);
        }
    
        /**
         * 自定义一些ToolBar的个性设置,继承的Activity记得要对它进行复写
         * @param toolBar
         */
        public void onCreateCustomToolbar(Toolbar toolBar) {
              toolBar.inflateMenu(R.menu.toolbar_menu);
              toolBar.setTitle("abc");
              //设置支持ToolBar
              setSupportActionBar(toolBar);
        }
    
        //当用户点击菜单栏中的某一个选项时,会调用该方法,重写此方法,当点击左上方图标时,关闭Activity
        @Override
        public boolean onContextItemSelected(MenuItem item) {
            if (item.getItemId() == android.R.id.home){
                finish();
                return true;
            }
            return super.onContextItemSelected(item);
        }
    }
    

    Demo中用到的MenuXML文件

    <menu xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:app="http://schemas.android.com/apk/res-auto">
        <!--注意:xmlns:app=.../res-auto 是要修改的地方,下面要引用app-->
        <!--    app:showAsAction= 对item是否隐藏折叠的设置,隐藏折叠显示文本,否则显示图片
                always就是一直显示,never就是隐藏折叠-->
    
        <item android:id="@+id/item0"
              app:showAsAction="always"
              android:icon="@drawable/miku"
              android:title="item0"
            />
    </menu>

    效果图如下


    展开全文
  • ToolBar封装策略

    2020-10-13 13:42:16
    策略一: 使用原生toolbar进行封装 流程: * 1所有的类都继承此AppToolBarActivity. * 2打气筒加载一个布局到根布局(即layout_toolbar),此布局包含ToolBar+Framelayout. * 3getContentView()为抽象方法,返回一个View...

    效果:

    策略一: 使用原生toolbar进行封装

    流程:

    * 1所有的类都继承此AppToolBarActivity.
    
    * 2打气筒加载一个布局到根布局(即layout_toolbar),此布局包含ToolBar+Framelayout.
    
    * 3getContentView()为抽象方法,返回一个View 将此View add到framelayout中.
    
    * 4做一些ToolBar的初始化操作.
    
    * 5使用
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            View view = LayoutInflater.from(this).inflate(R.layout.layout_toolbar, (ViewGroup) getWindow().getDecorView().getRootView(), false);
            mContent_frame = view.findViewById(R.id.content_frame);
            if(getContentView() != null){
                mContent_frame.addView(getContentView());
            }
            setContentView(view);
    
            ButterKnife.bind(this);
            steepTitle();
            setSupportActionBar(mToolbar);
            getSupportActionBar().setTitle("");
            getSupportActionBar().setDisplayHomeAsUpEnabled(true);
            getSupportActionBar().setDisplayShowHomeEnabled(true);
            setTitle(getTitle());
    
            initWidget();
            initData();
        }
    
    • 处理ToolBar的返回事件:
        //style.xml中
        <item name="android:homeAsUpIndicator">@mipmap/back_white</item>
        //AppToolBarActivity中
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            if(item.getItemId() == android.R.id.home){
                onBackPressed();
            }
            return super.onOptionsItemSelected(item);
        }
    
    • 处理中间Title 重写setTitle()
        //bar 中间标题
        @Override
        public void setTitle(CharSequence title) {
            mToolbar_tv_title.setText(title);
            mRadioGroup.setVisibility(View.GONE);
        }   
    
    • 处理右侧可能是文字或图片按钮 中间可能是多按钮
        //bar右侧是文字
        protected void setRightTextButtonEnable(@StringRes int rid, View.OnClickListener onClickListener) {
            mTv_title_right.setText(rid);
            mTv_title_right.setOnClickListener(onClickListener);
            mTv_title_right.setVisibility(View.VISIBLE);
        }
        
        //bar右侧是图标
        protected void setRightImageButtonEnable(@DrawableRes int rid, View.OnClickListener onClickListener) {
            mIv_title_right.setImageResource(rid);
            mIv_title_right.setOnClickListener(onClickListener);
            mIv_title_right.setVisibility(View.VISIBLE);
            mTv_title_right.setVisibility(View.GONE);
    
        }
    
        //bar中间是多按钮
        protected void setCenterRadioGroupEnable(String btnLefttext,String btnRighttext, RadioGroup.OnCheckedChangeListener onClickListener) {
            mRadioBtnLeft.setText(btnLefttext);
            mRadioBtnRight.setText(btnRighttext);
            mRadioGroup.setOnCheckedChangeListener(onClickListener);
            mRadioGroup.setVisibility(View.VISIBLE);
            mToolbar_tv_title.setVisibility(View.GONE);
        }
        
    
    • 处理所谓的沉浸式
        //加载沉浸式状态栏
        public void steepTitle() {
            if (Build.VERSION.SDK_INT >= 21) {
                getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
                //注意要清除 FLAG_TRANSLUCENT_STATUS flag
                getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
                getWindow().setStatusBarColor(getResources().getColor(R.color.maincolor));
            }
        }
       
    
    • 最后使用超简单:
        @Override
        protected View getContentView() {
            return initRId(R.layout.activity_main);
        }
    
        @Override
        protected void initWidget() {
            setBackEnable(false);
            setTitle("主页");
        }
    

    github地址传送门

    策略2:自己写一个Bar 使用重载方法初始化

    • 核心代码:
        protected void initAppBar() {
            initAppBar(true, false, -1, -1);
        }
    
        protected void initAppBar(boolean isBack) {
            initAppBar(isBack, false, -1, -1);
        }
    
        protected void initAppBar(boolean isBack, boolean isRightText) {
            initAppBar(isBack, isRightText, -1, -1);
        }
    
        protected void initAppBar(boolean isBack, boolean isRightText, @ColorRes int bgColor, @ColorRes int textColor) {
            //动态添加appbar 这样无需在每个xml中includ进去appbar的布局
            //如果不写这四行 需要在每个xml中incloud进去bar布局
            ViewGroup view = getWindow().getDecorView().findViewById(android.R.id.content);
            ViewGroup inflate = (ViewGroup) view.getChildAt(0);
            View barView = getLayoutInflater().inflate(R.layout.common_appbar, inflate,false);
            inflate.addView(barView,0);
    
            RelativeLayout layout = findViewById(R.id.common_appbar_rl);
            if (layout == null) {
                return;
            }
            invadeStatusBar();
            if (bgColor != -1) {
                layout.setBackgroundResource(bgColor);
            }
            LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) layout.getLayoutParams();
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                layoutParams.setMargins(0, getStatusBarHeight(), 0, 0);
            } else {
                layoutParams.setMargins(0, 0, 0, 0);
            }
            layout.setLayoutParams(layoutParams);
            ImageView iconIV = findViewById(R.id.common_appbar_iv);
            if (!isBack) {
                iconIV.setVisibility(View.GONE);
            } else {
                iconIV.setVisibility(View.VISIBLE);
                iconIV.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        finish();
                    }
                });
            }
            TextView centerTV = findViewById(R.id.common_appbar_center_tv);
            if (textColor != -1) {
                centerTV.setTextColor(getResources().getColor(textColor));
            }
            centerTV.setText(TypeUtil.isBlank(setAppBarTitle()) ? "" : setAppBarTitle());
            TextView rightTV = findViewById(R.id.common_appbar_right_tv);
            if (!isRightText) {
                rightTV.setVisibility(View.GONE);
            } else {
                rightTV.setVisibility(View.VISIBLE);
                if (textColor != -1) {
                    centerTV.setTextColor(getResources().getColor(textColor));
                }
                rightTV.setText(TypeUtil.isBlank(setAppBarRightTitle()) ? "" : setAppBarRightTitle());
                rightTV.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        onAppBarRightClick();
                    }
                });
            }
        }
    
    • 重载方法:
        protected abstract String setAppBarTitle();
    
        protected abstract String setAppBarRightTitle();
    
        protected abstract void onAppBarRightClick();
    
    • 使用:
      initAppBar(true,true);
    
      @Override
        protected String setAppBarTitle() {
            return "Tactics2";
        }
    
        @Override
        protected String setAppBarRightTitle() {
            return "更多";
        }
    
        @Override
        protected void onAppBarRightClick() {
            ToastUtil.showToast("更多");
        }
    

    最后安利一个小技巧:

    • Activity跳转时候,可以这么写,更舒服:
        //只需要在目标Activity敲下start 就会出现自带的方法,可以传递一些数据:
        public static void start(Context context, String id) {
            Intent starter = new Intent(context, TacticsOneActivity.class);
            starter.putExtra("id", id);
            context.startActivity(starter);
        }
    
        //在执行跳转的某按钮处,只需简短一句:
        XxxActivity.start(this,"1");
    
    • 同理Fragment:
        //只需要在目标Fragment敲下newI :
        public static ChargeRecordFragment newInstance(int type,String coinName,String coinDetailName) {
            Bundle args = new Bundle();
            args.putInt("type",type);
            args.putString("coinName",coinName);
            args.putString("coinDetailName",coinDetailName);
            ChargeRecordFragment fragment = new ChargeRecordFragment();
            fragment.setArguments(args);
            return fragment;
        }
        //Activity的某处拿到实例并传递数据:
        ChargeRecordFragment.newInstance(0,mCoinName,mCoinDetailName);
    
    展开全文
  • #1.Toolbar封装处理 #####试想了很多场景.死了n个脑细胞,最后得出来的结构图: ##(1).Appcompat风格: "1.0" encoding= "utf-8" ?> xmlns:android= "http://schemas.android.com/apk/res/android" xmlns...

    转载请标明出处:www.jianshu.com/p/5cb2586ac… 本文出自:Jlanglang

    #前言:

    MVP实战心得四 做了很多修改.期间有很多纠结的地方, 对比google对Activity以及AppcompatActivity的思路, 将原来的代码区分开,弄成2个module. 一个对应FragmentActivity 一个对应AppcompatActivity 区分开来,不再写在一起.

    如不依赖appcompat-v7包就不能使用appcompat控件一样<__>

    #1.Toolbar的封装处理 #####试想了很多场景.死了n个脑细胞,最后得出来的结构图:

    ##(1).Appcompat风格:

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.design.widget.CoordinatorLayout
        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="match_parent"
        android:fitsSystemWindows="true"
        android:theme="@style/BaseAppTheme">
    
        <android.support.design.widget.AppBarLayout
            android:id="@+id/app_bar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"/>
        <FrameLayout
            android:id="@+id/templet_content"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior"
            />
    </android.support.design.widget.CoordinatorLayout>
    复制代码

    ###Toolbar模版

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.design.widget.CollapsingToolbarLayout
        android:id="@+id/collapsing_layout"
        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="match_parent"
        android:fitsSystemWindows="true"
        app:contentScrim="?attr/colorPrimary"
        >
    
        <android.support.v7.widget.Toolbar
            android:id="@+id/tl_costom"
            style="@style/base_toolbar"
            android:layout_height="?actionBarSize"
            app:layout_collapseMode="pin"
            app:popupTheme="@style/popup_theme"
            app:theme="@style/toolbar_theme"
            />
    
    </android.support.design.widget.CollapsingToolbarLayout>
    复制代码

    设计思路: 1.最外层使用CoordinatorLayout,提供动画,联动特性. 2.使用AppBarLayout,可以添加Toolbar等多个控件,可以使用Tablayout,CollapsingToolbarLayout,Toolbar等. 提供扩展的可能性 3.主要内容使用FrameLayout,可以扩展封装loadingView等.

    ##(2).非Appcompat风格:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                  android:layout_width="match_parent"
                  android:layout_height="match_parent"
                  android:orientation="vertical">
        <LinearLayout
            android:id="@+id/app_bar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
        <FrameLayout
            android:id="@+id/templet_content"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    </LinearLayout>
    复制代码

    ###Toolbar模版

     <RelativeLayout
            style="@style/base_toolbar"
            android:layout_width="match_parent"
            android:layout_height="48dp"
            android:orientation="horizontal"
            >
    
            <TextView
                android:id="@+id/tv_left"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_alignParentLeft="true"
                android:background="@android:color/transparent"
                android:gravity="center"
                />
    
            <ImageButton
                android:id="@+id/ib_left"
                android:layout_width="48dp"
                android:layout_height="match_parent"
                android:layout_gravity="left"
                android:background="@android:color/transparent"
                android:gravity="center"
                android:src="@drawable/back"
                android:text="左边text"
                />
    
            <TextView
                android:id="@+id/tv_title"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_centerInParent="true"
                android:layout_gravity="center"
                android:gravity="center"
                />
    
    
            <TextView
                android:id="@+id/tv_right"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_alignParentRight="true"
                android:background="@null"
                android:gravity="center"
                />
    
            <ImageButton
                android:id="@+id/ib_right"
                android:layout_width="48dp"
                android:layout_height="match_parent"
                android:layout_alignParentRight="true"
                android:background="@android:color/transparent"
                android:gravity="center"
                android:visibility="gone"
                />
        </RelativeLayout>
    复制代码

    设计思路: 1.Toolbar必须使用Appcompat包,如果使用的普通的Acitivity就会出问题. 所以需要提供2套module 2.使用LinearLayout添加Toolbar,这里的Toolbar其实是一个RelativeLayout. 3.主要内容使用FrameLayout,可以扩展封装loadingView等.

    ##(3).ToolbarHelper: 只贴部分代码

    public abstract class ToolbarHelper {
      /**
         * 设置滑动Flag
         * @param viewId
         * @param flag
         * @return
         */
        public abstract boolean setScrollFlag(@IdRes int viewId, @AppBarLayout.LayoutParams.ScrollFlags int flag);
    
        /**
         * 获取AppBarLayout中的View
         * @param viewId
         * @param <V>
         * @return
         */
        public abstract <V extends View> V findAppBarView(@IdRes int viewId);
    
        /**
         * 获取AppBarLayout
         * @return
         */
        public abstract View getAppBarLayout();
    
        /**
         * 获取Toolbar
         * @return
         */
        public abstract Toolbar getToolbar();
    }
    复制代码

    ###具体实现:

    /**
     * @author jlanglang  2017/2/22 16:58
     * @版本 2.0
     * @Change
     */
    abstract class BaseToolBarHelperImpl extends ToolbarHelper {
        //ToolbarLayout的资源id
        int mToolbarLayout;
        Toolbar mToolbar;
        //通过UIView接口调用.
        UIView mUIView;
        //最外层View
        View mRootView;
        AppBarLayout mAppBarLayout;
        private boolean isMaterialDesign;
        //模仿ViewHolder机制.保存View.避免多次去findviewbyid同一个view
        private SparseArray<View> mViews;
    
        public BaseToolBarHelperImpl(@NonNull UIView uiView, View rootView, int toolbarLayout) {
            mUIView = uiView;
            mRootView = rootView;
            mToolbarLayout = toolbarLayout;
            mViews = new SparseArray<>();
            //初始化AppBarLayout
            mAppBarLayout = (AppBarLayout) mRootView.findViewById(R.id.app_bar);
            mAppBarLayout.removeAllViews();
            //将toolbarLayout添加到AppBarLayout中
            View inflate = LayoutInflater.from(mUIView.getContext()).inflate(mToolbarLayout, mAppBarLayout, true);
            mToolbar = (Toolbar) inflate.findViewById(R.id.tl_costom);
            if (mToolbar != null) {
                //传入的toolbarLayout中包含Toolbar,才设置.
                mUIView.setSupportActionBar(mToolbar);
            }
            //交给子类去初始化Toolbar
            initToolbar();
        }
        /*
        *初始化Toolbar
        */
        public abstract void initToolbar();
    
        /**
         * 从AppBarLayout中获取控件
         *
         * @param viewId
         * @param <V>
         * @return
         */
        @Nullable
        @Override
        public <V extends View> V findAppBarView(@IdRes int viewId) {
            View view = mViews.get(viewId);
            if (view == null && mAppBarLayout != null) {
                view = mAppBarLayout.findViewById(viewId);
                mViews.put(viewId, view);
            }
            return (V) view;
        }
    
        /**
         * 设置控件滑动效果
         * 
         * @param viewId 控件的资源id
         * @param flag 滑动flag
         * @return 是否设置成功
         */
        @Override
        public boolean setScrollFlag(@IdRes int viewId, @AppBarLayout.LayoutParams.ScrollFlags int flag) {
            View view = findAppBarView(viewId);
            if (view != null) {
                try {
                    AppBarLayout.LayoutParams layoutParams = (AppBarLayout.LayoutParams) view.getLayoutParams();
                    layoutParams.setScrollFlags(flag);
                } catch (ClassCastException e) {
                    e.printStackTrace();
                    return false;
                } catch (NullPointerException e) {
                    e.printStackTrace();
                    return false;
                }
            } else {
                return false;
            }
            return true;
        }
        @Nullable
        @Override
        public Toolbar getToolbar() {
            return mToolbar;
        }
    
    复制代码

    ###BaseAcitivity部分代码:

    package com.baozi.mvpdemo.base;
    /**
     * @author jlanglang  2016/1/5 9:42
     */
    public abstract class BaseActivity<T extends BasePresenter> extends AppCompatActivity
            implements BaseActivityView {
        protected T mPresenter;
        private SparseArray<View> mViews;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            mViews = new SparseArray<>();
            //创建presenter
            mPresenter = initPresenter();
            //绑定Activity
            mPresenter.onAttch(this);
            //创建ContentView
            View view = initView(LayoutInflater.from(this), savedInstanceState);
            super.setContentView(view);
            //初始化presenter
            mPresenter.onCreate();
            //延时加载数据.
            Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() {
                @Override
                public boolean queueIdle() {
                    mPresenter.loadData();
                    return false;
                }
            });
        }
    
        @Override
        public void setContentView(@LayoutRes int layoutResID) {
    
        }
    
        @Override
        public void setContentView(View view) {
    
        }
    
        @Override
        public void setContentView(View view, ViewGroup.LayoutParams params) {
    
        }
    
        /**
         * 通过viewId获取控件
         *
         * @param viewId 资源id
         * @return
         */
        @Override
        public <V extends View> V findView(@IdRes int viewId) {
            View view = mViews.get(viewId);
            if (view == null) {
                view = super.findViewById(viewId);
                mViews.put(viewId, view);
            }
            return (V) view;
        }
    
        @Override
        public View findViewById(@IdRes int id) {
            return findView(id);
        }
        /**
         * 初始化ContentView
         * 建议不要包含toolbar
         *
         * @param inflater
         * @param savedInstanceState
         * @return
         */
        @NonNull
        protected abstract View initView(@NonNull LayoutInflater inflater, Bundle savedInstanceState);
    
        /**
         * 子类实现Presenter,且必须继承BasePrensenter
         *
         * @return
         */
        protected abstract T initPresenter();
    
    }
    复制代码

    ###提供模版Activity:

    /**
     * 设置了默认的布局,默认的几个Toolbar模版,实现了ToolbarView,
     */
    public abstract class TempletActivity<T extends TempletPresenter> extends BaseActivity<T>
            implements ToolbarView {
        private ToolbarHelper mToolbarHelper;
        private View rootView;
    
        @NonNull
        @Override
        protected View initView(@NonNull LayoutInflater inflater, Bundle savedInstanceState) {
            ActionBar supportActionBar = getSupportActionBar();
            if (supportActionBar != null) {
                throw new IllegalStateException("pleace exends BaseActivity,TempletActivity theme must Noactionbar");
            }
            rootView = inflater.inflate(R.layout.activity_templet, null);
            //创建toolbar
            mToolbarHelper = getToolbarHelper();
            //ContentView容器
            FrameLayout contentGroup = (FrameLayout) rootView.findViewById(R.id.templet_content);
            //真正的创建contentView
            View contentView = initContentView(inflater, contentGroup, savedInstanceState);
            contentGroup.removeAllViews();
            contentGroup.addView(contentView);
            //交给Persenter去扩展
            mPresenter.wapperContentView(contentGroup);
            return rootView;
        }
        //继承的子类去实现
        @NonNull
        protected abstract View initContentView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState);
    
        /**
         * 默认使用base_toolbar
         * 如果不需要toolbar,请复写,并返回0.或者-1
         *
         * @return
         */
        @Override
        public int initToolbarLayout() {
            return ToolbarHelper.TOOLBAR_TEMPLET_DEFUATL;
        }
    
    
        /**
         * 此方法用于初始化菜单,其中menu参数就是即将要显示的Menu实例。 返回true则显示该menu,false 则不显示;
         * (只会在第一次初始化菜单时调用)
         */
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            if (!isMaterialDesign() || getToolbarHelper() == null) {
                return false;
            }
            return super.onCreateOptionsMenu(menu);
        }
    
        /**
         * 在onCreateOptionsMenu执行后,菜单被显示前调用;如果菜单已经被创建,则在菜单显示前被调用。 同样的,
         * 返回true则显示该menu,false 则不显示; (可以通过此方法动态的改变菜单的状态,比如加载不同的菜单等)
         */
        @Override
        public boolean onPrepareOptionsMenu(Menu menu) {
            return super.onPrepareOptionsMenu(menu);
        }
    
        /**
         * 显示menu的icon
         *
         * @param view
         * @param menu
         * @return
         */
        @Override
        protected boolean onPrepareOptionsPanel(View view, Menu menu) {
            if (menu != null) {
                if (menu.getClass().getSimpleName().equals("MenuBuilder")) {
                    try {
                        Method m = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE);
                        m.setAccessible(true);
                        m.invoke(menu, true);
                    } catch (Exception e) {
                        Log.e(getClass().getSimpleName(), "onMenuOpened...unable to set icons for overflow menu", e);
                    }
                }
            }
            return super.onPrepareOptionsPanel(view, menu);
        }
    
        /**
         * 每次菜单被关闭时调用.(菜单被关闭有三种情形,menu按钮被再次点击、back按钮被点击或者用户选择了某一个菜单项)
         */
        @Override
        public void onOptionsMenuClosed(Menu menu) {
            super.onOptionsMenuClosed(menu);
        }
    
        /**
         * 菜单项被点击时调用,也就是菜单项的监听方法。
         * 通过这几个方法,可以得知,对于Activity,同一时间只能显示和监听一个Menu 对象.
         */
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            return super.onOptionsItemSelected(item);
        }
    
    
        @Override
        public TempletActivity getActivity() {
            return this;
        }
    
        /**
         * 切换MaterialDesign风格.
         *
         * @param isMaterialDesign
         */
        @Override
        public void setMaterialDesignEnabled(boolean isMaterialDesign) {
            getToolbarHelper().setMaterialDesignEnabled(isMaterialDesign);
        }
    
        @Override
        public boolean isMaterialDesign() {
            return false;
        }
    
        /**
         * 如果设置的主题不是NoActionBar或者initToolbar()返回是0,则返回null.
         *
         * @return mToolbar 可能为null.
         */
        public Toolbar getToolbar() {
            return getToolbarHelper().getToolbar();
        }
    
        /**
         * @return
         */
        @Override
        public ToolbarHelper getToolbarHelper() {
            if (mToolbarHelper == null) {
                mToolbarHelper = ToolbarHelper.Create(this, rootView, initToolbarLayout());
            }
            return mToolbarHelper;
        }
    
        @Override
        protected abstract T initPresenter();
    }
    
    复制代码

    ###使用例子:

    public class MainAcitivity extends TempletActivity<TempletPresenter>  {
        @NonNull
        @Override
        protected View initContentView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
            getToolbarHelper().setTitle("首页");
            getToolbarHelper().setRightText("213", null);
            return inflater.inflate(R.layout.activity_main, null);
        }
    
        //这里偷懒,就不去单独写个PresenterImpl了
        @Override
        protected TempletPresenter initPresenter() {
            //需要继承
            return new TempletPresenter<MainAcitivityContract.View>() {
                @Override
                public void onCreate() {
                    //设置滑动效果
                     mView.getToolbarHelper().setScrollFlag(R.id.tl_costom, AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL|
                            AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS);
                }
    
                @Override
                public void loadData() {
    
                }
            };
        }
        //重写该方法,设置ToolbarLayout
        @Override
        public int initToolbarLayout() {
            return ToolbarHelper.TOOLBAR_TEMPLET_DEFUATL;
        }
    }
    复制代码

    ##(4).Appcompat风格的要点:

    1.如果自定义页面,或者模版的样式不符合你的要求,可以直接继承BaseActivity,BaseFragment 实现initView(@NonNull LayoutInflater inflater, Bundle savedInstanceState);方法 该方法相当于setContentView(),onCreateView(); 或者接着往下看,有惊喜。。

    2.由于BaseActivity,BaseFragment都继承UIVIew. 通过initView()方法来初始化View 所以两者之间切换,改动可以非常的小.

    3.TempletActivity持有ToolbarHelper的实现类,并且实现了ToolbarView.UIView, Presenter可以通过继承了ToolbarView.UIViewView来操作TempletActivity.

    4.BaseActivityBaseFragment,属于基类,无需关系Toolbar的情况.也就不需要ToolbarHelper

    5.通过重写initToolbarLayout()就能设置不同样式的Toolbar,如果样式满足不了需求,可以直接继承BaseActivity,BaseFragment来自定义

    6.可以通过ToolbarHelper获取mApplayout,进行增删子View.以及设置属性.

    7.可以通过ToolbarHelperfindAppBarView(id)获取mApplayout中的子控件.

    8.可以通过ToolbarHelpersetScrollFlag(id,flag)设置mApplayout中子控件的滑动效果. 9.可以自定义toolbarlayout,只不过Toolbar的id要求命名为tl_costom,否则无法获取的Toolbar当然,也可以随便起名字.不过就得手动做一些事了,通过findAppBarView(id)获取到Toolbar,然后setSupportActionBar() ##(5)默认的四种样式: 1.带TabLayout的Toolbar

    2.啥也没有的Toolbar

    3.自定义了一些VIew的ToolBar

    4.可以通过滑动上推折叠的Toolbar

    缺点:对AppbarLayout的一些设置只能通过代码来设定了。

    #2.摆脱butterknife

    在实践组件化的时候,发现butterknife不好用,moudle里面找不到view。 后来看git上的说明,把R改成R2.发现有点蛋疼,不是很好用了,干脆弃用算了吧。

    最后重写了findviewbyId(),通过泛型,减少强转操作。不用每次都去强转了。不过得自己知道对应的控件id是什么类型了,这个不可能不知道吧。

    部分代码:

    public abstract class BaseActivity<T extends BasePresenter> extends AppCompatActivity 
      implements BaseActivityView {
        private SparseArray<View> mViews;
         * 通过viewId获取控件
         *
         * @param viewId 资源id
         * @return
         */
        @Override
        public <V extends View> V findView(@IdRes int viewId) {
            View view = mViews.get(viewId);
            if (view == null) {
                view = super.findViewById(viewId);
                mViews.put(viewId, view);
            }
            return (V) view;
        }
    
        @Override
        public View findViewById(@IdRes int id) {
            return findView(id);
        }
    复制代码

    自己写findviewbyid吧。。用工具生成也可以的。

    #3.普通风格 普通风格的具体实现代码就不贴了,这文已经很长了,哈哈.有兴趣直接github看代码好了.

    #4.Fragment的Toolbar封装 具体实现和activity差不多,因为我一直以来的设想就是改很少的代码就能两者切换. 这里就不贴了(其实是我还没写.),陆续更新. 如果你看我这一系列文章,会发现,最开始的封装结构和现在的有很大的差别了.为什么不去更新改掉以前的 我觉得这是成长的记录吧.哈哈

    #再附上githubdemo地址,时不时就更新 mvpDemo


    您的喜欢与回复是我最大的动力-_-

    展开全文
  • Android之ToolBar项目封装,踩坑过河

    千次阅读 2016-06-23 22:50:37
    Toolbar封装

    欢迎各位访问的博客,博客地址

    概述

    继承关系:

    java.lang.Object
       ↳    android.view.View
           ↳    android.view.ViewGroup
               ↳    android.widget.Toolbar

    其实toolbar就是一个封装好的ViewGroup,其主要五大部分对应的子View如下:

    //菜单,ActionMenuView也是个ViewGroup
    private ActionMenuView mMenuView;
    //主标题
    private TextView mTitleTextView;
    //副标题
    private TextView mSubtitleTextView;
    //导航按钮
    private ImageButton mNavButtonView;
    //Logo图标
    private ImageView mLogoView;

    看下图,比较清晰:

    ToolBar图解

    项目封装

    配置theme

    为了适配5.0之后安卓的设计,做起statusbar的颜色适配

    <style name="AppTheme" parent="Theme.AppCompat.Light.Theme.AppCompat.Light.NoActionBar">
            <item name="colorPrimaryDark">@color/main_dark</item>
            <item name="colorPrimary">@color/main</item>
            <item name="colorAccent">@color/strong</item>
            <item name="android:textColorPrimary">@android:color/white</item>
            <item name="android:actionBarSize">@dimen/nav_bar_height</item>
        </style>

    这里注意下,主题使用的parent是Theme.AppCompat.Light.NoActionBar,当然有些项目中配全局Theme时候还是用的Theme.AppCompat.Light.DarkActionBar,这时候需要改成没有ActionBar的主题,这里可以直接改成Theme.AppCompat.Light.NoActionBar,但是有些项目里如果想有些地方使用Actionbar有些地方使用Toolbar(当然很少。。)可以这样配一下即可:

    <style name="AppTheme.NoActionBar">
            <item name="windowActionBar">false</item>
            <item name="windowNoTitle">true</item>
    </style>

    然后在需要使用Toolbar的activity里给他配上这样的theme即可:

    <activity
            android:name=".ui.activity.MainTabBarActivity"
            android:label="@string/app_name"
            android:screenOrientation="portrait"
            android:launchMode="singleTask"
            android:theme="@style/AppTheme.NoActionBar"
            android:windowSoftInputMode="stateHidden">
    </activity>

    关于theme中几个color字段的描述看谷歌官方图,如下:

    几种color

    或者看谷歌文档(自备梯子):Material Theme

    由于我们项目里设定了toobar的高度,这里指定了actionBarSize,然后通过设置toolbar高度为这个值;

    布局代码

    由于项目中toolbar归属于fragment管理,所以这里是将toolbar封装在fragment中处理了,这里通过各个fragment的xml添加<include layout="@layout/toolbar_layout"/>

    toolbar_layout.xml如下:

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.v7.widget.Toolbar
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        android:elevation="1dp">
        <TextView
            android:id="@+id/nav_left_text"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:drawableLeft="@drawable/nav_back_light"
            android:drawableStart="@drawable/nav_back_light"
            android:layout_gravity = "start"
            android:gravity="center"
            android:minWidth="50dp"
            android:text="返回"
            android:textColor="@android:color/white"
            android:textSize="@dimen/font_title"
            android:visibility="gone"/>
        <TextView
            android:id="@+id/center_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity = "center"
            android:textColor="@android:color/white"
            android:textSize="@dimen/font_large"
            tools:text="标题" />
        <TextView
            android:id="@+id/nav_right_text_button"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_gravity = "end"
            android:gravity="center"
            android:minWidth="50dp"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:textColor="@color/color_999"
            android:textSize="@dimen/font_normal"
            android:visibility="gone" />
    </android.support.v7.widget.Toolbar>

    toolbar上的东西被我分成五种:

    1. navigationicon:通过.setNavigationIcon去处理
    2. logo:通过setlogo
    3. title与subtitle:通过.setTitle与setSubtitle去处理
    4. 自定义部分:这里也分成左中右三个部分,可以看上面布局文件,通过标签android:layout_gravity 来指定位置,这里有坑,自定义部分布局最左边有间隙,如果要去掉,可以设置:contentInset 这个标签去除。
    5. menu:menu的显示方式可以自行设置

    这样来看,基本所有的需求都能满足了;

    fragment中抽象封装:

    这里要看各个项目需求,由于我们公司项目中对最右边图标灵活度要求并不高,我一般使用menu就可以解决了,如果menu不能满足你,完全可以使用自定义部分中的“右部分”。

    下面进入封装,在baseFragment中做了如下封装,项目中使用的是JakeWharton的注入框架butterknife链接

    1. 首先注入toolbar及自定义部分中除最右边图标的控件,因为最右边图标我们项目中一般menu就够用了:
     @BindView(R.id.toolbar)
     protected Toolbar mToolBar;
     @BindView(R.id.center_title)
     TextView mCenterTitle;
     @BindView(R.id.nav_left_text)
     TextView mNavLeftText;
    1. 然后在初始化fragment视图时候将mToolBar、mCenterTitle、mNavLeftText传给其子fragment进行定制,这三个控件传递出去后完全可以定制navigationicon、logo、title与subtitle、自定义部分这四个部分。以下代码中的initview和popFragment是我封装好的在fragment的OncreateView时候调用的,详细封装请看:浅谈Activity,Fragment模块化封装
    @Override
    protected void initView(View view, Bundle savedInstanceState) {
          initToolBar(mToolBar, mCenterTitle, mNavLeftText);
    }
    protected void initToolBar(Toolbar toolbar, TextView centerTitle, TextView navLeftText){
            ((AppCompatActivity)getActivity()).setSupportActionBar(toolbar);
            ((AppCompatActivity)getActivity()).getSupportActionBar().setDisplayShowTitleEnabled(false);
    toolbar.setNavigationIcon(R.drawable.nav_back_light);
    toolbar.setNavigationOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    popFragment();
                }
            });
        }

    这里有个坑:

    ((AppCompatActivity)getActivity()).getSupportActionBar().setDisplayShowTitleEnabled(false);

    必须设置这个,不然默认的title一直在,即使你设置了toolbar.settitle(“xxoo”)。。。

    这里做了一件事,给navigationButton导航按钮做了个监听,pop出当前这个fragment出栈

    1. 还剩最后一个东西没有定制:menu

    这个很简单,不过也要注意下,必须在fragment中设置菜单,一定要先设置:

    setHasOptionsMenu(true);

    关于源码,可以去看下,然后处理方式很简单了:

    @Override
        public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
            inflater.inflate(R.menu.search, menu);
            super.onCreateOptionsMenu(menu, inflater);
        }

    这里也有个坑:如果你没有设置:

    ((AppCompatActivity)getActivity()).setSupportActionBar(toolbar);

    那么onCreateOptionsMenu 并不会被回调。

    1. 最后做下menu的监听即可:
    toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
                @Override
                public boolean onMenuItemClick(MenuItem item) {
                    switch (item.getItemId()){
                        }
                    return true;
                }
            });

    总结:

    Toolbar是android5.0之后出现的MD设计风的控件,支持5.0之后的elevation特性,相比较Actionbar具有高度自定义的特性,因为其本身是一个ViewGroup内部布局完全自由处理,这样大大扩展了其自由定制性,不多说,赶紧开始替换Actionbar吧!

    具体代码请看我的github:Android练习小项目

    展开全文
  • Toolbar简单封装

    2018-12-27 17:57:03
    对Toolbar进行封装,为后续使用做铺垫,作者认为常见的对Toolbar封装的有2中方法。 第一种在BaseActivity中封装,这种封装不足之处在于BaseActivity会比较复杂,耦合性高,不利于后期维护,BaseActivity一般封装语言...
  • ToolBar封装

    千次下载 热门讨论 2015-06-12 23:54:03
    ToolBar封装,使代码步重复,快捷开发
  • Toolbar完整封装

    千次阅读 2016-03-17 22:20:44
    Toolbar封装使用
  • ToolBar封装

    2017-05-19 11:55:38
    ToolBar封装 在开发app过程中,切换不同的fragment经常需要显示不同的toolbar,为了提高代码的质量和编程的效率,需要对toolbar进行统一的封装; 首先toolbar最常用的习惯的在xml中实现 xmlns
  • 封装Toolbar到BaseActivity

    千次阅读 2018-01-17 17:02:00
    Android 5.0的时候Google用Toolbar替代了ActionBar,而...一个应用的几乎所有界面都需要头部app bar,为了能够方便各个界面方便使用,统一管理,这里把toolBar封装到BaseActivity中。 1,定义一个toolbar_l...
  • toolbar封装

    热门讨论 2016-07-07 15:01:28
    Android 5.0的时候就用Toolbar替代了ActionBar,而ActionBarActivity又被AppCompatActivity替代...一个应用的几乎所有界面都需要头部app bar,为了能够方便各个界面方便使用,统一管理,这里就来对toolBar进行简单的封装
  • ToolBar项目封装使用

    2018-06-16 01:03:20
    概述 继承关系: java.lang.Object ↳ android.view.View ...复制代码其实toolbar就是一个封装好的ViewGroup,其主要五大部分对应的子View如下: //菜单,ActionMenuView也是个ViewGroup private...
  • Android ToolBar封装

    千次阅读 2017-04-08 14:03:24
    标题文字”类型的普通toolbar,也有“返回图标-标题文字-菜单图标”和“文字-标题文字-文字”这种类型的,也就是说,Toolbar的左边和右边都有可能是文字或者图标,而中间一般都是标题,所以寻思着封装toolbar,使...
  • android Toolbar封装

    千次阅读 2016-07-07 16:42:35
    你们还在用自定义标题栏吗,你们还在为actionbar标题不能居中不灵活苦恼吗,Toolbar一切问题都帮你搞定Toolbar 标题居中 编写带有Toolbar的基类 Toolbar 标题居中 Toolbar的标题是默认左对齐的,不过Toolbar继承...
  • 如图:有关ToolBar的详细介绍: Frist Blood Double Kill接下来介绍我们的ToolBar:首先看attrs.xml文件,这里定义了几个属性: <resources> <declare-styleable name="CustomToolBar"> <attr name="is
  •  谷歌写的toolbar比较好,所以我们其实是没有必要自己去写个布局来替代toolbar,但是toolbar封装又不是很好用,我封装的主要有一下几个方面。 1.更改状态栏颜色。2. 自定义activity进入或者退...
  • Toolbar封装及使用

    2016-12-12 19:37:24
    所以要对Toolbar进行封装. 代码框架 程序效果(这里进行简单的设置) 布局文件 主窗体中没有进行编写 ToolbarActivity的xml文件代码 xml version="1.0" encoding="utf-8"?> ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 412
精华内容 164
关键字:

toolbar封装