AndroidR上展讯CameraApp的TopPanelLayout处理

我们以后摄Photo为例,跟踪下CameraAPP顶部的Icon是怎么加载上去的。
首先,UI相关的继承关系如下:
AutoPhotoUI --> PhotoUI —>DreamUI

具体布局是:TopPanelLayout
public class TopPanelLayout extends LinearLayout

看下自定义view的内容

public void addTopButtons(ArrayList<TopPanelUtil.IconAndDes> list) {
        if(list.size() <= 0){
            return;
        }

        mList.addAll(list);
        int length = mList.size();
        for(int i = 0; i < length; i++){
            TopPanelUtil.IconAndDes value= mList.get(i);
            addTopButton(value,i,length);
        }

    }

 public void addTopButtons(TopPanelUtil.IconAndDes value, int index){
     mList.add(index,value);
     addTopButton(value,index,mList.size());
     if (index == 0 && mList.size() >= 2){
         ((ViewGroup) this.getChildAt(1)).getChildAt(0).setVisibility(View.VISIBLE);
     }
 }

 public void removeTopButton(Integer id){
     int index = findItemIndex(id);

     if(index == -1){
         return;
     }

     TopPanelUtil.IconAndDes value = mList.remove(index);

     if(index == 0) {
         ((ViewGroup) this.getChildAt(1)).getChildAt(0).setVisibility(View.GONE);
     }
     this.removeViewAt(index);
 }

很熟悉,有一些add、remove相关的,应该是view的操作。并且数据都转换成了 TopPanelUtil.IconAndDes 类型在传递。
展讯平台的TopLayout做的比较好,就是无论顶部有几个Icon,都是等间距的,如果只有两个的话,就是左右两边各一个Icon,这样看起来比较舒服。
具体的控制是通过LayoutParams做的

    private void addTopButton(TopPanelUtil.IconAndDes value, int index, int length){
        boolean isLeftEdge = index == 0 && length != 1;//如果只有一个Icon的话,还是添加widget,这样就能在右侧显示了
        LinearLayout frame = generateButtonLayout(value, isLeftEdge);
        addTopButton(frame,index,isLeftEdge);

    }

    private void addTopButton(LinearLayout frame, int index, boolean leftEdge) {
        LinearLayout.LayoutParams lp;
        if(leftEdge){//最左侧的View不设置weiget
            lp = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
                    LayoutParams.WRAP_CONTENT);
        } else {//除了最左侧的View,其他view都设置相等的weiget
            lp = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,
                    LayoutParams.WRAP_CONTENT,1);
        }

        this.addView(frame,index,lp);
    }

Icon分为两种:普通Button 和 MultitoggleImageButton

private LinearLayout generateButtonLayout(TopPanelUtil.IconAndDes value, boolean leftEdge) {
        LinearLayout frame = null;
        if(value.buttonType == R.integer.button_type_multitoggleimagebutton){
            frame = addMultitoggleImageButton(value,leftEdge);
        } else if ( value.buttonType == R.integer.button_type_rotateimagebutton ){
            frame = addRotateImageButton(value,leftEdge);
        }
        return frame;
    }

    private LinearLayout addMultitoggleImageButton(TopPanelUtil.IconAndDes value, boolean leftEdge){
        int layoutId = R.layout.top_panel_item_multitoggle_image_button;
        LayoutInflater lf = LayoutInflater.from(getContext());
        LinearLayout frame = (LinearLayout)lf.inflate(layoutId,null);

        MultiToggleImageButton button = (MultiToggleImageButton) frame.getChildAt(1);
        button.setId(value.id);
        button.overrideContentDescriptions(value.desID);
        button.overrideImageIds(value.iconID);
        button.setState(0);

        if(leftEdge){
            frame.getChildAt(0).setVisibility(View.GONE);
        }

        return frame;
    }

vie拿到数据后做的相关的处理就是这些了,最开始看到的addTopButtons相关的方法,便是数据来源了。现在跟踪下数据来自什么逻辑。

DreamUI中的关键方法

@Override
    public void fitTopPanel(ViewGroup topPanelParent){
    	//1 加载布局
        LayoutInflater lf = LayoutInflater.from(topPanelParent.getContext());
        mTopPanel = (TopPanelLayout)(lf.inflate(R.layout.top_panel_layout, null));
		//2 获取xml的数据配置
        int configID = getTopPanelConfigID();
        ArrayList<TopPanelUtil.IconAndDes> list = TopPanelUtil.generateTopPanelList(topPanelParent.getContext(),configID);
		//3 过滤xml配置的数据
        filterTopPanelConfig(list);
		// 4 addTop来了,将过滤后的数据传给view去显示
        mTopPanel.addTopButtons(list);
        ((CameraActivity)topPanelParent.getContext()).getButtonManager().load(mTopPanel);

        bindTopPanelButton();
		//5 填充好了TopPanelLayout之后,在把它放到topPanelParent中
        FrameLayout.LayoutParams lay = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        topPanelParent.addView(mTopPanel,lay);

        updateTopPanelButtonStatus();
    }

上面代码中的1,2,3,4步写得很清楚了,在不同的Module下,显示的Icon不同就是因为第二步中的xml配置数据了。
基类DreamUI中 getTopPanelConfigID 方法并未实现,需要具体的moduleUI去实现

在AutoPhotoUI中看到(不同Module有自己的配置)

@Override
    protected int getTopPanelConfigID() {
        return R.array.auto_photo_top_panel;
    }
<array name="auto_photo_top_panel">
        <item>@array/flash_photo_front_led_config</item>
        <item>@array/hdr_config</item>
        <item>@array/motionphoto_config</item>
        <item>@array/makeup_display_photo_config</item>
        <item>@array/camera_settings_config</item>
    </array>

我们看到应该是有5个配置了。
前面我们说到Icon有两种类型,在xml中我们可以很清楚的看到两种类型的配置和差异

<array name="flash_photo_front_led_config">
        <item>@integer/button_type_multitoggleimagebutton</item>
        <item>@integer/flash_toggle_button_dream</item>
        <item>@array/camera_flash_descriptions</item>
        <item>@array/dream_camera_front_led_flashmode_icons</item>
    </array>
<array name="camera_settings_config">
        <item>@integer/button_type_rotateimagebutton</item>
        <item>@integer/settings_button_dream</item>
        <item>@drawable/ic_setting_indicator_unisoc</item>
    </array>

显然,button_type_rotateimagebutton 是少一个description的配置哦。

在上面的TopPanelLayout中我们看到它将传入的数据转换成了 TopPanelUtil.IconAndDes类型

public static class IconAndDes {
        public int buttonType;
        public int id;
        public int desID;
        public int iconID;

        public IconAndDes(TypedArray type){
            buttonType = type.getResourceId(0,-1);
            id = type.getResourceId(1,-1);
            if(buttonType == R.integer.button_type_rotateimagebutton){
                iconID = type.getResourceId(2,-1);
            } else if( buttonType == R.integer.button_type_multitoggleimagebutton ){
                desID = type.getResourceId(2,-1);
                iconID = type.getResourceId(3,-1);
            }
        }
    }

这个类的成员变量一个看就和xml的配置比较相似了吧,没错,xml配置的数据就是转成了这个对象来装的,并且这里配合xml两种类型的button,也做了type的区分。

数据加载进来了,第3步,filterTopPanelConfig还是由各个Module去决定。
所以,我们在xml配置了设置项,但是不一定会显示出来,因为还可能在java的filter方法中过滤掉哦。

topPanelLayout填充之后,再将其add到topPanelParent,这样设置项就显示出来了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值