Android自定义数字键盘

2023-05-16

好久没有写Android的文章了,有两三个月多了吧,刚开始搞微信小程序,后来又开搞ReactNative,现在又兴奋的开搞AI机器学习的东西,感觉挺有意思的,不过AI与其它的东西相比要难很多,需要补很多数学知识,不过我现在学的都还是皮毛,没啥深度,但是我会慢慢深入的,对AI的兴趣比较大,年轻人就要不断的折腾嘛,当然自己的老本行也要搞起啦,饭还是要吃的。

好像说的有点多了,今天的这篇文章是介绍Android中自定义键盘的一些套路,通过定义一个数字键盘为例,本篇的文章语言是基于Kotlin实现的,如果还没有用或者不熟悉该语言的同学,可以自己补习,我之前也写过入门文章。

效果图

源码传送门

加载键盘存储键属性的XML描述

我们下面的介绍都是依靠上图的实现来展开的,首先是软键盘的布局,我们需要我们的res/xml目录下创建一个xml文件,根节点就是Keyboard,然后就是键盘的每一行Row,每一行中可以指定每一列,也就是具体的键Key,代码实现

<?xml version="1.0" encoding="utf-8"?><!--
isRepeatable:长按时是否重复这个操作
-->
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
    android:horizontalGap="1px"
    android:keyHeight="7%p"
    android:keyWidth="33.33%p"
    android:verticalGap="1px">
    <Row android:keyHeight="6%p">
        <Key
            android:codes="-4"
            android:keyIcon="@drawable/hidden"
            android:keyWidth="100%" />
    </Row>
    <Row>
        <Key
            android:codes="49"
            android:keyLabel="1" />
        <Key
            android:codes="50"
            android:keyLabel="2" />
        <Key
            android:codes="51"
            android:keyLabel="3" />
    </Row>
    <Row>
        <Key
            android:codes="52"
            android:keyLabel="4" />
        <Key
            android:codes="53"
            android:keyLabel="5" />
        <Key
            android:codes="54"
            android:keyLabel="6" />
    </Row>
    <Row>
        <Key
            android:codes="55"
            android:keyLabel="7" />
        <Key
            android:codes="56"
            android:keyLabel="8" />
        <Key
            android:codes="57"
            android:keyLabel="9" />
    </Row>
    <Row>
        <Key
            android:codes="46"
            android:keyLabel="." />
        <Key
            android:codes="48"
            android:keyLabel="0" />
        <Key
            android:codes="-5"
            android:isRepeatable="true"
            android:keyIcon="@drawable/delete" />
    </Row>
</Keyboard>

在Keyboard节点属性中,我们通过horizontalGap设置水平的间距,通过verticalGap设置垂直的间距,通过keyWidth设置每一个key的宽度,通过keyHeight设置。需要注意的地点是如果Keyboard ,Row和Key都可以指定宽高。通常我们可以指定在Keyboard 中设置每一个键的宽高就可以了。当然如果对特定行的宽高要有所调整,可以在Row 或者key上设置,例如我们示例图中展示的最上面的一行,它的宽度比其它行都低了一点,则我们在第一行设置了属性android:keyHeight=”6%p”

在每一个key中有下面常用属性
- android:codes 官网介绍是说这个是该键的unicode 值或者逗号分隔值,当然我们也可以设置成我们想要的值,在源码中提供了几个特定的值

//就不解释了,通过名字应该看得出来
    public static final int KEYCODE_SHIFT = -1;
    public static final int KEYCODE_MODE_CHANGE = -2;
    public static final int KEYCODE_CANCEL = -3;
    public static final int KEYCODE_DONE = -4;
    public static final int KEYCODE_DELETE = -5;
    public static final int KEYCODE_ALT = -6;
  • android:keyOutputText 设置该值后,当点击key时回调onText(text: CharSequence?)会执行,参数就是我们设置的值。
  • android:keyIcon设置key上显示的icon
  • android:keyLabel 键上显示的值
  • android:isRepeatable 当长按时是否重复该键设置的操作,例如我们删除键可以设置此属性。
  • android:keyEdgeFlags 该属性有两个值,分别是left,right,用与指定显示在最左还是最右,一般不用此属性。默认从左到右排列。
    还有其它属性,不在介绍,可以自己去查阅api

自定义KeyboardView

