[解決済み] android:DrawableRightを使ってButtonやTextViewでVectorDrawableを使用することは可能でしょうか?
質問
テキストビューやイメージビューでVectorDrawableアセットを使用すると、 "android:DrawableRight" / "android:DrawableEnd" / "android:DrawableStart" / "android:DrawableLeft" を使用するとランタイム クラッシュが発生しました。
アプリは警告を出さずに正常にコンパイルされます。
を使っています。
- Gradle 1.5
- サポートライブラリ 23.2 ('com.android.support:appcompat-v7:23.2.0')
しかし、私が発見したのは、このようなクラッシュなしに、Java で SVG をプログラム的に割り当てることができるということです。
TextView tv = (TextView) findViewById(R.id.textView);
tv.setCompoundDrawablesWithIntrinsicBounds(null,null, getResources().getDrawable(R.drawable.ic_accessible_white_36px),null);
(これは23.2のサポートライブラリのバグだと思われます)
しかし、SVGアセットにdrawableRightなどを使用することは可能なのでしょうか?
以下は私のレイアウトです。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="au.com.angryitguy.testsvg.MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableRight="@drawable/ic_accessible_white_36px"
android:background="@color/colorPrimary"
android:textColor="#FFFFFF"
android:textSize="22sp"
android:text="Hello World!"/>
</RelativeLayout>
以下は私のアクティビティです。
package au.com.angryitguy.testsvg;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
Googleのマテリアルデザインサイトにある、修正されていないVectorDrawableのアセットです。
<vector android:height="24dp" android:viewportHeight="24.0"
android:viewportWidth="24.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FFFFFF" android:pathData="M12,4m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"/>
<path android:fillColor="#FFFFFF" android:pathData="M19,13v-2c-1.54,0.02 -3.09,-0.75 -4.07,-1.83l-1.29,-1.43c-0.17,-0.19 -0.38,-0.34 -0.61,-0.45 -0.01,0 -0.01,-0.01 -0.02,-0.01L13,7.28c-0.35,-0.2 -0.75,-0.3 -1.19,-0.26C10.76,7.11 10,8.04 10,9.09L10,15c0,1.1 0.9,2 2,2h5v5h2v-5.5c0,-1.1 -0.9,-2 -2,-2h-3v-3.45c1.29,1.07 3.25,1.94 5,1.95zM12.83,18c-0.41,1.16 -1.52,2 -2.83,2 -1.66,0 -3,-1.34 -3,-3 0,-1.31 0.84,-2.41 2,-2.83L9,12.1c-2.28,0.46 -4,2.48 -4,4.9 0,2.76 2.24,5 5,5 2.42,0 4.44,-1.72 4.9,-4h-2.07z"/>
</vector>
以下は私のアプリのbuild.gradleです。
apply plugin: 'com.android.application'
android {
compileSdkVersion 23
buildToolsVersion "23.0.2"
defaultConfig {
applicationId "au.com.angryitguy.testsvg"
minSdkVersion 16
targetSdkVersion 23
versionCode 1
versionName "1.0"
// Stops the Gradle plugin’s automatic rasterization of vectors
generatedDensities = []
}
// Flag to tell aapt to keep the attribute ids around
aaptOptions {
additionalParameters "--no-version-vectors"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.2.0'
}
以下はクラッシュの様子です。(テキストビューを参照する inflate エラーに注意してください)。
java.lang.RuntimeException: Unable to start activity ComponentInfo{
au.com.angryitguy.testsvg/au.com.angryitguy.testsvg.MainActivity}:
android.view.InflateException: Binary XML file line #13:
Error inflating class TextView
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2059)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
at android.app.ActivityThread.access$600(ActivityThread.java:130)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
...
Caused by: android.view.InflateException:
Binary XML file line #13: Error inflating class TextView
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:746)
at android.view.LayoutInflater.inflate(LayoutInflater.java:489)
at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
at android.view.LayoutInflater.inflate(LayoutInflater.java:352)
at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:267)
at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:129)
at au.com.angryitguy.testsvg.MainActivity.onCreate(MainActivity.java:14)
at android.app.Activity.performCreate(Activity.java:5008)
...
Caused by: android.content.res.Resources$NotFoundException:
File res/drawable/ic_accessible_white_36px.xml from drawable resource ID #0x7f02004b
at android.content.res.Resources.loadDrawable(Resources.java:1918)
at android.content.res.TypedArray.getDrawable(TypedArray.java:601)
at android.widget.TextView.<init>(TextView.java:622)
at android.support.v7.widget.AppCompatTextView.<init>(AppCompatTextView.java:60)
at android.support.v7.widget.AppCompatTextView.<init>(AppCompatTextView.java:56)
at android.support.v7.app.AppCompatViewInflater.createView(AppCompatViewInflater.java:103)
at android.support.v7.app.AppCompatDelegateImplV7.createView(AppCompatDelegateImplV7.java:963)
at android.support.v7.app.AppCompatDelegateImplV7.onCreateView(AppCompatDelegateImplV7.java:1022)
at android.support.v4.view.LayoutInflaterCompatHC$FactoryWrapperHC.onCreateView(LayoutInflaterCompatHC.java:44)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:675)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:746)
at android.view.LayoutInflater.inflate(LayoutInflater.java:489)
at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
at android.view.LayoutInflater.inflate(LayoutInflater.java:352)
at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:267)
at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:129)
at au.com.angryitguy.testsvg.MainActivity.onCreate(MainActivity.java:14)
at android.app.Activity.performCreate(Activity.java:5008)
...
Caused by: org.xmlpull.v1.XmlPullParserException:
Binary XML file line #1: invalid drawable tag vector
at android.graphics.drawable.Drawable.createFromXmlInner(Drawable.java:877)
at android.graphics.drawable.Drawable.createFromXml(Drawable.java:818)
at android.content.res.Resources.loadDrawable(Resources.java:1915)
at android.content.res.TypedArray.getDrawable(TypedArray.java:601)
at android.widget.TextView.<init>(TextView.java:622)
at android.support.v7.widget.AppCompatTextView.<init>(AppCompatTextView.java:60)
at android.support.v7.widget.AppCompatTextView.<init>(AppCompatTextView.java:56)
at android.support.v7.app.AppCompatViewInflater.createView(AppCompatViewInflater.java:103)
at android.support.v7.app.AppCompatDelegateImplV7.createView(AppCompatDelegateImplV7.java:963)
at android.support.v7.app.AppCompatDelegateImplV7.onCreateView(AppCompatDelegateImplV7.java:1022)
at android.support.v4.view.LayoutInflaterCompatHC$FactoryWrapperHC.onCreateView(LayoutInflaterCompatHC.java:44)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:675)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:746)
at android.view.LayoutInflater.inflate(LayoutInflater.java:489)
at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
at android.view.LayoutInflater.inflate(LayoutInflater.java:352)
at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:267)
at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:129)
at au.com.angryitguy.testsvg.MainActivity.onCreate(MainActivity.java:14)
at android.app.Activity.performCreate(Activity.java:5008)
...
どのように解決するのですか?
<ブロッククオートSVGアセットにdrawableRightなどを使用することは可能でしょうか?
可能です。
AppCompatTextView
現在
サポート
app:drawableLeftCompat
,
app:drawableTopCompat
,
app:drawableRightCompat
,
app:drawableBottomCompat
,
app:drawableStartCompat
と
app:drawableEndCompat
のようなバックポートされた描画可能なタイプをサポートする、複合描画可能です。
VectorDrawableCompat
.
これをgradleファイルにインクルードします。
implementation 'androidx.appcompat:appcompat:1.1.0-alpha01'
テキストビューでは
app:drawableLeftCompat
app:drawableStartCompat
ボタンで app:drawableLeftCompat や app:drawableStartCompat を使用中に問題が発生した場合は、ライブラリを次のように更新する必要があります。
androidx.appcompat:appcompat:1.2.0-alpha01 に更新する必要があります。
にバグがあったそうです。
androidx.appcompat:appcompat:1.1.0-alpha01
を見ることができます。 ドキュメント
まだアップデートしたくないという人も
Google はこの問題についてすぐに何かするつもりはないようなので、私はすべてのアプリに対してより強固な再利用可能なソリューションを考え出さなければなりませんでした。
-
最初にカスタム テキストビュー 属性を追加します。 を参照してください。 :
<resources> <declare-styleable name="CustomTextView"> <attr name="drawableStartCompat" format="reference"/> <attr name="drawableEndCompat" format="reference"/> <attr name="drawableTopCompat" format="reference"/> <attr name="drawableBottomCompat" format="reference"/> </declare-styleable> </resources>
-
次に、このようなカスタムTextViewクラスを作成します。
import android.content.Context; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; import android.os.Build; import android.support.v7.content.res.AppCompatResources; import android.support.v7.widget.AppCompatTextView; import android.util.AttributeSet; public class CustomTextView extends AppCompatTextView { public CustomTextView(Context context) { super(context); } public CustomTextView(Context context, AttributeSet attrs) { super(context, attrs); initAttrs(context, attrs); } public CustomTextView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initAttrs(context, attrs); } void initAttrs(Context context, AttributeSet attrs) { if (attrs != null) { TypedArray attributeArray = context.obtainStyledAttributes( attrs, R.styleable.CustomTextView); Drawable drawableStart = null; Drawable drawableEnd = null; Drawable drawableBottom = null; Drawable drawableTop = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { drawableStart = attributeArray.getDrawable(R.styleable.CustomTextView_drawableStartCompat); drawableEnd = attributeArray.getDrawable(R.styleable.CustomTextView_drawableEndCompat); drawableBottom = attributeArray.getDrawable(R.styleable.CustomTextView_drawableBottomCompat); drawableTop = attributeArray.getDrawable(R.styleable.CustomTextView_drawableTopCompat); } else { final int drawableStartId = attributeArray.getResourceId(R.styleable.CustomTextView_drawableStartCompat, -1); final int drawableEndId = attributeArray.getResourceId(R.styleable.CustomTextView_drawableEndCompat, -1); final int drawableBottomId = attributeArray.getResourceId(R.styleable.CustomTextView_drawableBottomCompat, -1); final int drawableTopId = attributeArray.getResourceId(R.styleable.CustomTextView_drawableTopCompat, -1); if (drawableStartId != -1) drawableStart = AppCompatResources.getDrawable(context, drawableStartId); if (drawableEndId != -1) drawableEnd = AppCompatResources.getDrawable(context, drawableEndId); if (drawableBottomId != -1) drawableBottom = AppCompatResources.getDrawable(context, drawableBottomId); if (drawableTopId != -1) drawableTop = AppCompatResources.getDrawable(context, drawableTopId); } // to support rtl setCompoundDrawablesRelativeWithIntrinsicBounds(drawableStart, drawableTop, drawableEnd, drawableBottom); attributeArray.recycle(); } } }
-
これで、カスタム属性によって、どんなレイアウトでも簡単に使えるようになりました。
<YOUR_VIEW_PACKAGE.CustomTextView android:id="@+id/edt_my_edit_text" android:layout_width="wrap_content" android:layout_height="wrap_content" app:drawableStartCompat="@drawable/your_vector_drawable" <!-- vector drawable --> app:drawableEndCompat="@drawable/your_vector_drawable" <!-- vector drawable --> app:drawableTopCompat="@drawable/your_vector_drawable" <!-- vector drawable --> app:drawableBottomCompat="@drawable/your_vector_drawable" <!-- vector drawable --> />
- 似たようなことは ボタン , 編集テキスト と ラジオボタン はTextViewから派生しているため
お役に立てれば幸いです :)
関連
-
Eclipse問題 アクセス制限。タイプ 'SunJCE' が API でないことを解決し、/jdk ディレクトリにある /jre と jre の違いについて理解を深める。
-
Eclipse の問題 アクセス制限。タイプ 'jfxrt' はAPI解決されていません。
-
SLF4J: クラス・パスに複数のSLF4Jバインディングが含まれています。
-
StringBuilderが投げるArrayIndexOutOfBoundsExceptionの探索
-
java -jarコマンドでパッケージを実行すると、無効または破損したjarfile xxxx.jarが表示される。
-
java.sql.SQLException: 結果セットの開始前
-
java send https request prompt java.security.cert.について。
-
Java基礎編 - オブジェクト指向
-
Javaがリソースリークに遭遇した:'input'が閉じない 解決方法
-
[解決済み] serialVersionUIDとは何ですか、またなぜそれを使用する必要がありますか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
NullPointerException - java.lang.
-
XMLファイル操作時のjava.util.NoSuchElementExceptionを解決する方法。
-
executeQuery()でデータ操作文が発行できない。解決方法
-
SLF4J: クラス・パスに複数のSLF4Jバインディングが含まれています。
-
Jsoup-Crawlingの動作
-
SpringBoot 起動エラー java.nio.charset.MalformedInputException: 入力長 = 2 解決
-
java.sql.SQLException: 結果セットの開始前
-
java send https request prompt java.security.cert.について。
-
htmlとwordの相互変換の実装(画像あり)
-
[解決済み] ImageButtonにテキストを表示するには?