当Java工作正常时,Kotlin在PasswordTransformationMethod崩溃

时间:2018-06-03 14:46:27

标签: java android kotlin kotlin-android-extensions

下面的代码在Kotlin / Android中崩溃,底部提供了堆栈跟踪。它是从Java / Android转换而来的,并没有出现这样的问题。还提供了原始Java代码。当我尝试将字符添加到密码字段时发生崩溃。编辑现有字符效果很好。

我有两个问题:

  1. Kotlin用Kotlin的CharSequence替换java.lang.CharSequence的动机是什么?这两个是完全不同的,我怀疑它会导致崩溃。
  2. 有没有办法让它在Kotlin工作?
  3. Kotlin代码崩溃了Android的Paint

            mPwd!!.transformationMethod = object : PasswordTransformationMethod() {
            override fun getTransformation(source: CharSequence, view: View): CharSequence {
                return PasswordCharSequence(source)
            }
            internal inner class PasswordCharSequence(private val source: CharSequence)// Store char sequence
                : CharSequence {
    
                val mSource = source
                public override val length = mSource.length
    
                init {
                    App.d(TAG, "SOURCE " + mSource + " " + length)
                }
                override fun get(index: Int): Char {
                    App.d(TAG, "SOURCE IND " + index + " " + mSource.length)
                    return if (mChkUnmask!!.isChecked) mSource.get(index) else '*'
                }
                override fun subSequence(start: Int, end: Int): CharSequence {
                    App.d(TAG, "SOURCE SUB " + start + " " + end)
                    return mSource.subSequence(start, end) // Return default
                }
            }
        }
    

    完美运行的原始Java代码

            mPwd.setTransformationMethod(new PasswordTransformationMethod() {
    
            @Override
            public CharSequence getTransformation(CharSequence source, View view) {
                return new PasswordCharSequence(source);
            }
    
            class PasswordCharSequence implements CharSequence {
                private CharSequence mSource;
                public PasswordCharSequence(CharSequence source) {
                    mSource = source; // Store char sequence
                }
                public char charAt(int index) {
                    return mChkUnmask.isChecked()?mSource.charAt(index):'*';
                }
                public int length() {
                    return mSource.length(); // Return default
                }
                public CharSequence subSequence(int start, int end) {
                    return mSource.subSequence(start, end); // Return default
                }
            }
        });
    

    从Logcat堆栈跟踪

    06-03 00:35:08.143 16694 16694 E AndroidRuntime: java.lang.IndexOutOfBoundsException
    06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.graphics.Paint.getRunAdvance(Paint.java:2986)
    06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.text.TextLine.handleText(TextLine.java:719)
    06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.text.TextLine.handleRun(TextLine.java:873)
    06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.text.TextLine.measureRun(TextLine.java:387)
    06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.text.TextLine.measure(TextLine.java:277)
    06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.text.TextLine.metrics(TextLine.java:251)
    06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.text.Layout.getLineExtent(Layout.java:1072)
    06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.text.Layout.getLineWidth(Layout.java:1038)
    06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.widget.TextView.desired(TextView.java:8142)
    06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.widget.TextView.onMeasure(TextView.java:8208)
    06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.view.View.measure(View.java:21051)
    06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:715)
    06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:461)
    06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.view.View.measure(View.java:21051)
    06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:715)
    06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:461)
    06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.view.View.measure(View.java:21051)
    06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6459)
    06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
    06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.support.v7.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:141)
    06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.view.View.measure(View.java:21051)
    06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6459)
    06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.support.v7.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java:400)
    

    来自Log.d(...)的程序输出

    10这里是CharSequence长度。第一位数 - 当前指数。当我尝试从键盘添加索引为9的字符时发生崩溃。它从未被添加,并且没有出现在

    下面的输出中
    06-03 00:35:08.121 16694 16694 D GAC-STORE: SOURCE IND 810
    06-03 00:35:08.121 16694 16694 D GAC-STORE: SOURCE IND 710
    06-03 00:35:08.121 16694 16694 D GAC-STORE: SOURCE IND 610
    06-03 00:35:08.121 16694 16694 D GAC-STORE: SOURCE IND 510
    06-03 00:35:08.121 16694 16694 D GAC-STORE: SOURCE IND 410
    06-03 00:35:08.121 16694 16694 D GAC-STORE: SOURCE IND 310
    06-03 00:35:08.121 16694 16694 D GAC-STORE: SOURCE IND 210
    06-03 00:35:08.121 16694 16694 D GAC-STORE: SOURCE IND 110
    06-03 00:35:08.121 16694 16694 D GAC-STORE: SOURCE IND 010
    06-03 00:35:08.121 16694 16694 D GAC-STORE: SOURCE IND 010
    06-03 00:35:08.121 16694 16694 D GAC-STORE: SOURCE IND 110
    06-03 00:35:08.121 16694 16694 D GAC-STORE: SOURCE IND 210
    06-03 00:35:08.121 16694 16694 D GAC-STORE: SOURCE IND 310
    06-03 00:35:08.121 16694 16694 D GAC-STORE: SOURCE IND 410
    06-03 00:35:08.121 16694 16694 D GAC-STORE: SOURCE IND 510
    06-03 00:35:08.122 16694 16694 D GAC-STORE: SOURCE IND 610
    06-03 00:35:08.122 16694 16694 D GAC-STORE: SOURCE IND 710
    06-03 00:35:08.122 16694 16694 D GAC-STORE: SOURCE IND 810
    06-03 00:35:08.122 16694 16694 D GAC-STORE: SOURCE IND 010
    06-03 00:35:08.122 16694 16694 D GAC-STORE: SOURCE IND 110
    06-03 00:35:08.122 16694 16694 D GAC-STORE: SOURCE IND 210
    06-03 00:35:08.122 16694 16694 D GAC-STORE: SOURCE IND 310
    06-03 00:35:08.122 16694 16694 D GAC-STORE: SOURCE IND 410
    06-03 00:35:08.122 16694 16694 D GAC-STORE: SOURCE IND 510
    06-03 00:35:08.122 16694 16694 D GAC-STORE: SOURCE IND 610
    06-03 00:35:08.122 16694 16694 D GAC-STORE: SOURCE IND 710
    06-03 00:35:08.122 16694 16694 D GAC-STORE: SOURCE IND 810
    06-03 00:35:08.122 16694 16694 D GAC-STORE: SOURCE IND 810
    

    mPwd的布局

    <EditText
        android:id="@+id/txtDlgPwd"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/chkStorePwd"
        android:hint ="Ecnryption Password"
        android:maxLines="1"
        android:singleLine="true"
        android:inputType="textPassword|textNoSuggestions"
        android:imeOptions="actionDone"
        android:layout_marginLeft="10dp"
        android:layout_marginTop="20dp"
        android:textSize="15sp"/>
    