该类是用来渲染虚拟键盘的类,类中有一个接口OnKeyboardActionListener能检测按键和触摸动作,我们要自定义虚拟键盘,只需要继承该类并实现该监听接口即可,当然我这里并没有实现接口,我单独创建了一个工具类,用于将自定义键盘View和EditText关联,并设置接口监听,这些稍后介绍到再说,我们最主要关注的就是onDraw方法,它可以让我们自定义键盘的绘制,随心所欲的画我们想要的东西。当然,我们也可以不做任何实现,它默认的有一种绘制。

class CustomKeyboardView : KeyboardView {
    private var mKeyBoard: Keyboard? = null

    constructor(context: Context, attrs: AttributeSet) : this(context, attrs,0) {}

    constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
        //
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        mKeyBoard = this.keyboard
        var keys: MutableList<Keyboard.Key>? = null
        if (mKeyBoard != null) {
            keys = mKeyBoard!!.keys
        }
        if (keys != null) {
            for (key in keys) {
                //可以自定义自己的绘制(例如某个按钮绘制背景图片和文字,亦或者更改某个按钮颜色等)
                if (key.codes[0] == -111) {//过滤指定某个键自定义绘制
                }
            }
        }
    }
}

在上面的onDraw方法中,我们通过this.keyboard(即java的getKeyboard方法,是KeyboardView 中的方法)获取Keyboard对象,并通过mKeyBoard!!.keys获取键盘的Key对象,即每一个键对象,如果我们想自定义绘制,就可以自己实现绘制,当然也可以针对个人键绘制,例如键上字体颜色,背景等。例如我们针对Key的code是 -111的自定义一些绘制操作。

    if (key.codes[0] == -111) {//过滤指定某个键自定义绘制
          //绘制后,原来xml中的keyLabel以及keyIcon会被覆盖,如需显示文字
          //需要自己重新绘制,要后绘制文字,否则文字不显示
          drawBackground(R.drawable.bg_keyboardview1, canvas, key)
          drawTextOrIcon(canvas, key)
    }

背景selector

<selector
    xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@color/btnpressed" android:state_pressed="true"/>
    <item android:drawable="@color/btnnormal"/>
</selector>

需要注意的是需要先绘制背景,再绘制文字或icon,否则文字或者icon就看不到了,相信你肯定知道为啥,真不知道的话那….

    //绘制背景
    fun drawBackground(drawableId: Int, canvas: Canvas, key: Keyboard.Key) {
        var drawable = resources.getDrawable(drawableId)
        var drawableState: IntArray = key.currentDrawableState
        if (key.codes[0] != 0) {
            drawable.state=drawableState
        }
        drawable.bounds = Rect(key.x, key.y, key.x + key.width, key.height + key.y)
        drawable.draw(canvas)
    }

绘制背景前先通过key.currentDrawableState(java的getCurrentDrawableState() 方法,后面不在提了)获取当前的状态,然后设置到drawable,然后通过Rect指定绘制的区域。Rect参数分别是左上右下。key.x,key.对应的就是该key的左上角的坐标,则left=key.x, top=key.y, right=key.x+key.width, bottom=key.y+key.height然后调用 drawable.draw(canvas)开始绘制。

绘制完成背景之后,我们开始绘制文字或者icon。

 //绘制文字或图标
    fun drawTextOrIcon(canvas: Canvas, key: Keyboard.Key) {
        var bounds = Rect()
        var paint = Paint()
        paint.color = Color.WHITE
        paint.isAntiAlias = true
        paint.textAlign = Paint.Align.CENTER
        paint.typeface = Typeface.DEFAULT
        if (key.label != null) {
            var label = key.label.toString()
            //为了将字体大小与默认绘制的Label字体大小相同,需要反射获取默认大小。然后在此处设置文字大小
            //还有一种取巧的方法在布局文件keyboardview中设置keyTextSize,labelTextSize
            var field = KeyboardView::class.java.getDeclaredField("mLabelTextSize")
            field.isAccessible = true
            var labelTextSize = field.get(this) as Int
            paint.textSize = labelTextSize.toFloat()
            paint.getTextBounds(label, 0, label.length, bounds)
            canvas.drawText(label, (key.x + key.width / 2).toFloat(), (key.y + key.height / 2 + bounds.height() / 2).toFloat(), paint)
        } else if (key.icon != null) {
            key.icon.bounds = Rect(key.x + (key.width - key.icon.intrinsicWidth) / 2, key.y + (key.height - key.icon.intrinsicHeight) / 2, key.x + (key.width - key.icon.intrinsicWidth) / 2 + key.icon.intrinsicWidth, key.y + (key.height - key.icon.intrinsicHeight) / 2 + key.icon.intrinsicHeight)
            key.icon.draw(canvas)
        }
    }

