TextView上的addFontWeightStyle NoSuchMethodException

时间:2019-02-15 11:28:14

标签: android material-design androidx

我正在为项目使用 Androidx 库,并且我想为 textview 设置 font ,所以当我应用任何字体时而不是系统给我的任何 Textview 组件

  

TypefaceCompatApi21Impl:java.lang.NoSuchMethodException       java.lang.NoSuchMethodException:addFontWeightStyle [类java.lang.String,int,boolean]

这种类型的运行时错误,但应用没有崩溃。

那么如何克服这个错误。

注意:它将在没有android x依赖的情况下正常运行。

我的代码下方:

<androidx.appcompat.widget.AppCompatTextView
        android:id="@+id/menu_tv_title"
        style="@style/font_work_sans_medium"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:maxLines="1"
        android:ellipsize="end"
        android:paddingEnd="@dimen/_12sdp"
        android:paddingStart="@dimen/_12sdp"
        android:textColor="@android:color/black"
        android:textSize="17sp"
        android:gravity="center"
        tools:text="title"
        tools:visibility="gone"/>

这是样式

<style name="font_work_sans_medium" parent="@android:style/TextAppearance.Small">
    <item name="android:fontFamily">@font/work_sans_medium</item>
</style>

我还通过编程这样设置字体

var typeFace: Typeface? = ResourcesCompat.getFont(context, R.font.work_sans_bold)
    getTitleView().setTypeface(typeFace, Typeface.NORMAL)

仍然收到此错误

9 个答案:

答案 0 :(得分:26)

对于一些研究,我发现该解决方案可能对我有帮助,实际上我使用的是不稳定的alpha依赖项,因此我将AndroidX的lib版本降级了

我正在使用这种依赖性

package com.example.veekalp.imageupload;

import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;

import net.gotev.uploadservice.MultipartUploadRequest;
import net.gotev.uploadservice.UploadNotificationConfig;

import java.io.IOException;
import java.util.UUID;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    //Declaring views
    private Button buttonChoose;
    private Button buttonUpload;
    private ImageView imageView;
    private EditText editText;

    //Image request code
    private int PICK_IMAGE_REQUEST = 1;

    //storage permission code
    private static final int STORAGE_PERMISSION_CODE = 123;

    //Bitmap to get image from gallery
    private Bitmap bitmap;

    //Uri to store the image uri
    private Uri filePath;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //Requesting storage permission
        requestStoragePermission();

        //Initializing views
        buttonChoose = (Button) findViewById(R.id.buttonChoose);
        buttonUpload = (Button) findViewById(R.id.buttonUpload);
        imageView = (ImageView) findViewById(R.id.imageView);
        editText = (EditText) findViewById(R.id.editTextName);

        //Setting clicklistener
        buttonChoose.setOnClickListener(this);
        buttonUpload.setOnClickListener(this);
    }


    /*
    * This is the method responsible for image upload
    * We need the full image path and the name for the image in this method
    * */
    public void uploadMultipart() {
        //getting name for the image
        String name = editText.getText().toString().trim();

        //getting the actual path of the image
        String path = getPath(filePath);

        //Uploading code
        try {
            String uploadId = UUID.randomUUID().toString();

            //Creating a multi part request
            new MultipartUploadRequest(this, uploadId, Constants.UPLOAD_URL)
                    .addFileToUpload(path, "image") //Adding file
                    .addParameter("name", name) //Adding text parameter to the request
                    .setNotificationConfig(new UploadNotificationConfig())
                    .setMaxRetries(2)
                    .startUpload(); //Starting the upload

        } catch (Exception exc) {
            Toast.makeText(this, exc.getMessage(), Toast.LENGTH_SHORT).show();
        }
    }


    //method to show file chooser
    private void showFileChooser() {
        Intent intent = new Intent();
        intent.setType("image/*");
        intent.setAction(Intent.ACTION_GET_CONTENT);
        startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_IMAGE_REQUEST);
    }

    //handling the image chooser activity result
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data != null && data.getData() != null) {
            filePath = data.getData();
            try {
                bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), filePath);
                imageView.setImageBitmap(bitmap);

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    //method to get the file path from uri
    public String getPath(Uri uri) {
        Cursor cursor = getContentResolver().query(uri, null, null, null, null);
        cursor.moveToFirst();
        String document_id = cursor.getString(0);
        document_id = document_id.substring(document_id.lastIndexOf(":") + 1);
        cursor.close();

        cursor = getContentResolver().query(
                android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                null, MediaStore.Images.Media._ID + " = ? ", new String[]{document_id}, null);
        cursor.moveToFirst();
        String path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
        cursor.close();

        return path;
    }


    //Requesting permission
    private void requestStoragePermission() {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)
            return;

        if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_EXTERNAL_STORAGE)) {
            //If the user has denied the permission previously your code will come to this block
            //Here you can explain why you need this permission
            //Explain here why you need this permission
        }
        //And finally ask for the permission
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, STORAGE_PERMISSION_CODE);
    }


    //This method will be called when the user will tap on allow or deny
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

        //Checking the request code of our request
        if (requestCode == STORAGE_PERMISSION_CODE) {

            //If permission is granted
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                //Displaying a toast
                Toast.makeText(this, "Permission granted now you can read the storage", Toast.LENGTH_LONG).show();
            } else {
                //Displaying another toast if permission is not granted
                Toast.makeText(this, "Oops you just denied the permission", Toast.LENGTH_LONG).show();
            }
        }
    }


    @Override
    public void onClick(View v) {
        if (v == buttonChoose) {
            showFileChooser();
        }
        if (v == buttonUpload) {
            uploadMultipart();
        }
    }
}

