钉钉组织架构android_android钉钉组织架构 - CSDN
  • 现在基本上很多的企业都会使用钉钉,然后细心地人会看到钉钉组织架构功能。在联系人中放着一个可以展开的公司,下面有组织架构和自己所在的部门。 现在我们产品经理说我们项目中也要加入组织架构功能,而且给个...

    现在基本上很多的企业都会使用钉钉,然后细心地人会看到钉钉组织架构功能。在联系人中放着一个可以展开的公司,下面有组织架构和自己所在的部门。


    现在我们产品经理说我们项目中也要加入组织架构功能,而且给个变态的需求就是如果一个人在多家公司呢。那就得有多个组织架构了。

    这个需求你可能一下就会想到用ExpandListView能解决所有问题。可以呢,如果他本身就存在在ExpandListView的header或者ListView的header中,你直接放入ExpandListView确定不影响滑动的时候的性能吗,在某些机型上滑动的时候会流畅吗。答案是:不允许这样嵌套

    于是我就想到一个办法,就是动态的去生成item,并给每一个item加上点击监听,还有变态需求就是如果存在一个人多家公司,那么就要双层item并进行点击监听。

    下面是我做的效果,就是通过动态添加和动态监听。


    代码分析:

    //点击展开组织架构事件
            RelativeLayout rl__organization_head[] = new RelativeLayout[organizationList.size()];
            //箭头m_
            final ImageView iv_organization_arrow[] = new ImageView[organizationList.size()];
            //组织架构的body
            final LinearLayout ll_organization_body[] = new LinearLayout[organizationList.size()];
    
            for (int j = 0; j < organizationList.size(); j++) {
                //初始化header(公司)部分
                organization_header_view = LayoutInflater.from(mContext).inflate(R.layout.item_organization_header, null);
                tv_organization_header_text = (TextView) organization_header_view.findViewById(R.id.tv_organizational_organization);
                rl__organization_head[j] = (RelativeLayout) organization_header_view.findViewById(R.id.rl__organization_head);
                iv_organization_arrow[j] = (ImageView) organization_header_view.findViewById(R.id.iv_organization_arrow);
                ll_organization_body[j] = (LinearLayout) organization_header_view.findViewById(R.id.ll_organization_body);
    
                tv_organization_header_text.setText(organizationList.get(j).getOrganizationName());
    
                //组织架构body(部门)-name
                TextView tv_organization_body_text[][] = new TextView[organizationList.size()][organizationList.get(j).getOrganizations().size()];
    
                for (int i = 0; i < organizationList.get(j).getOrganizations().size(); i++) {
                    //初始化body(部门)部分
                    insitution_body_view = LayoutInflater.from(mContext).inflate(R.layout.item_organization_body, null);
                    tv_organization_body_text[j][i] = (TextView) insitution_body_view.findViewById(R.id.tv_organization_body_text);
                    view_organization_body_text_line = insitution_body_view.findViewById(R.id.view_organization_body_text_line);
    
                    if (i == 0) {
                        view_organization_body_text_line.setVisibility(View.GONE);
                    }
                    tv_organization_body_text[j][i].setText(organizationList.get(j).getOrganizations().get(i).getOrganizationName());
                    ll_organization_body[j].addView(insitution_body_view);
    
                    final int finalJ1 = j;
                    final int finalI = i;
                    tv_organization_body_text[j][i].setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            String departmentName = organizationList.get(finalJ1).getOrganizations().get(finalI).getOrganizationName();
                            String departmentId = organizationList.get(finalJ1).getOrganizations().get(finalI).getOrganizationId();
                            Intent intent = new Intent(getActivity(), OrganizationActivity.class);
                            intent.putExtra("organizationId", organizationList.get(finalJ1).getOrganizationId());
                            intent.putExtra("organizationName", organizationList.get(finalJ1).getOrganizationName());
                            if (finalI > 0) {
                                intent.putExtra("nextFlag", "next");
                                intent.putExtra("firstIntent", "first");
                            }
                            intent.putExtra("departmentId", departmentId);
                            intent.putExtra("departmentName", departmentName);
                            startActivity(intent);
                        }
                    });
                }
    
                //默认关闭组织架构
                ll_organization_body[j].setVisibility(View.GONE);
                iv_organization_arrow[j].setBackgroundResource(R.drawable.cell_header_down);
    
                ll_organization_header.addView(organization_header_view);
    
                final int finalJ = j;
                rl__organization_head[j].setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (isShowFra) {
                            iv_organization_arrow[finalJ].setBackgroundResource(R.drawable.cell_header_up);
                            isShowFra = false;
                            ll_organization_body[finalJ].setVisibility(View.VISIBLE);
                        } else {
                            iv_organization_arrow[finalJ].setBackgroundResource(R.drawable.cell_header_down);
                            isShowFra = true;
                            ll_organization_body[finalJ].setVisibility(View.GONE);
                        }
                    }
                });
            }
    
        }
    有道行的一眼就能看出怎么回事,对我用的数组去处理点击监听问题。类似仿写一个简单的ExpandListView,对绘制和滑动没有任何影响,占用内存也不大。

    就是不断的addView动态将item addView到第二层,然后再将第二层动态addView到第一层,以双重for循环处理。organizationList.size()就可以生成多少个公司的组织架构。是不是类似与ExpandListView了,这里为什么不用ExpandListView,是因为这个组件要放在ExpandListView的header里面,至少这样也不会影响ExpandListView的性能。

    至于如果只要一个公司呢,organizationList.size() = 1或者拆分出只要一层for循环就行了。精华部分就是怎么去给每一个item添加点击监听事件,这个解决了,多少层都没有问题,一个大树都没有问题。


    补充组织架构里面部门的写法,也是简单一级循环监听的方式来处理部门列表的显示,当然也可以用listview也可以做,只是需要对数据处理

    /**
         * 处理部门显示的ui
         */
        private void handleDepartmentUi() {
            if (departmentData != null && departmentData.size() > 0) {
                for (int i = 0; i < departmentData.size(); i++) {
                    department_item_view = LayoutInflater.from(this).inflate(R.layout.item_organization_department, null);
                    rl_department_item = (RelativeLayout) department_item_view.findViewById(R.id.rl_organization_department_item);
                    tv_department_name = (TextView) department_item_view.findViewById(R.id.tv_organization_department_name);
                    tv_department_count = (TextView) department_item_view.findViewById(R.id.tv_organization_department_count);
    
                    tv_department_name.setText(departmentData.get(i).getOrganizationName());
    //                tv_department_count.setText("100");
                    //统一监听每个item
                    rl_department_item.setOnClickListener(clickListener);
                    rl_department_item.setTag(i);
    
                    ll_department_item.addView(department_item_view);
                }
            } else {
                ll_department_item.setVisibility(View.GONE);
                view_department_line_1.setVisibility(View.GONE);
            }
        }
    
        /**
         * 处理组织架构item的监听
         */
        private View.OnClickListener clickListener = new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int id = (Integer) v.getTag();
                Intent intent = new Intent(DepartmentActivity.this, OrganizationActivity.class);
                intent.putExtra("departmentName", departmentData.get(id).getOrganizationName());
                intent.putExtra("departmentId", departmentData.get(id).getOrganizationId());
                intent.putExtra("organizationId", organizationId);
                intent.putExtra("organizationName", organizationName);
                intent.putExtra("nextFlag", "next");
                startActivityForResult(intent, CLOSEREQUESTCODE);
            }
        };

    这里就是我简单处理部门的方式,其实listview也可以做的,但是要看需求

    不知道是否是你们所需要的,还是其他部分,可以提问




    展开全文
  • 仿钉钉组织架构功能

    2020-07-30 23:30:10
    仿钉钉组织架构通讯录功能,实现方式由fragment的回退栈实现,常见的同一个标题头部,内容不一致的分布操作或是展示皆可参考
  • 仿钉钉组织架构通讯录功能,实现方式由fragment的回退栈实现,常见的同一个标题头部,内容不一致的分布操作或是展示皆可参考
  • 前言 开发中我们会遇到同一个标题头部,类似注册或重置密码时的分步操作,...本文所说的仿钉钉组织架构功能就是基于这个来实现的,Fragment回退栈具体相关的知识可自行去了解,本文只作简单介绍。 相关方法 ...

    前言

    开发中我们会遇到同一个标题头部,类似注册或重置密码时的分步操作,标题栏都是相同的,只是内容部分的输入框有所不同,可能会想到直接写多个Activity来实现,但是这样的话内存消耗上面就多了,这个时候我们就可以利用Fragment的回退栈来实现这个功能。本文所说的仿钉钉的组织架构功能就是基于这个来实现的,Fragment回退栈具体相关的知识可自行去了解,本文只作简单介绍。

    相关方法

    • addToBackStack(String tag);//将Fragment加入回退栈,tag为此Fragment在回退栈中的唯一标识
    • getBackStackEntryCount();//获取回退栈Fragment的总个数
    • getBackStackEntryAt(int index);//获取回退栈中某个Fragment
    • popBackStack();//将回退栈中栈顶的Fragment出栈
    • popBackStackImmediate(String tag, int flags);
      tag为null,flags为0时,弹出回退栈中最上层的那个fragment,flags为1时,弹出回退栈中所有fragment。
      tag不为null,flags为0时,弹出该fragment以上的Fragment,如果是1,弹出该fragment(包括该fragment)以
      上的fragment。
    • fullScroll(HorizontalScrollView.FOCUS_RIGHT);//控制HorizontalScrollView滚动到最右边,延时调用

    效果图

    效果展示

    实现思路

    1.可以选择在加入回退栈的时候传入当前部门的名称作为tag

    private void initDeptFragment(ArrayList<DeptListBean.DataBean.DepartmentListBean> mDeptList,
                                      ArrayList<String> mDeptUserList, String tag) {
            Fragment mDeptFragment = new DeptFragment();
            FragmentManager manager = getActivity().getSupportFragmentManager();
            Bundle bundle = new Bundle();
            bundle.putParcelableArrayList("deptList", mDeptList);
            bundle.putStringArrayList("deptUserList", mDeptUserList);
            mDeptFragment.setArguments(bundle);
            manager.beginTransaction()
                    .replace(R.id.dept_content, mDeptFragment)
                    .addToBackStack(tag)
                    .commit();
        }

    2.点击导航tab时,通过这个tag找到Fragment,然后再进行相关操作

     mNavView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        int currentIndex = 0;
    
                        if (mNavView.getTag() != null) {
                            currentIndex = (int) mNavView.getTag();
                        }
    
                        if (currentIndex == 0) {//点击回到一级部门,清除所有回退栈
                            if (mNavNameList.size() > 1) {
                                getActivity().getSupportFragmentManager().popBackStackImmediate(mNavNameList.get(1), FragmentManager.POP_BACK_STACK_INCLUSIVE);
                            }
                        } else {
                            getActivity().getSupportFragmentManager().popBackStackImmediate(mNavNameList.get(currentIndex), 0);
                        }
    
                    }
                });

    3.动态添加导航tab后,控制滚动到最右边

    mHsvNav.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        mHsvNav.fullScroll(HorizontalScrollView.FOCUS_RIGHT); //方法不能直接被调用,可能会不生效,需先加入消息队列等待调用
                    }
                }, 100L);

    4.返回处理,根据回退栈Fragment数量决定是清除栈顶Fragment还是退出Activity

    mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (getActivity().getSupportFragmentManager().getBackStackEntryCount() > 0) {
                        getActivity().getSupportFragmentManager().popBackStack();
                    } else {
                        getActivity().finish();
                    }
                }
            });

    小弟理解可能有所偏差,欢迎各位对之中出现的错误或是代码的质量优化,不吝赐教,谢谢!

    Demo下载


    展开全文
  • 安卓仿制钉钉通讯录,显示部门和联系人,界面头部显示对应的公司和部门,同时显示对应部门的人员。点击头部同时支持回退部门
  • 项目开发,要求一个类似于钉钉审核的东西,如下 挺简单的一个东西,去网上找了一下,发现没有现成的,就想着自己做一个了 大概说一下思路,其实比较简单 1.这个审核列表可以提取为一个有字的view和右边的一个...

    项目开发,要求一个类似于钉钉审核的东西,如下


    挺简单的一个东西,去网上找了一下,发现没有现成的,就想着自己做一个了

    大概说一下思路,其实比较简单

    1.这个审核列表可以提取为一个有字的view和右边的一个箭头这样的一个layout组成的,最后一个为一个加号的图片

    2.点击加号可以添加新的项,点击项目,可以删除当前

    3.颜色是随机的

    其实这就是一个gridview就可以实现的简单ui了(其实还可以用recylerview,会更加简单好看,需要的可以自己尝试)

    首先一个简单的gridview

    <GridView
            android:id="@+id/gv_audit"
            android:layout_width="match_parent"
            android:layout_height="200dp"
            android:numColumns="5"
            android:horizontalSpacing="3dp"
            android:verticalSpacing="5dp">
    
        </GridView>
    参数意义就不讲了,都能看懂吧

    然后就是一个gridview的适配器

    public class AuditGridAdapter extends BaseAdapter {
    
        private LayoutInflater inflater;
        private boolean shape;
        private Context context;
        private List<NameEntity> nameList = new ArrayList<>();
    
    
        public boolean isShape() {
            return shape;
        }
    
        public void setShape(boolean shape) {
            this.shape = shape;
        }
    
        public AuditGridAdapter(Context context, List<NameEntity> nameList) {
            this.context = context;
            this.nameList = nameList;
            inflater = LayoutInflater.from(context);
        }
    
        public int getCount() {
            if (nameList.size() == 9) {
                return 9;
            }
            return (nameList.size() + 1);
        }
    
        public Object getItem(int arg0) {
            return null;
        }
    
        public long getItemId(int arg0) {
            return 0;
        }
    
        public View getView(int position, View convertView, ViewGroup parent) {
            convertView = inflater.inflate(R.layout.item_audit, parent, false);
            TextView tvName = (TextView) convertView.findViewById(R.id.tvAuditName);
            ImageView ivArrow = (ImageView) convertView.findViewById(R.id.ivAuditArrow);
            if (position == nameList.size()) {
                tvName.setBackground(ContextCompat.getDrawable(context, R.mipmap.more));
                ivArrow.setVisibility(View.INVISIBLE);
                tvName.setText("");
                if (position == 9) {
                    tvName.setVisibility(View.INVISIBLE);
                }
            } else {
                NameEntity name = nameList.get(position);
                if (position == 8) {
                    ivArrow.setVisibility(View.INVISIBLE);
                } else {
                    ivArrow.setVisibility(View.VISIBLE);
                }
                tvName.setBackground(ContextCompat.getDrawable(context, name.getColor()));
                tvName.setText(name.getName());
            }
            return convertView;
        }
    
    }

    挨个看,首先是getcount( )方法

     public int getCount() {
            if (nameList.size() == 9) {
                return 9;
            }
            return (nameList.size() + 1);
        }
    重写了这个方法,是为了最后加号的实现,判断是否为9是为了给审核列表设置一个上限,我这里最多只能有九个项,+1是为了给加号留一个位置,做过照片上传之类的东西的,应该都明白是什么意思吧

    然后是getview方法,这里我没有用holder,恩,不是不能用,因为懒而已。。。这只是个demo

    if (position == nameList.size()) {
                tvName.setBackground(ContextCompat.getDrawable(context, R.mipmap.more));
                ivArrow.setVisibility(View.INVISIBLE);
                tvName.setText("");
                if (position == 9) {
                    tvName.setVisibility(View.INVISIBLE);
                }
            } else {
                NameEntity name = nameList.get(position);
                if (position == 8) {
                    ivArrow.setVisibility(View.INVISIBLE);
                } else {
                    ivArrow.setVisibility(View.VISIBLE);
                }
                tvName.setBackground(ContextCompat.getDrawable(context, name.getColor()));
                tvName.setText(name.getName());
            }

    注意上面的这个方法,当position = nameList.size()的时候,意思是,当前是审核列表的最后一项,给最后一项设置背景图片为那个加号,设置右边的箭头为不可见,设置字为空,同时,如果position=9,即,现在已经到了最大值,就不再显示加号了

    else

    就设置文字啊,颜色啊什么的

    我这里用了一个NameEntity,里面就两个参数

     */
    public class NameEntity {
        private String name;
        private int color;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getColor() {
            return color;
        }
    
        public void setColor(int color) {
            this.color = color;
        }
    }

    一个颜色,一个文字
    好,下面就是使用方法了

    public class AuditTestActivity extends AppCompatActivity {
    
        private GridView gvAudit;
        private AuditGridAdapter adapter;
        private List<NameEntity> namelist = new ArrayList<>();
        private String[] nameArray = new String[]{"张三", "李四", "王五", "巴拉巴", "舒克", "贝塔", "心相印", "stanny", "安卓", "java"};
        private int[] colorArray = new int[]{R.mipmap.circle1, R.mipmap.circle2, R.mipmap.circle3, R.mipmap.circle4, R.mipmap.circle5, R.mipmap.circle6};
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_audit_test);
    
            gvAudit = (GridView) findViewById(R.id.gv_audit);
            adapter = new AuditGridAdapter(this, namelist);
            gvAudit.setSelector(new ColorDrawable(Color.TRANSPARENT));
            gvAudit.setAdapter(adapter);
            gvAudit.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    if (position == namelist.size()) {
                        NameEntity name = new NameEntity();
                        name.setName(nameArray[(int) (Math.random() * 10)]);
                        name.setColor(colorArray[(int) (Math.random() * 6)]);
                        namelist.add(name);
                        adapter.notifyDataSetChanged();
                    } else {
                        namelist.remove(position);
                        adapter.notifyDataSetChanged();
                    }
                }
            });
        }
    }

    我这里初始化了两个数组,分别是文字数组和背景图片id数组

    然后最重要的设置item点击事件

    如果点击的position=nameList.size()

    即我现在点的是最后一个加号,就添加一个数据进去,刷新列表

    否则,就移除当前点击的那个数据

    听简单的实现,效果如下



    展开全文
  • 摘要:近期项目中需要实现组织架构图,搜索了大半天网上也没有体验良好、功能能够满足项目需要的demo,无奈只能自己写。实现思路是通过自定义view的方式,通过计算每一项的开始坐标来在canvas上定位,通过...

    摘要:近期项目中需要实现组织架构图,搜索了大半天网上也没有体验良好、功能能够满足项目需要的demo,无奈只能自己写。实现思路是通过自定义view的方式,通过计算每一项的开始坐标来在canvas上定位,通过onTouchEvent监听手势的移动和缩放在进行画布的缩放和位移,实现项目需求。

     

    需求

    1. 支持横竖屏切换
    2. 支持选中状态切换
    3. item项 字体颜色、背景颜色、选中颜色、字体大小、横向间距、纵向间距(不考虑连线)自定义
    4. 每行的高度取决于改行中的内容最大值,内容居中显示
    5. 支持手势滑动、缩放
    6. 缩放比例最大值,最小值

    实现思路

    首先数据源必须是树形结构,数据源只有一个跟结点,每个节点都可能有多个子节点,以此类推。

    • 对数据源进行遍历,计算出最大行数和最大列数,目的是计算出所画布局的高drawHeight宽drawWidth
    • 遍历解析出每个节点所在的行数和列数,方便计算节点的起始位置sX sY,这样就可以根据该行的行高直接画出给item项
    • 第一种情况,如果显示内容的高宽都比view可视范围高宽小的话滑动是不考虑滑动和缩放
    • 第二种情况,如果高宽其中有一项的值大于view可视范围的实际高宽,则计算出能全部看到范围的最小缩放比例,用于手动缩放时无限缩小的限制
    • 左上角是原点(0,0),画的起点也是从原点开始,所以默认进来如果是上面第二种情况 则需要将画布canvas移动到中间位置,所以translateX translateY 至关重要
    • 点击事件在onTouchEvent中实现,获取点击屏幕的x、y坐标遍历数据源跟所有item项所占区域坐标进行比较,判断是否是该项的选中,通过接口回调传递事件

    实现步骤

    属性定义

    <declare-styleable name="OrgMapView" >
            <!--绘制项的宽度-->
            <attr name="item_width" format="dimension|reference" />
            <!--item的高度-->
            <attr name="item_height" format="dimension|reference" />
            <!--item 横向间距-->
            <attr name="item_margin_h" format="dimension|reference" />
            <!--item 纵向间距-->
            <attr name="item_margin_v" format="dimension|reference" />
            <!--item 内容间距-纵向-->
            <attr name="item_padding_v" format="dimension|reference" />
            <attr name="item_line1_margin_top" format="dimension|reference" />
            <attr name="item_margin_to_line" format="dimension|reference" />
            <!--item 圆角大小-->
            <attr name="item_raidus" format="dimension|reference" />
            <!--item 默认背景色-->
            <attr name="item_bgcolor" format="color|reference" />
            <!--item 选中背景色-->
            <attr name="item_bgcolor_selected" format="color|reference" />
            <!--item 字体颜色-->
            <attr name="item_textcolor" format="color|reference" />
            <!--item 选中的背景颜色-->
            <attr name="item_textcolor_selected" format="color|reference" />
            <!--item 字体大小-->
            <attr name="item_textsize" format="dimension|reference" />
        </declare-styleable>

    数据源解析

    我采用递归的方式计算出总行数、总列数、所有叶子结点坐在的列数

     /**
         * 递归解析数据
         * a,计算出总列数和总行数
         * b,所有叶子结点项设置所在列的值
         *
         * @param data 数据源
         */
        private void paraseDataLineAndLastNodeRow(MorgDataBean data) {
            if (data == null || data.getChilds() == null || data.getChilds().size() == 0) {
                return;
            }
            for (MorgDataBean d : data.getChilds()) {
                /*自己所处的行数=父节点所在的行数+1
                 从上到下的顺序*/
                d.setCurrentLine(data.getCurrentLine() + 1);
                /*总行数也是根据行数的增加而增加的*/
                if (data.getCurrentLine() + 1 > totalLineCount) {
                    totalLineCount = data.getCurrentLine() + 1;
                }
                /*所有分支的叶子结点数 即该叶子结点项所在的列数*/
                if (d.getChilds() == null || d.getChilds().size() == 0) {
                    /*列数+1*/
                    totalRowCount++;
                    d.setCurrentRow(totalRowCount);
                }
                paraseDataLineAndLastNodeRow(d);
            }
        }

    倒叙遍历该节点的父节点坐在的列数

    /*倒序遍历*/
            for (int i = totalLineCount; i > 0; i--) {
                paraseDataNodeRow(i, data);
            }
        /**
         * 目的修改 该级父对象即data 的所在列数
         *
         * @param level 遍历的级数 需要倒数遍历 从大到小的顺序
         * @param data  数据源
         */
        private void paraseDataNodeRow(int level, MorgDataBean data) {
            if (data == null) {
                return;
            }
    
            if (data.getChilds() == null) {
                return;
            }
            for (MorgDataBean d : data.getChilds()) {
                if (d.getCurrentLine() == level && data.getCurrentRow() == 0) {
                    data.setCurrentRow((d.getCurrentRow() + data.getChilds().get(data.getChilds().size() - 1).getCurrentRow()) / 2.0f);
                } else {
                    paraseDataNodeRow(level, d);
                }
            }
        }

    计算每行最大的内容长度,用来确定行最高值

        /**
         * 计算每行line 的最大内容长度
         */
        private void paraseDataContentMaxLength4Line(MorgDataBean data) {
            if (data == null) {
                return;
            }
            for (MorgDataBean d : data.getChilds()) {
                if (!isEmpty(d.getOrgname()) && contentMaxLength4line.length > d.getCurrentLine()) {
                    contentMaxLength4line[d.getCurrentLine()] = Math.max(contentMaxLength4line[d.getCurrentLine()], d.getOrgname().trim().length());
                    contentMaxHeigth4line[d.getCurrentLine()] = getTotalContentHeight(contentMaxLength4line[d.getCurrentLine()]);
                }
                if (d.getChilds() != null && d.getChilds().size() > 0) {
                    paraseDataContentMaxLength4Line(d);
                }
            }
        }

    使用如下(activity_layout.xml):

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
    
        <com.coocpu.orgmap.OrgMapView
            android:id="@+id/orgMapView"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:item_width="28dp"
            app:item_height="167dp"
            app:item_bgcolor="#FFF6F6F6"
            app:item_bgcolor_selected="#FF609961"
            app:item_raidus="8dp"
            app:item_textcolor="#FF343434"
            app:item_textcolor_selected="#FFFFFFFF"
            app:item_textsize="16sp"
            app:item_margin_h="16dp"
            app:item_margin_v="62dp"
            app:item_padding_v="10dp"
            app:item_line1_margin_top="42dp"
            app:item_margin_to_line="10dp"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"/>
        <View
            android:layout_width="0dp"
            android:layout_height="1dp"
            android:background="#ffebebeb"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"/>
    
        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            android:padding="14dp"
            android:onClick="expand"
            android:src="@mipmap/morgmanage_icon_expand"/>
    
    </androidx.constraintlayout.widget.ConstraintLayout>

    MainActivity.java

    
    public class MainActivity extends AppCompatActivity {
        /**
         * 是否是横屏
         * 默认false
         */
        boolean mIsPreviewLand = false;
    
        OrgMapView orgMapView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            orgMapView = findViewById(R.id.orgMapView);
    
            /*设置数据源*/
            String val = orgMapView.getOriginalFundData(this);
            Gson gson = new Gson();
            MorgDataBean data = gson.fromJson(val, MorgDataBean.class);
            orgMapView.setData(data);
        }
    
        public void expand(View view) {
            setRequestedOrientation(!mIsPreviewLand ? ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE : ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            mIsPreviewLand = !mIsPreviewLand;
        }
    }

    组织架构模拟数据可以到github项目中自行下载使用。

    实现效果如下:

     

    github项目下载地址

     

    不足之处:点击事件的时间间隔没有处理的很好,希望小伙伴能够给予好的意见和方案,欢迎评论转载。

    展开全文
  • 自定义NineGirdView实现 钉钉--发现--圈子 的多图展示效果
  • 项目采用github上开源项目PinnedHeaderListView,并重写了该项目中的适配器的相关方法,实现了不同section中加载不同个数的item。item由图片和文本构成。
  • 钉钉联系人列表是: 包含汉字时候取后两个(不满两个字符去所有) 如:这片海 取:片海 不包含汉字时候取前两个(不满两个字符取所有) 如:sea 取 se 设计思路 画圆形图像,根据获得的名字进行在圆形图像的...
  • 钉钉、微信选择联系人,支持a-z选择和搜索框,钉钉、微信选择联系人,支持a-z选择和搜索框
  • 最近无意中看到钉钉这个App,发现联系人详情这个界面的效果还是蛮好看的。正好最近在看Material Design,所以想看看可不可用Android系统原生的来实现这种效果。先看效果图:这是有一个推滑的特效的,在钉钉上有一个...
  • Android架构图 (5层)

    千次阅读 2017-11-09 21:28:38
    android五层架构
  • 钉钉的通讯录
  • 本文引用了唐小智发表于InfoQ公众号上的“钉钉企业级IM存储架构创新之道”一文的部分内容,收录时有改动,感谢原作者的无私分享。 1、引言 业界的 IM 产品在功能上同质化较高,而企业级的 IM 产品对于高可用、安全...
  • 高仿android通讯录

    2011-06-01 22:51:50
    最近都没有时间来更新我的博客,主要是在项目中遇到一些比较棘手的问题需要解决,今天我就把我解决的难题写了个Demo出来与大家一起分享,最终达到火种通讯录联系人界面的效果。 在这次代码编写当中,我主要用到了...
  • //获取屏幕大小,以合理设定 按钮 大小及位置  DisplayMetrics dm = new DisplayMetrics();  getWindowManager().getDefaultDisplay().getMetrics(dm);  int width = dm.widthPixels; ... int height = dm....
  • 企业钉钉重点功能使用说明

    万次阅读 2016-06-06 14:39:39
    内容多来自钉钉及tower的帮助中心,此处是帮助大家梳理主要用到的功能,方便查阅,为了隐私已打码处理个人及公司相关的名字。
1 2 3 4 5 ... 14
收藏数 272
精华内容 108
关键字:

钉钉组织架构android