通过上面的代码,我们做了下判断如果有label的时候就绘制文字,如果没有但是有icon就绘制icon,否则不做处理。在这里可以指定绘制文字的大小,颜色等。需要注意的一点是文字大小,为了和显示的其他默认绘制key的大小相同,需要获取KeyboardView中的mLabelTextSize或者mKeyTextSize,因为该变量没有提供暴露方法,所以需要我们反射操作。当然还有一种取巧的方法,我们可以在xml中指定字体大小,在此设置成相同大小。对于坐标区域的计算上面已经做了分析。

布局使用

<?xml version="1.0" encoding="utf-8"?><!--
background:整个键盘的背景色
keyBackground   :设置键的背景
keyPreviewHeight:预览高度
keyPreviewLayout   :设置预览布局
keyPreviewOffset :设置反馈的垂直偏移量
keyTextColor    :设置key标签文字颜色
keyTextSize:设置key标签字体大小
labelTextSize:设置带文本和图标的键上个的文本的小大

-->
<com.code4android.keyboard.CustomKeyboardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/keyboard_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/keyborad_line_color"
    android:focusable="true"
    android:focusableInTouchMode="true"
    android:keyBackground="@drawable/bg_keyboardview"
    android:keyPreviewHeight="35dp"
    android:keyPreviewLayout="@layout/keyboard_key_preview"
    android:keyPreviewOffset="0dp"
    android:keyTextColor="#8a8a8a"
    android:keyTextSize="18sp"
    android:labelTextSize="18sp"
    android:paddingTop="0dp"
    android:shadowColor="#fff"
    android:shadowRadius="0.0" />

我们创建了自定义的View之后,需要再创建上面layout供加载。keyBackground属性是设置Key的背景,一般我们可以设置一个selected选择器。keyPreviewHeight设置预览的高度,即我们点击时会有一个提示效果。keyPreviewLayout是我们预览的布局,它需要是一个TextView 。keyPreviewOffset是预览的偏移量,keyTextColor设置key字体颜色,shadowRadius我们一般设置为0,它表示字体的阴影,如果不设置0.看起来回模糊。

创建工具类

在工具类中创建了两个构造方法


    constructor(activity: Activity) : this(activity, true, false)
    /**
     * @param activity
     * @param isRandom  是否时随机键盘
     * @param mIsDecimal  是否支持小数输入
     */
    constructor(activity: Activity, isRandom: Boolean, isDecimal: Boolean) {
        mActivity = activity
        mIsRandom = isRandom
        mIsDecimal = isDecimal
        mKeyboard = Keyboard(mActivity, R.xml.keyboard)
        addViewToRoot()
    }

//加载自定义的键盘layout
    private fun addViewToRoot() {
        mKeyBoardViewContainer = mActivity.layoutInflater.inflate(R.layout.keyboardview, null)
        //var frameLayout: FrameLayout = mActivity.window.decorView as FrameLayout//不要直接往DecorView(状态栏,内容,导航栏)中addView,如使用这个则最后显示布局不全(一部分内容在导航栏区域)
        var frameLayout: FrameLayout = mActivity.window.decorView.find(android.R.id.content)
        var lp = FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT)
        lp.gravity = Gravity.BOTTOM
        frameLayout.addView(mKeyBoardViewContainer, lp)
        mKeyBoardView = mKeyBoardViewContainer.find(R.id.keyboard_view)
    }

在构造方法中初始化Keyboard,以及布局文件,在代码中我们看到我们获取到DecorView中id为android.R.id.content的布局,该布局是FrameLayout 布局,我们创建的布局都是放在这个布局中了,对这方面不理解的可以看看我之前写的文章深入分析setContentView。为了让我们自定义的键盘显示在最下面,设置Gravity为BOTTOM,然后通过frameLayout.addView(mKeyBoardViewContainer, lp)添加到FrameLayout 中。

除此之外,我们创建一个函数attachTo(EditText)将EditText与我们自定义的键盘绑定