您应该使用它代替

 implementation 'androidx.core:core-ktx:1.1.0-alpha04'
 implementation 'androidx.appcompat:appcompat:1.1.0-alpha02'

答案 1 :(得分:16)

该问题已报告给Android team,并且似乎可以在将来的版本中解决:

根据以下版本的第25条评论

implementation 'androidx.appcompat:appcompat:1.1.0-alpha03'
implementation 'androidx.core:core-ktx:1.1.0-alpha05'

答案 2 :(得分:5)

我从xml文件中删除了这一行,现在可以正常运行了

android:textStyle="bold"

关于 addFontWeightStyle 方法,该方法在API21 Impl中引发NoSuchMethodException

答案 3 :(得分:5)

只需仔细阅读堆栈跟踪-这是AndroidX的问题。似乎androidx.core.graphics.TypefaceCompatApi21Impl()试图通过反射从框架类addFontWeightStyle(lass java.lang.String, int, boolean)内部的某个内部静态解析带有签名android.graphics.FontFamily的方法……事实证明该方法不存在。我在androidx.appcompat.widget.AppCompatAutoCompleteTextView中遇到了同样的问题。在Google修复之前,我们无能为力。

答案 4 :(得分:3)

根据Class.java方法,显然该方法预期是公开的(或者如果不存在,我相信不是这样)并且不公开(请看下面的评论):

private Method getMethod(String name, Class<?>[] parameterTypes, boolean recursivePublicMethods)
        throws NoSuchMethodException {
    if (name == null) {
        throw new NullPointerException("name == null");
    }
    if (parameterTypes == null) {
        parameterTypes = EmptyArray.CLASS;
    }
    for (Class<?> c : parameterTypes) {
        if (c == null) {
            throw new NoSuchMethodException("parameter type is null");
        }
    }
    Method result = recursivePublicMethods ? getPublicMethodRecursive(name, parameterTypes)
                                           : getDeclaredMethodInternal(name, parameterTypes);
    ***// Fail if we didn't find the method or it was expected to be public.***
    if (result == null ||
        (recursivePublicMethods && !Modifier.isPublic(result.getAccessFlags()))) {
        throw new NoSuchMethodException(name + " " + Arrays.toString(parameterTypes));
    }
    return result;
}

我相信这是Androidx中的一种错误。

答案 5 :(得分:1)

尝试一下:

 <style name="CutsomFontTextView" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- Customize your theme here. -->
    <item name="android:fontFamily">@font/yourfont</item>
</style>

然后将此主题应用于如下所示的textview

<androidx.appcompat.widget.AppCompatTextView
    android:id="@+id/menu_tv_title"
    android:theme="@style/CutsomFontTextView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_gravity="center"
    android:maxLines="1"
    android:ellipsize="end"
    android:paddingEnd="@dimen/_12sdp"
    android:paddingStart="@dimen/_12sdp"
    android:textColor="@android:color/black"
    android:textSize="17sp"
    android:gravity="center"
    tools:text="title"
    tools:visibility="gone"/>

答案 6 :(得分:1)

您的样式父项是@android:style/TextAppearance.Small,请点击该父项。您只会看到两项

<item name="textSize">14sp</item>
        <item name="textColor">?textColorSecondary</item>

因此错误是正确的。该样式内部没有fontFamily属性。

尝试将父主题更改为

<style name="font_work_sans_medium" parent="Base.Theme.AppCompat.Light.DarkActionBar">
 <item name="android:fontFamily">@font/work_sans_medium</item>
</style>

答案 7 :(得分:1)

以编程方式设置字体时,您是否尝试过删除最后一个参数?

getTitleView().setTypeface(typeFace)

代替

getTitleView().setTypeface(typeFace, Typeface.NORMAL)

内部正在使用fontStyle

答案 8 :(得分:0)

此处是编码的新手,但是如果您通过 Build /' Edit Libraries and Dependencies (编辑库和依赖项)”进入工具栏,然后单击建议,然后对 androidx.appcompat:appcompat:XXX 单击更新,它将解决该错误,而不是在build.gradle文件中进行:)