web-dev-qa-db-ja.com

セレクターを使用してandroid

プログラムで行うのではなく、xmlを使用してtabhostのアイコンに色を付けたい(とにかくそれを行うことができなかった)...だから私はSOでこのスレッドを見つけました: Android imageviewは色合いを変更してボタンクリックをシミュレートします

それはかなり良い解決策のように思えますが、私のプロジェクトでそれを正しく適応させることができませんでした...私は次の変更を行いました:

public class TintableImageView extends ImageView {
private ColorStateList tint;

public TintableImageView(Context context) {
    super(context);
}

//this is the constructor that causes the exception
public TintableImageView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(context, attrs, 0);
}

public TintableImageView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    init(context, attrs, defStyle);
}

//here, obtainStyledAttributes was asking for an array
private void init(Context context, AttributeSet attrs, int defStyle) {
    TypedArray a = context.obtainStyledAttributes(attrs, new int[]{R.styleable.TintableImageView_tint}, defStyle, 0);
    tint = a.getColorStateList(R.styleable.TintableImageView_tint);
    a.recycle();
}

@Override
protected void drawableStateChanged() {
    super.drawableStateChanged();
    if (tint != null && tint.isStateful())
        updateTintColor();
}

public void setColorFilter(ColorStateList tint) {
    this.tint = tint;
    super.setColorFilter(tint.getColorForState(getDrawableState(), 0));
}

private void updateTintColor() {
    int color = tint.getColorForState(getDrawableState(), 0);
    setColorFilter(color);
}

}

@drawable/selector.xmlAndroid:tintを参照することもできなかったため、colors.xmlでこれを行いました。

<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="azulPadrao">#2e7cb4</color>
<drawable name="tab_icon_selector">@drawable/tab_icon_selector</drawable>
</resources>

私のセレクター:

<?xml version="1.0" encoding="utf-8"?>

<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item Android:state_selected="true" Android:tint="#007AFF" />
<item Android:state_focused="true" Android:tint="#007AFF" />
<item Android:state_pressed="true" Android:tint="#007AFF" />
<item Android:tint="#929292" />
</selector>

私のタブレイアウト:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
          Android:orientation="vertical" Android:id="@+id/TabLayout"
          Android:layout_width="fill_parent" Android:layout_height="fill_parent"
          Android:gravity="center" Android:background="@drawable/tab_bg_selector">

<com.myapp.TintableImageView
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:id="@+id/imageView" Android:layout_gravity="center" Android:tint="@drawable/tab_icon_selector"/>
<TextView Android:id="@+id/TabTextView" Android:text="Text"
          Android:layout_width="wrap_content"
          Android:layout_height="wrap_content" Android:textColor="@drawable/tab_text_selector"
          Android:textSize="10dip"
          Android:textStyle="bold" Android:layout_marginTop="2dip"/>

</LinearLayout>

助言がありますか?前もって感謝します

[編集] Android:tintapp:tintを設定した後)が正しいときにxmlns:app="http://schemas.Android.com/apk/res/com.myapp"を使用するためにNumberFormatExceptionを取得していましたが、今は使用していると思いますセレクタが間違った方法で、アイコンが状態に関係なくすべて黒であるため...私はcolors.xml内から<drawable name="tab_icon_selector">@drawable/tab_icon_selector</drawable>を設定しようとしましたが、動作しません

[/編集]

27
Lucas Jota

https://stackoverflow.com/a/18724834/2136792 にある私のソリューションを参照すると、不足していることがいくつかあります。

TintableImageView.Java

@Override
protected void drawableStateChanged() {
    super.drawableStateChanged();
    if (tint != null && tint.isStateful())
        updateTintColor();
}

public void setColorFilter(ColorStateList tint) {
    this.tint = tint;
    super.setColorFilter(tint.getColorForState(getDrawableState(), 0));
}

private void updateTintColor() {
    int color = tint.getColorForState(getDrawableState(), 0);
    setColorFilter(color);
}

drawableStateChanged()は、要素の状態が変化したときに色合いが更新されるようにオーバーライドする必要があります。

ドロアブルからドロアブルを参照することで問題が発生するかどうかはわかりませんが、selector.xmlを「/ res/color」フォルダーに移動して、「@ color/selector.xml」で参照できます(aapt merges /res/values/colors.xmlと/ res/colorフォルダーの両方)。