fun attachTo(editText: EditText) {
        //如果editText与上次设置的是同一个对象,并且键盘已经正在在显示,不再执行后续操作
        if (mEditText != null && mEditText == editText && mKeyBoardView.visibility == View.VISIBLE) return
        mEditText = editText
        Log.e(TAG, "attachTo")
        //根据焦点及点击监听,来显示或者隐藏键盘
        onFoucsChange()
        //隐藏系统键盘
        hideSystemSoftKeyboard()
        //显示自定义键盘
        showSoftKeyboard()
    }

    private fun onFoucsChange() {
        mEditText!!.setOnFocusChangeListener { v, hasFocus ->
            Log.e(TAG, "onFoucsChange:$hasFocus" + v)
            //如果获取焦点,并且当前键盘没有显示,则显示,并执行动画
            if (hasFocus && mKeyBoardView.visibility != View.VISIBLE) {
                mKeyBoardView.visibility = View.VISIBLE
                startAnimation(true)
            } else if (!hasFocus && mKeyBoardView.visibility == View.VISIBLE) {
                //如果当前时失去较大,并且当前在键盘正在显示,则隐藏
                mKeyBoardView.visibility = View.GONE
                startAnimation(false)
            }
        }

        mEditText!!.setOnClickListener {
            Log.e(TAG, "setOnClickListener")
            //根据上面焦点的判断,如果已经获取到焦点,并且键盘隐藏。再次点击时,
            // 焦点改变函数不会回调,所以在此判断如果隐藏就显示
            if (mKeyBoardView.visibility == View.GONE) {
                mKeyBoardView.visibility = View.VISIBLE
                startAnimation(true)
            }
        }
    }

    private fun hideSystemSoftKeyboard() {
        //11版本开始需要反射setShowSoftInputOnFocus方法设置false,来隐藏系统软键盘
        if (Build.VERSION.SDK_INT > 10) {
            var clazz = EditText::class.java
            var setShowSoftInputOnFocus: Method? = null
            setShowSoftInputOnFocus = clazz.getMethod("setShowSoftInputOnFocus", Boolean::class.java)
            setShowSoftInputOnFocus.isAccessible = true
            setShowSoftInputOnFocus.invoke(mEditText, false)
        } else {
            mEditText!!.inputType = InputType.TYPE_NULL
        }
        var inputMethodManager = mActivity.applicationContext.inputMethodManager
        inputMethodManager.hideSoftInputFromWindow(mEditText!!.windowToken, 0)
    }

private fun showSoftKeyboard() {
        if (mIsRandom) {
            //生成随机键盘
            generateRandomKey()
        } else {
            //有序键盘
            mKeyBoardView.keyboard = mKeyboard
        }
        mKeyBoardView.isEnabled = true
        //设置预览,如果设置false,则就不现实预览效果
        mKeyBoardView.isPreviewEnabled = true
        //设置可见
        mKeyBoardView.visibility = View.VISIBLE
        //指定键盘弹出动画
        startAnimation(true)
        //设置监听
        mKeyBoardView.setOnKeyboardActionListener(mOnKeyboardActionListener())
    }

    private fun generateRandomKey() {
        var keys = mKeyboard.keys
        var numberKeys = mutableListOf<Keyboard.Key>()
        //保存数字
        var nums = mutableListOf<Int>()
        //0的ASCII码是48,之后顺序加1
        for (key in keys) {
            //过滤数字键盘
            if (key.label != null && "0123456789".contains(key.label)) {
                nums.add(Integer.parseInt(key.label.toString()))
                numberKeys.add(key)
            }
        }
        var random = Random()
        var changeKey = 0//更改numberKeys对应的数值
        while (nums.size > 0) {
            var size = nums.size
            var randomNum = nums[random.nextInt(size)]
            var key = numberKeys[changeKey++]
            key.codes[0] = 48 + randomNum
            key.label = randomNum.toString()
            nums.remove(randomNum)
        }
        mKeyBoardView.keyboard = mKeyboard
    }

具体的解释已在代码中体现。

设置键盘监听

在上面代码中我们看一句mKeyBoardView.setOnKeyboardActionListener(mOnKeyboardActionListener()),它就是设置键盘的监听。OnKeyboardActionListener接口是KeyboardView的内部类,我们在此设置监听可以指定在对应的回调种操作EditText。该接口回调方法如下

  • swipeUp()
    当用户快速将手指从下向上移动时调用
  • swipeDown 方法
    当用户快速将手指从上向下移动时调用
  • swipeLeft
    当用户快速将手指从右向左移动时调用
  • swipeRight()
    当用户快速将手指从左向右移动时调用
  • onPress(primaryCode: Int)
    点击key时调用primaryCode时对应key的codes值
  • onRelease(primaryCode: Int)
    释放key时调用
  • onKey(primaryCode: Int, keyCodes: IntArray?)
    我选择在此对EditText的编辑,onPress之后调用的。
  • onText(text: CharSequence?)
    设置keyOutputText时会会回调

