iis服务器助手广告
返回顶部
首页 > 资讯 > 精选 >Android怎么实现小米相机底部滑动指示器
  • 266
分享到

Android怎么实现小米相机底部滑动指示器

2023-06-14 12:06:31 266人浏览 八月长安
摘要

这篇文章给大家分享的是有关Android怎么实现小米相机底部滑动指示器的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。先上一张图看下效果:主要实现功能有:支持左右滑动,每次滑动一个tab支持tab点击,直接跳到对应

这篇文章给大家分享的是有关Android怎么实现小米相机底部滑动指示器的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

先上一张图看下效果:

Android怎么实现小米相机底部滑动指示器

主要实现功能有:

支持左右滑动,每次滑动一个tab

支持tab点击,直接跳到对应tab

选中的tab一直处于居中位置

支持部分UI自定义(大家可根据需要自己改动)

tab点击回调

内置Tab接口,放入的内容需要实现Tab接口

设置预选中tab

public class Cameraindicator extends LinearLayout {    // 当前选中的位置索引    private int currentIndex;    //tabs集合    private Tab[] tabs;     // 利用Scroller类实现最终的滑动效果    public Scroller mScroller;    //滑动执行时间(ms)    private int mDuration = 300;    //选中text的颜色    private int selectedTextColor = 0xffffffff;    //未选中的text的颜色    private int nORMalTextColor = 0xffffffff;    //选中的text的背景    private Drawable selectedTextBackgroundDrawable;    private int selectedTextBackgroundColor;    private int selectedTextBackgroundResources;    //是否正在滑动    private boolean isScrolling = false;     private int onLayoutCount = 0;      public CameraIndicator(Context context) {        this(context, null);    }     public CameraIndicator(Context context, @Nullable AttributeSet attrs) {        this(context, attrs, 0);    }     public CameraIndicator(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        mScroller = new Scroller(context);     }     @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        int widthMode = MeasureSpec.getMode(widthMeasureSpec);        int widthSize = MeasureSpec.getSize(widthMeasureSpec);        int heightMode = MeasureSpec.getMode(heightMeasureSpec);        int heightSize = MeasureSpec.getSize(heightMeasureSpec);        //测量所有子元素        measureChildren(widthMeasureSpec, heightMeasureSpec);        //处理wrap_content的情况        int width = 0;        int height = 0;        if (getChildCount() == 0) {            setMeasuredDimension(0, 0);        } else if (widthMode == MeasureSpec.AT_MOST && heightMode == MeasureSpec.AT_MOST) {            for (int i = 0; i < getChildCount(); i++) {                View child = getChildAt(i);                width +=  child.getMeasuredWidth();                height = Math.max(height, child.getMeasuredHeight());            }            setMeasuredDimension(width, height);        } else if (widthMode == MeasureSpec.AT_MOST) {            for (int i = 0; i < getChildCount(); i++) {                View child = getChildAt(i);                width +=  child.getMeasuredWidth();            }            setMeasuredDimension(width, heightSize);        } else if (heightMode == MeasureSpec.AT_MOST) {            for (int i = 0; i < getChildCount(); i++) {                View child = getChildAt(i);                height = Math.max(height, child.getMeasuredHeight());            }            setMeasuredDimension(widthSize, height);        } else {            //如果自定义ViewGroup之初就已确认该ViewGroup宽高都是match_parent,那么直接设置即可            setMeasuredDimension(widthSize, heightSize);        }    }     @Override    protected void onLayout(boolean changed, int l, int t, int r, int b) {        //给选中text的添加背景会多次进入onLayout,会导致位置有问题,暂未解决        if (onLayoutCount > 0) {            return;        }        onLayoutCount++;         int counts = getChildCount();        int childLeft = 0;        int childRight = 0;        int childTop = 0;        int childBottom = 0;        //居中显示        int widthOffset = 0;          //计算最左边的子view距离中心的距离        for (int i = 0; i < currentIndex; i++) {            View childView = getChildAt(i);            widthOffset += childView.getMeasuredWidth() + getMargins(childView).get(0)+getMargins(childView).get(2);        }         //计算出每个子view的位置        for (int i = 0; i < counts; i++) {            View childView = getChildAt(i);            childView.setOnClickListener(v -> moveTo(v));            if (i != 0) {                View preView = getChildAt(i - 1);                childLeft = preView.getRight() +getMargins(preView).get(2)+ getMargins(childView).get(0);            } else {                childLeft = (getWidth() - getChildAt(currentIndex).getMeasuredWidth()) / 2 - widthOffset;            }            childRight = childLeft + childView.getMeasuredWidth();            childTop = (getHeight() - childView.getMeasuredHeight()) / 2;            childBottom = (getHeight() + childView.getMeasuredHeight()) / 2;            childView.layout(childLeft, childTop, childRight, childBottom);        }         TextView indexText = (TextView) getChildAt(currentIndex);        changeSelectedUIState(indexText);     }     private List<Integer> getMargins(View view) {        LayoutParams params = (LayoutParams) view.getLayoutParams();        List<Integer> listMargin = new ArrayList<Integer>();        listMargin.add(params.leftMargin);        listMargin.add(params.topMargin);        listMargin.add(params.rightMargin);        listMargin.add(params.bottomMargin);        return listMargin;    }     @Override    public void computeScroll() {        if (mScroller.computeScrollOffset()) {            // 滑动未结束,内部使用scrollTo方法完成实际滑动            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());            invalidate();        } else {            //滑动完成            isScrolling = false;            if (listener != null) {                listener.onChange(currentIndex,tabs[currentIndex]);            }        }        super.computeScroll();    }          public final void scrollToNext(int currentIndex, int nextIndex) {        TextView selectedText = (TextView) getChildAt(currentIndex);        if (selectedText != null) {            selectedText.setTextColor(normalTextColor);            selectedText.setBackground(null);        }        selectedText = (TextView) getChildAt(nextIndex);        if (selectedText != null) {            changeSelectedUIState(selectedText);        }    }     private void changeSelectedUIState(TextView view) {        view.setTextColor(selectedTextColor);        if (selectedTextBackgroundDrawable != null) {            view.setBackground(selectedTextBackgroundDrawable);        }         if (selectedTextBackgroundColor != 0) {            view.setBackgroundColor(selectedTextBackgroundColor);        }        if (selectedTextBackgroundResources != 0) {            view.setBackgroundResource(selectedTextBackgroundResources);        }    }          public void moveToRight() {        moveTo(getChildAt(currentIndex - 1));    }          public void moveToLeft() {        moveTo(getChildAt(currentIndex + 1));    }         private void moveTo(View view) {        for (int i = 0; i < getChildCount(); i++) {            if (view == getChildAt(i)) {                if (i == currentIndex) {                    //不移动                    break;                } else if (i < currentIndex) {                    //向右移                    if (isScrolling) {                        return;                    }                    isScrolling = true;                    int dx = getChildAt(currentIndex).getLeft() - view.getLeft() + (getChildAt(currentIndex).getMeasuredWidth() - view.getMeasuredWidth()) / 2;                    //这里使用scroll会使滑动更平滑不卡顿,scroll会根据起点、终点及时间计算出每次滑动的距离,其内部有一个插值器                    mScroller.startScroll(getScrollX(), 0, -dx, 0, mDuration);                    scrollToNext(currentIndex, i);                    setCurrentIndex(i);                    invalidate();                } else if (i > currentIndex) {                    //向左移                    if (isScrolling) {                        return;                    }                    isScrolling = true;                    int dx = view.getLeft() - getChildAt(currentIndex).getLeft() + (view.getMeasuredWidth() - getChildAt(currentIndex).getMeasuredWidth()) / 2;                    mScroller.startScroll(getScrollX(), 0, dx, 0, mDuration);                    scrollToNext(currentIndex, i);                    setCurrentIndex(i);                    invalidate();                }            }        }    }          public void setTabs(Tab... tabs) {        this.tabs = tabs;        //暂时不通过layout布局添加textview        if (getChildCount()>0){            removeAllViews();        }        for (Tab tab : tabs) {            TextView textView = new TextView(getContext());            textView.setText(tab.getText());            textView.setTextSize(14);            textView.setTextColor(selectedTextColor);            textView.setPadding(dp2px(getContext(),5), dp2px(getContext(),2), dp2px(getContext(),5),dp2px(getContext(),2));            LayoutParams layoutParams= new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);            layoutParams.rightMargin=dp2px(getContext(),2.5f);            layoutParams.leftMargin=dp2px(getContext(),2.5f);            textView.setLayoutParams(layoutParams);            addView(textView);        }    }      public int getCurrentIndex() {        return currentIndex;    }     //设置默认选中第几个    public void setCurrentIndex(int currentIndex) {        this.currentIndex = currentIndex;    }     //设置滑动时间    public void setDuration(int mDuration) {        this.mDuration = mDuration;    }     public void setSelectedTextColor(int selectedTextColor) {        this.selectedTextColor = selectedTextColor;    }     public void setNormalTextColor(int normalTextColor) {        this.normalTextColor = normalTextColor;    }     public void setSelectedTextBackgroundDrawable(Drawable selectedTextBackgroundDrawable) {        this.selectedTextBackgroundDrawable = selectedTextBackgroundDrawable;    }     public void setSelectedTextBackgroundColor(int selectedTextBackgroundColor) {        this.selectedTextBackgroundColor = selectedTextBackgroundColor;    }     public void setSelectedTextBackgroundResources(int selectedTextBackgroundResources) {        this.selectedTextBackgroundResources = selectedTextBackgroundResources;    }     public interface OnSelectedChangedListener {        void onChange(int index, Tab tag);    }     private OnSelectedChangedListener listener;     public void setOnSelectedChangedListener(OnSelectedChangedListener listener) {        if (listener != null) {            this.listener = listener;        }    }     private int dp2px(Context context, float dpValue) {        DisplayMetrics metrics = context.getResources().getDisplayMetrics();        return (int) (metrics.density * dpValue + 0.5F);    }      public interface Tab{        String getText();    }     private float startX = 0f;    @Override    public boolean onTouchEvent(MotionEvent event) {        if (event.getAction() == MotionEvent.ACTION_DOWN) {            startX = event.getX();        }        if (event.getAction() == MotionEvent.ACTION_UP) {            float endX = event.getX();            //向左滑条件            if (endX - startX > 50 && currentIndex > 0) {                moveToRight();            }            if (startX - endX > 50 && currentIndex < getChildCount() - 1) {                moveToLeft();            }        }        return true;    }     @Override    public boolean onInterceptTouchEvent(MotionEvent event) {        if (event.getAction() == MotionEvent.ACTION_DOWN) {            startX = event.getX();        }        if (event.getAction() == MotionEvent.ACTION_UP) {            float endX = event.getX();            //向左滑条件            if (Math.abs(startX-endX)>50){                onTouchEvent(event);            }        }        return super.onInterceptTouchEvent(event);    }}

在Activity或fragment中使用

private var tabs = listOf("慢动作", "短视频", "录像", "拍照", "108M", "人像", "夜景", "萌拍", "全景", "专业")    lateinit var  imageAnalysis:ImageAnalysis     override fun initView() {         //实现了CameraIndicator.Tab的对象        val map = tabs.map {            CameraIndicator.Tab { it }        }?.toTypedArray() ?: arrayOf()        //将tab集合设置给cameraIndicator,(binding.cameraIndicator即xml布局里的控件)        binding.cameraIndicator.setTabs(*map)        //默认选中  拍照        binding.cameraIndicator.currentIndex = 3        //点击某个tab的回调binding.cameraIndicator.setSelectedTextBackgroundResources(R.drawable.selected_text_bg)         binding.cameraIndicator.setOnSelectedChangedListener { index, tag ->            Toast.makeText(this,tag.text,Toast.LENGTH_SHORT).show()        } }

感谢各位的阅读!关于“Android怎么实现小米相机底部滑动指示器”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

--结束END--

本文标题: Android怎么实现小米相机底部滑动指示器

本文链接: https://www.lsjlt.com/news/270967.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Android实现小米相机底部滑动指示器
    近期工作内容需要涉及到相机开发,其中一个功能点就是实现一个相机预览页底部的滑动指示器,现在整理出来供大家讨论参考。 先上一张图看下效果: 主要实现功能有: 1.支持左右滑动,每次滑...
    99+
    2024-04-02
  • Android怎么实现小米相机底部滑动指示器
    这篇文章给大家分享的是有关Android怎么实现小米相机底部滑动指示器的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。先上一张图看下效果:主要实现功能有:支持左右滑动,每次滑动一个tab支持tab点击,直接跳到对应...
    99+
    2023-06-14
  • Android仿天猫横向滑动指示器功能的实现
    Android开发中会有很多很新奇的交互,比如天猫商城的首页头部的分类,使用的是GridLayoutManager+横向指示器实现的,效果如下图。 那对于这种效果要如何实现呢?最简...
    99+
    2022-11-13
    Android横向滑动指示器 Android横向滑动
  • Android中怎么实现底图局部加载移动
    今天就跟大家聊聊有关Android中怎么实现底图局部加载移动,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。具体如下:public class MapMgr&nbs...
    99+
    2023-05-30
    android
  • Android中怎么实现美团顶部的滑动菜单
    本篇文章为大家展示了Android中怎么实现美团顶部的滑动菜单,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。首先需要一个代表每个活动主题的 JavaBeanpublic class&nbs...
    99+
    2023-05-30
    android
  • 怎么Android应用中实现一个APP显示界面滑动优化
    这篇文章将为大家详细讲解有关怎么Android应用中实现一个APP显示界面滑动优化,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。1、界面布局<xml version=&quo...
    99+
    2023-05-31
    android pp roi
  • 纯CSS怎么实现微信小程序仿QQ顶部提示弹框动画效果
    这篇文章将为大家详细讲解有关纯CSS怎么实现微信小程序仿QQ顶部提示弹框动画效果,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。效果思路 用css的animation属性做动画代码wxml:<view...
    99+
    2023-06-08
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作