11
Stephen Kidson

API 21+を使用している場合は、セレクタと tint を使用してXMLで簡単にこれを行うことができます。

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <item Android:state_activated="true">
        <bitmap Android:src="@drawable/ic_settings_grey"
                Android:tint="@color/primary" />
    </item>

    <item Android:drawable="@drawable/ic_settings_grey"/>
</selector>
32

これは、Android support-v4ライブラリからの DrawableCompat を使用して実装しました。

通常のImageButtonImageViewをサブクラス化するため、この情報はImageViewsにも適用されます)で、 素材アイコンコレクション の黒いアイコンを使用します。

_<ImageButton
  Android:id="@+id/button_add"
  Android:src="@drawable/ic_add_black_36dp"
  Android:background="?attr/selectableItemBackgroundBorderless"
  Android:contentDescription="@string/title_add_item" />
_

これは私が作成したユーティリティメソッドです。

_public static void tintButton(@NonNull ImageButton button) {
    ColorStateList colours = button.getResources()
            .getColorStateList(R.color.button_colour);
    Drawable d = DrawableCompat.wrap(button.getDrawable());
    DrawableCompat.setTintList(d, colours);
    button.setImageDrawable(d);
}
_

_res/color/button_colour.xml_は、ボタンが押されたときにアイコンの色を赤から半透明の赤に変更するセレクターです。

_<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">

    <item
      Android:state_pressed="false"
      Android:color="@color/red" />

    <item
      Android:color="@color/red_alpha_50pc" />

</selector>
_

アクティビティのonCreate()メソッドでImageButtonが膨らんだ後、ボタンごとにtintButton(...)ヘルパーメソッドを呼び出すだけです。


これをAndroid 4.1(my minSdkVersion)および5.0デバイスでテストしましたが、DrawableCompatはAndroid 1.6。

19
Christopher Orr

サポートライブラリ22.1では、DrawableCompatを使用して、Drawable、APIレベル4+

DrawableCompat.wrap(Drawable)およびsetTint()、setTintList()、およびsetTintMode()は機能します。複数の色をサポートするためだけに、個別のドロウアブルを作成および維持する必要はありません!

10
bugraoral

コードの@Dreamingに同意し、例を挙げます。

ic_up_small

<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">

    <item Android:color="@color/comment_count_selected_color" Android:state_selected="true" />
    <item Android:color="@color/comment_count_text_color"/>

</selector>

layout/item_post_count_info.xml

<Android.support.v7.widget.AppCompatImageView
    Android:id="@+id/post_upvote_icon"
    Android:layout_width="14dp"
    Android:layout_height="14dp"
    Android:layout_marginLeft="17dp"
    app:srcCompat="@drawable/ic_up_small"
    app:tint="@color/post_up_color"/>

注意:Android:tintの代わりにapp:tintを使用する必要があります。

サポートライブラリのバージョンは26.0.2です。

app/build.gradle

implementation 'com.Android.support:appcompat-v7:26.0.2'
implementation 'com.Android.support:support-core-utils:26.0.2'
implementation 'com.Android.support:support-annotations:26.0.2'
implementation 'com.Android.support:support-v4:26.0.2'
implementation 'com.Android.support:design:26.0.2'

Android:tintを使用すると、クラッシュし、ログは次のようになります。