具体实现

 inner class mOnKeyboardActionListener : KeyboardView.OnKeyboardActionListener {
        override fun swipeRight() {
            Log.e(TAG, "swipeRight")
        }

        override fun onPress(primaryCode: Int) {
            Log.e(TAG, "onPress")
            //添加震动效果
            mActivity.applicationContext.vibrator.vibrate(50)
            指定隐藏(确定)删除不显示预览
            mKeyBoardView.isPreviewEnabled = !(primaryCode == Keyboard.KEYCODE_DONE || primaryCode == Keyboard.KEYCODE_DELETE)
        }

        override fun onRelease(primaryCode: Int) {
            Log.e(TAG, "onRelease")
        }

        override fun swipeLeft() {
            Log.e(TAG, "swipeLeft")
        }

        override fun swipeUp() {
            Log.e(TAG, "swipeUp")
        }

        override fun swipeDown() {
            Log.e(TAG, "swipeDown")
        }

        override fun onKey(primaryCode: Int, keyCodes: IntArray?) {
            Log.e(TAG, "onKey primaryCode:$primaryCode keyCodes:$keyCodes")
            if (mEditText == null) throw RuntimeException("The mEditText is null,Please call attachTo method")

            mEditText?.let {
                var editable: Editable = it.text
                var textString = editable.toString()
                //获取光标位置
                var start = it.selectionStart
                when (primaryCode) {
                    //如果是删除键,editable有值并且光标大于0(即光标之前有内容),则删除
                    Keyboard.KEYCODE_DELETE -> {
                        if (!editable.isNullOrEmpty()) {
                            if (start > 0) {
                                editable.delete(start - 1, start)
                            } else {
                            }
                        } else {
                        }
                    }
                    Keyboard.KEYCODE_DONE -> {
                        hideSoftKeyboard()
                        mOnOkClick?.let {
                            //点击确定时,写一个回调,如果你对有确定的需求
                            it.onOkClick()
                        }
                    }
                    else -> {
                        //   由于promaryCode是用的ASCII码,则直接转换字符即可,46是小数点
                        if (primaryCode != 46 ) {
                            //如果点击的是数字,不是小数点,则直接写入EditText,由于我codes使用的是ASCII码,
                            // 则可以直接转换为数字。当然可以你也可以获取label,或者根据你自己随便约定。
                            editable.insert(start, Character.toString(primaryCode.toChar()))
                        } else {
                            //如果点击的是逗号
                            if (mIsDecimal && primaryCode == 46) {
                                if ("" == textString) {
                                    //如果点的是小数点,并且当前无内容,自动加0
                                    editable.insert(start, "0.")
                                } else if (!textString.contains(".")) {
                                    //当前内容不含有小数点,并且光标在第一个位置,依然加0操作
                                    if (start == 0) {
                                        editable.insert(start, "0.")
                                    } else {
                                        editable.insert(start, ".")
                                    }
                                } else {
                                    //如果是不允许小数输入,或者允许小数,但是已经有小数点,则不操作
                                }
                            } else {
                            }
                        }
                    }
                }
            }
        }

        override fun onText(text: CharSequence?) {
            Log.e(TAG, "onText:" + text.toString())
        }

    }
 fun hideSoftKeyboard(): Boolean {
        if (mEditText == null) return false
        var visibility = mKeyBoardView.visibility
        if (visibility == View.VISIBLE) {
            startAnimation(false)
            mKeyBoardView.visibility = View.GONE
            return true
        }
        return false
    }

    fun startAnimation(isIn: Boolean) {
        Log.e(TAG, "startAnimation")
        var anim: Animation
        if (isIn) {
            anim = AnimationUtils.loadAnimation(mActivity, R.anim.anim_bottom_in)
        } else {
            anim = AnimationUtils.loadAnimation(mActivity, R.anim.anim_bottom_out)
        }
        mKeyBoardViewContainer.startAnimation(anim)
    }

当点击的是KEYCODE_DONE 时,调用hideSoftKeyboard函数隐藏键盘,并执行隐藏动画,动画的xml文件就不在贴出了。