3 个答案:

答案 0 :(得分:1)

幸运的是,Android / Kotlin允许在单个项目中混合使用Java和Kotlin文件。我用它来解决这个问题。

为密码处理创建了一个Java类。请注意,CharSequence是一个本地Java类,这有所不同。

import java.lang.CharSequence;

public class PasswordHandler implements CharSequence {

    private CharSequence mSource;
    private Switch mUnmask;

    public PasswordHandler(CharSequence source, Switch unmask) {
        mSource = source;
        mUnmask = unmask;
    }

    public char charAt(int index) {
        return mUnmask.isChecked()?mSource.charAt(index):'*';
    }
    public int length() {
        return mSource.length();
    }
    public CharSequence subSequence(int start, int end) {
        return mSource.subSequence(start, end);
    }

    @NonNull
    @Override
    public String toString() {
        String star = new String();
        int l = length();
        if (!mUnmask.isChecked()) {
            while (l-- > 0){
                star += "*";
            }
        }
        return mUnmask.isChecked()? mSource.toString():star;
    }
}

在Kotlin的类中的getTransfromation方法中实例化此类。 Kotlin编译器这次很好。崩溃不再发生。我仍然希望看到纯粹的Kotlin解决方案。

mPwd!!.transformationMethod = object : PasswordTransformationMethod() {
            override fun getTransformation(source: CharSequence, view: View): CharSequence {
                return PasswordHandler(source, mChkUnmask)
            }

        } 

答案 1 :(得分:0)

发生这种情况是因为在初始化期间设置了 length 字段。尝试使用 getter

internal class PasswordCharSequence(private val source: CharSequence) : CharSequence {

    override val length: Int
        get() = source.length

    // Rest implementation

}

答案 2 :(得分:-1)

class CustomPasswordSymbole : PasswordTransformationMethod() {
    override fun getTransformation(source: CharSequence?, view: View?): CharSequence {
        return PasswordCharSequence(source)
    }

    class PasswordCharSequence(source: CharSequence?) : CharSequence{
        val mSource = source
        override val length: Int=6 ///manually enter lenght of your password

        override fun get(index: Int): Char {
            return '*'
         }

        override fun subSequence(startIndex: Int, endIndex: Int): CharSequence {
            return  mSource!!.subSequence(startIndex, endIndex)
        }
    }
}