E/AndroidRuntime:FATAL EXCEPTION:main Android.view.InflateException:Binary XML file line#0:Error inflating class at Android.view.LayoutInflater.createView(LayoutInflater.Java:613)at Android.view.LayoutInflater.createViewFromTag(LayoutInflater。 Java:687)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 com.opera.six.viewholder.post.PostCountInfoViewHolder $ 1.create(PostCountInfoViewHolder.Java:29)at com.opera.six.viewholder.post.PostCountInfoViewHolder $ 1.create(PostCountInfoViewHolder.Java:25)at com.opera.six。 collection.CollectionAdapter.onCreateViewHolder(CollectionAdapter.Java:39)at com.opera.six.collection.CollectionAdapter.onCreateViewHolder(CollectionAdapter.Java:19)at Android.support.v7.widget.RecyclerView $ Adapter.createViewHolder(RecyclerView.Java: 6493)at Android.support.v7.widget.RecyclerView $ Recycler.tryGetViewHolderForPosit ionByDeadline(RecyclerView.Java:5680)at Android.support.v7.widget.RecyclerView $ Recycler.getViewForPosition(RecyclerView.Java:5563)at Android.support.v7.widget.RecyclerView $ Recycler.getViewForPosition(RecyclerView.Java:5559) Android.support.v7.widget.LinearLayoutManager $ LayoutState.next(LinearLayoutManager.Java:2229)at Android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.Java:1556)at Android.support.v7.widget.LinearLayoutManager AndroidのAndroid.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.Java:608)のAndroid.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.Java:3693)の.fill(LinearLayoutManager.Java:1516) support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.Java:3410)at Android.support.v7.widget.RecyclerView.onLayout(RecyclerView.Java:3962)at Android.view.View.layout(View.Java:13754) Android.view.ViewGroup.layout(ViewGroup.Java:4364)at Android.support.v4.widget.SwipeRefreshLayout.onLayout(SwipeR efreshLayout.Java:610)at Android.view.View.layout(View.Java:13754)at Android.view.ViewGroup.layout(ViewGroup.Java:4364)at Android.support.design.widget.HeaderScrollingViewBehavior.layoutChild(HeaderScrollingViewBehavior .Java:132)at Android.support.design.widget.ViewOffsetBehavior.onLayoutChild(ViewOffsetBehavior.Java:42)at Android.support.design.widget.AppBarLayout $ ScrollingViewBehavior.onLayoutChild(AppBarLayout.Java:1361)at Android.support。 design.widget.CoordinatorLayout.onLayout(CoordinatorLayout.Java:869)at Android.view.View.layout(View.Java:13754)at Android.view.ViewGroup.layout(ViewGroup.Java:4364)at Android.support.v4 .view.ViewPager.onLayout(ViewPager.Java:1767)at Android.view.View.layout(View.Java:13754)at Android.view.ViewGroup.layout(ViewGroup.Java:4364)at Android.widget.LinearLayout。 setChildFrame(LinearLayout.Java:1649)at Android.widget.LinearLayout.layoutVertical(LinearLayout.Java:1507)at Android.widget.LinearLayout.onLayout(LinearLayout.Java:1420)at Android。 view.View.layout(View.Java:13754)at Android.view.ViewGroup.layout(ViewGroup.Java:4364)at Android.widget.FrameLayout.onLayout(FrameLayout.Java:448)at Android.view.View.layout (View.Java:13754)Android.view.ViewGroup.layout(ViewGroup.Java:4364)at Android.widget.FrameLayout.onLayout(FrameLayout.Java:448)at Android.view.View.layout(View.Java: 13754)Android.view.ViewGroup.layout(ViewGroup.Java:4364)at Android.widget.LinearLayout.setChildFrame(LinearLayout.Java:1649)at Android.widget.LinearLayout.layoutVertical(LinearLayout.Java:1507)at Android。 widget.LinearLayout.onLayout(LinearLayout.Java:1420)at Android.view.View.layout(View.Java:13754)at Android.view.ViewGroup.layout(ViewGroup.Java:4364)at Android.widget.FrameLayout.onLayout (FrameLayout.Java:448)Android.view.View.layout(View.Java:13754)at Android.view.ViewGroup.layout(ViewGroup.Java:4364)at Android.widget.FrameLayout.onLayout(FrameLayout.Java: 448)Android.view.View.layout(View.Java:13754)at Android.view.ViewGrou p.layout(Vi

7
Francis Bacon

現在のAppCompatサポートライブラリでは、app:tint on ImageViewタグ。AppCompatImageViewとして膨張し、状態の変化を適切に処理します。

AppCompatImageViewで、mImageHelperに状態の変更が通知されていることがわかります。

@Override
protected void drawableStateChanged() {
    super.drawableStateChanged();
    if (mBackgroundTintHelper != null) {
        mBackgroundTintHelper.applySupportBackgroundTint();
    }
    if (mImageHelper != null) {
        mImageHelper.applySupportImageTint();
    }
}

Android Studioは現在これについて警告を出しますが、安全に抑制することができます。

4
Hai Zhang