具体使用方式如下

        keyboardUtli = KeyBoardUtil(this@KeyBoardDemoActivity)
        et_keyboard.setOnTouchListener { v, event ->
            keyboardUtli?.attachTo(et_keyboard)
           //设置是否可以输入小数
            keyboardUtli?.mIsDecimal = true
            false
        }
        et_keyboard2.setOnTouchListener { v, event ->
            keyboardUtli?.attachTo(et_keyboard2)
            keyboardUtli?.mIsDecimal = false
            false
        }

好了,到此,这篇文章也就结束了,如果有错误之处多多指正,毕竟我还不是一个大牛。哈哈哈,Have a wonderful day。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android自定义数字键盘 的相关文章

  • 如何在 Android 中保存相机的临时照片?

    在尝试从相机拍照并将其保存到应用程序的缓存文件夹中时 我没有得到任何可见的结果 应用程序不会崩溃 但在 LogCat 上 当我尝试将 ImageView src 字段设置为刚刚获取的文件的 URI 时 我收到此消息 09 17 14 03
  • 谷歌坐标认证

    当我尝试连接到 Google 坐标时 总是出现异常GoogleAuthException 我拥有 Google 地图协调中心许可证 我确实使用我的包应用程序名称和 SHA1 在 google 控制台中创建了我的客户端 ID 我将权限添加到清
  • Adobe 是否为其 PDF 阅读器提供 Android SDK 或 API? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我希望能够在我们的应用程序内的视图中显示本地 PDF 文件 在 Android 4 03 下的平板电脑上运行 目前 我们将 Adob eR
  • 在画布上绘图

    我正在编写一个 Android 应用程序 它可以在视图的 onDraw 事件上直接绘制到画布上 我正在绘制一些涉及单独绘制每个像素的东西 为此我使用类似的东西 for int x 0 x lt xMax x for int y 0 y lt
  • 在 java 类和 android 活动之间传输时音频不清晰

    我有一个android活动 它连接到一个java类并以套接字的形式向它发送数据包 该类接收声音数据包并将它们扔到 PC 扬声器 该代码运行良好 但在 PC 扬声器中播放声音时会出现持续的抖动 中断 安卓活动 public class Sen
  • Android SIP 来电使用带有广播接收器的服务

    大家好 其实我正在尝试创建一个应用程序 支持基于 SIP 通过互联网进行音频呼叫 这里使用本机 sip 我遇到了来电问题 我已经完成了服务的注册部分 但是在接听电话时我无法接听电话 请帮助我 Service file package exa
  • 无法访问 com.google.android.gms.internal.zzbfm 的 zzbfm 类文件未找到

    我正在将我的 Android 应用程序项目从GCM to FCM 为此 我使用 Android Studio 中的 Firebase 助手工具 并遵循 Google 开发人员指南中的说明 一切都很顺利 并将我的应用程序代码更改为FCM根据助
  • Android:捕获的图像未显示在图库中(媒体扫描仪意图不起作用)

    我遇到以下问题 我正在开发一个应用程序 用户可以在其中拍照 附加到帖子中 并将图片保存到外部存储中 我希望这张照片也显示在图片库中 并且我正在使用媒体扫描仪意图 但它似乎不起作用 我在编写代码时遵循官方的Android开发人员指南 所以我不
  • 发布android后更改应用内购买项目的价格

    在 Google Play 上发布后 是否可以更改应用内购买商品的价格 我假设该应用程序也已发布 完整的在线文档位于http developer android com http developer android com也http sup
  • 在gradle插件中获取应用程序变体的包名称

    我正在构建一个 gradle 插件 为每个应用程序变体添加一个新任务 此新任务需要应用程序变体的包名称 这是我当前的代码 它停止使用最新版本的 android gradle 插件 private String getPackageName
  • JavaMail 只获取新邮件

    我想知道是否有一种方法可以在javamail中只获取新消息 例如 在初始加载时 获取收件箱中的所有消息并存储它们 然后 每当应用程序再次加载时 仅获取新消息 而不是再次重新加载它们 javamail 可以做到这一点吗 它是如何工作的 一些背
  • 如何在PreferenceActivity中添加工具栏

    我已经使用首选项创建了应用程序设置 但我注意到 我的 PreferenceActivity 中没有工具栏 如何将工具栏添加到我的 PreferenceActivity 中 My code 我的 pref xml
  • 如何使用InputConnectionWrapper?

    我有一个EditText 现在我想获取用户对此所做的所有更改EditText并在手动将它们插入之前使用它们EditText 我不希望用户直接更改中的文本EditText 这只能由我的代码完成 例如通过使用replace or setText
  • Android 中麦克风的后台访问

    是否可以通过 Android 手机上的后台应用程序 服务 持续监控麦克风 我想做的一些想法 不断聆听背景中的声音信号 收到 有趣的 音频信号后 执行一些网络操作 如果前台应用程序需要的话 后台应用程序必须能够智能地放弃对麦克风的访问 除非可
  • .isProviderEnabled(LocationManager.NETWORK_PROVIDER) 在 Android 中始终为 true

    我不知道为什么 但我的变量isNetowrkEnabled总是返回 true 我的设备上是否启用互联网并不重要 这是我的GPSTracker class public class GPSTracker extends Service imp
  • 增加活动的屏幕亮度

    显然 Android 操作系统中至少有三种不同的技术可以改变屏幕亮度 其中两个在纸杯蛋糕之后不再起作用 而第三个被接受的技术显然有一个错误 我想在单视图活动开始时增加屏幕亮度 然后在活动结束时将亮度恢复为用户设置 没有按钮 没有第二个视图或
  • 将两个文本视图并排放置在布局中

    我有两个文本视图 需要在布局中并排放置 并且必须遵守两条规则 Textview2 始终需要完整显示 如果布局中没有足够的空间 则必须裁剪 Textview1 例子 文本视图1 文本视图2 Teeeeeeeeeeeeeeeeeextview1
  • android sdk 的位置尚未在 Windows 操作系统的首选项中设置

    在 Eclipse 上 我转到 windows gt Android SDK 和 AVD Manager 然后弹出此消息 Android sdk 的位置尚未在首选项中设置 进入首选项 在侧边栏找到 Android 然后会出现一个 SDK 位
  • 如何将 google+ 登录集成到我的 Android 应用程序中?

    大家好 实际上我需要通过我的应用程序从 google 登录人们 现在我阅读了 google 上的文档 其中指出 要允许用户登录 请将 Google Sign In 集成到您的应用中 初始化 GoogleApiClient 对象时 请求 PL
  • 按日期对 RecyclerView 进行排序

    我正在尝试按日期对 RecyclerView 进行排序 但我尝试了太多的事情 我不知道现在该尝试什么 问题就出在这条线上适配器 notifyDataSetChanged 因为如果我不放 不会显示错误 但也不会更新 recyclerview

随机推荐

  • 【软考高项笔记】第2章 信息技术发展2.2 新一代信息技术及应用(★)

    2 2 新一代信息技术及应用 xff08 xff09 2 2 1 物联网IOT 通过信息传感设备 xff0c 将物品和互联网相连接 xff0c 进行信息交换和通信 1 技术基础 物联网架构 感知层 xff1a 传感器 网络层 xff1a 互
  • Ubuntu12.04的汉化

    博主装上了Ubuntu12 04后进入系统才发现是英文版 xff0c 看着挺费劲的 xff0c 所以需要汉化一下 本文适用于ubuntu 12 04英文版的系统 1 进入ubuntu系统 xff0c 在顶部齿状标志找到system 2 在p
  • freertos优化版printf、sprintf、snprintf

    优化版printf sprintf snprintf printf stdarg c 当调用标准 C 库函数时 xff0c 栈空间使用量可能会急剧上升 xff0c 特别是 IO 与字符串处理函数 xff0c 比如 sprintf 在 Fre
  • 分享一下我参加开发者大会以来自己的总结(仅供参考)

    手机游戏设计 1选材类型符合移动平台特性 2剧情背景知名度高 3选材定义自己的用户 xff0c 用户觉得游戏的玩法 游戏设计法则 xff08 无需全部实现 xff0c 根据自己游戏类型找和适合法则结合 xff09 法则 1 xff1a 富有
  • 时钟周期、机器周期、指令周期的概念及三者之间的关系;定时器及计数器

    时钟周期 时钟周期也称为振荡周期 xff0c 定义为时钟脉冲的倒数 可以这样来理解 xff0c 时钟周期就是单片机外接晶振的倒数 xff0c 例如12M的晶振 xff0c 它的时间周期就是1 12 us xff0c 是计算机中最基本的 最小
  • 自旋锁-原理

    跟互斥锁一样 xff0c 一个执行单元要想访问被自旋锁保护的共享资源 xff0c 必须先得到锁 xff0c 在访问完共享资源后 xff0c 必须释放锁 如果在获取自旋锁时 xff0c 没有任何执行单元保持该锁 xff0c 那么将立即得到锁
  • openvslam------slam解读系列

    是什么 openvslam是日本先进工业科技研究 xff08 National Institute of Advanced Industrial Science and Technology xff09 所于2019年5月20日开源的视觉S
  • Hadoop编程学习1--WordCount

    span class hljs keyword package span org apache hadoop examples span class hljs keyword import span java io IOException
  • p2p传输实时视频流

    HYP2P是好游科技开发的p2p sdk xff0c 利用nat穿透的原理实现p2p打洞 xff0c 主要用于实时音视频的传输 使用时可以配置成tcp模式或udp模式 xff0c tcp模式会自动帮您解决丢包 乱序 重传问题 中转模式则是基
  • 笑谈Android图表------MPAndroidChart

    MPAndroidChart是一款基于Android的开源图表库 xff0c MPAndroidChart不仅可以在Android设备上绘制各种统计图表 xff0c 而且可以对图表进行拖动和缩放操作 xff0c 应用起来非常灵活 MPAnd
  • 详谈高大上的图片加载框架Glide -应用篇

    在Android设备上 xff0c 加载网络图片一直是一个头疼的问题 xff0c 因为Android设备种类繁多 xff08 当然最主要的是配置 xff09 xff0c 处理的稍不周到轻则应用卡顿 xff0c 严重者就会出现OOM的 xff
  • 微信小程序开发环境搭建

    微信小程序可谓是今天最火的一个名词了 xff0c 一经出现真是轰炸了整个开发人员 xff0c 当然很多App开发人员有了一个担心 xff0c 微信小程序的到来会不会给移动端App带来一个寒冬 xff0c 身为一个Android开发者我是不相
  • 实现APP定位功能

    源码传送门 若你不小心点击进入GitHub了捎带给个star 前言 最近更新项目中用的百度定位SDK时遇见了一个奇葩的问题 当升级SDK后百度定位一直返回505 通过百度定位官网查看该码表示AK非法或者不存在 很纠结 于是自己又写了一个de
  • Linux系统命令行创建新文件

    linux命令行创建文件 方法有许多 xff0c 下面简单介绍一下 方法1 使用cat命令 cat span class token operator gt span sample1 span class token punctuation
  • Java利器之UML类图详解

    前言 UML xff08 Unified Modeling Language xff09 中文统一建模语言 xff0c 是一种开放的方法 xff0c 用于说明 可视化 构建和编写一个正在开发的 面向对象的 软件密集系统的制品的开放方法 UM
  • 从零开始学习Linux部署Java web项目

    前言 最近越来越发现需要学习的东西太多了 xff0c 前几天公司服务器出现问题 xff0c 需要对服务器硬件进行维护 xff0c 当然服务器上的服务需要部署到另一个服务器上 这对于我来说是很陌生的 xff0c 虽然这件工作没有让我去做 xf
  • 致敬我奋起直追的2016

    前言 其实当用奋起直追这个词语形容我的2016时 xff0c 自己一度怀疑是不是配得上这个词语 虽然2016成长了不少 xff0c 但是依然没有达到我想要的效果 在学习过程中不断出现越学越倒退的感觉 还偶尔会出现一些恐惧感 不过庆幸的是 x
  • 微信小程序分页加载

    分页加载功能大家遇到的应该会经常遇到 xff0c 应用场景也很多 xff0c 例如微博 xff0c QQ xff0c 微信朋友圈以及新闻类应用 xff0c 都会有分页加载的功能 xff0c 这不仅节省了我们用户的流量 xff0c 还提升了用
  • ReactNative ViewPageAndroid组件详解

    源码传送门 在我们开发Android的时候 xff0c ViewPage这个控件的使用频率还是很高的 xff0c 最简单的就是制作引导页 xff0c 应用程序的主界面等 xff0c 在ReactNative开发中实现该功能的组件是ViewP
  • Android自定义数字键盘

    好久没有写Android的文章了 xff0c 有两三个月多了吧 xff0c 刚开始搞微信小程序 xff0c 后来又开搞ReactNative 现在又兴奋的开搞AI机器学习的东西 xff0c 感觉挺有意思的 xff0c 不过AI与其它的东西相