android - 9-पैच और कार्डव्यू पर रिपल प्रभाव को कैसे संभालें, और चयनकर्ता के राज्यों पर नियंत्रण रखें?




android-listview android-5.0-lollipop (4)

पृष्ठभूमि

मैं एंड्रॉइड लॉलीपॉप और उससे ऊपर की सूची देखें आइटम के लिए एक साधारण लहर प्रभाव जोड़ना चाहता हूं।

सबसे पहले मैं इसे सरल पंक्तियों के लिए सेट करना चाहता हूं, और फिर 9-पैच पंक्तियों और यहां तक ​​कि कार्डव्यू भी सेट करना चाहता हूं।

समस्या

मुझे यकीन था कि यह बहुत आसान होगा, क्योंकि मुझे सामान्य चयनकर्ता को परिभाषित करने की भी आवश्यकता नहीं है। मैं सरल पंक्तियों के लिए भी ऐसा करने में असफल रहा। किसी कारण से, लहर प्रभाव पंक्ति की सीमाओं से परे चला जाता है:

इतना ही नहीं, लेकिन कुछ मामलों में, आइटम की पृष्ठभूमि उस रंग पर फंस जाती है जिसे मैंने सेट किया है।

कोड

मैंने यही कोशिश की है:

MainActivity.java

public class MainActivity extends ActionBarActivity {

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

        final ListView listView = (ListView) findViewById(android.R.id.list); 
        final LayoutInflater inflater = LayoutInflater.from(this);
        listView.setAdapter(new BaseAdapter() {

            @Override
            public View getView(final int position, final View convertView, final ViewGroup parent) {
                View rootView = convertView;
                if (rootView == null) {
                    rootView = inflater.inflate(android.R.layout.simple_list_item_1, parent, false);
                    ((TextView) rootView.findViewById(android.R.id.text1)).setText("Test");
                }
                return rootView;
            }

            @Override
            public long getItemId(final int position) {
                return 0;
            }

            @Override
            public Object getItem(final int position) {
                return null;
            }

            @Override
            public int getCount() {
                return 2;
            }
        });
    }

}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@android:id/list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:cacheColorHint="@android:color/transparent"
    android:divider="@null"
    android:dividerHeight="0px"
    android:fadeScrollbars="false"
    android:fastScrollEnabled="true"
    android:listSelector="@drawable/listview_selector"
    android:scrollingCache="false"
    android:verticalScrollbarPosition="right" />

res / drawable-v21 / listview_selector.xml (मेरे पास अन्य एंड्रॉइड संस्करणों के लिए एक सामान्य चयनकर्ता है)

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

मैंने क्या कोशिश की है

ऊपर दिए गए सरल कोड के अलावा, मैंने ListView पर "listSelector" का उपयोग करने के बजाय चयनकर्ता प्रति आइटम की पृष्ठभूमि संपत्ति को सेट करने का भी प्रयास किया है, लेकिन इससे मदद नहीं मिली।

मैंने कोशिश की एक और चीज वस्तुओं के अग्रभूमि को सेट करना है, लेकिन यह भी एक ही परिणाम था।

प्रश्न

मैं यह समस्या कैसे हल करूं? ऐसा क्यों होता है? मैंने गलत क्या किया?

मैं 9-पैच और यहां तक ​​कि कार्डव्यू का समर्थन करने के लिए आगे कैसे जा सकता हूं?

साथ ही, मैं नई पृष्ठभूमि के लिए एक राज्य कैसे सेट कर सकता हूं, जैसे चेक / चयनित किया जा रहा है?

अद्यतन: दृश्य के बाहर चित्रकारी इस तरह से कुछ का उपयोग कर तय किया गया है:

<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="?attr/colorControlHighlight" >

    <item android:id="@android:id/mask">
        <color android:color="@color/listview_pressed" />
    </item>

</ripple>

फिर भी, इसमें पृष्ठभूमि की समस्या फंस गई है, और मुझे नहीं पता कि शेष लापता सुविधाओं (9-पैच, कार्ड व्यू, ...) को कैसे संभालना है।

मुझे लगता है कि रंगों के फंसने के विचारों के अग्रभूमि के रूप में इसका उपयोग करने के साथ कुछ करना है।

संपादित करें: मुझे लगता है कि कुछ लोग यह नहीं समझते कि यहां क्या सवाल है।

यह नए तरंग प्रभाव को संभालने के बारे में है, जबकि अभी भी पुराने चयनकर्ता / कार्डव्यू है।

उदाहरण के लिए, यहां एक चयनकर्ता-ड्रॉबल है:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="..." android:state_selected="true"/>
    <item android:drawable="..." android:state_activated="true"/>
    <item android:drawable="..." android:state_focused="true" android:state_pressed="true"/>
    <item android:drawable="..." android:state_pressed="true"/>
    <item android:drawable="..."/>
</selector>

इसका उपयोग सूची चयनकर्ता या एकल दृश्य की पृष्ठभूमि के रूप में किया जा सकता है।

हालांकि, मुझे यह नहीं मिल रहा है कि इसे रिपल ड्रॉबल के साथ कैसे उपयोग किया जाए।

मुझे पता है कि लहर पहले से ही कुछ राज्यों का ख्याल रखती है, लेकिन कुछ के लिए, यह नहीं है। इसके अलावा, मैं यह नहीं पता कि इसे 9-पैच और कार्डव्यू को कैसे संभालना है।

मुझे उम्मीद है कि अब मेरी समस्या को समझना आसान है।

लहर के रंग के मुद्दे के बारे में "अटक गया" हो जाता है, मुझे लगता है कि यह लेआउट बनाने के कारण है। मैं एक लेआउट चाहता था जिसे चेक किया जा सकता है (जब मैं फैसला करता हूं) और क्लिक करने का प्रभाव भी पड़ता है, तो यही वह है जो मैंने बनाया है ( इस वेबसाइट पर आधारित है और दूसरा जो मुझे नहीं मिल रहा है):

public class CheckableRelativeLayout extends RelativeLayout implements Checkable {
    private boolean mChecked;
    private static final String TAG = CheckableRelativeLayout.class.getCanonicalName();
    private static final int[] CHECKED_STATE_SET = { android.R.attr.state_checked };
    private Drawable mForegroundDrawable;

    public CheckableRelativeLayout(final Context context) {
        this(context, null, 0);
    }

    public CheckableRelativeLayout(final Context context, final AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CheckableRelativeLayout(final Context context, final AttributeSet attrs, final int defStyle) {
        super(context, attrs, defStyle);
        final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CheckableRelativeLayout, defStyle,
                0);
        setForeground(a.getDrawable(R.styleable.CheckableRelativeLayout_foreground));
        a.recycle();
    }

    public void setForeground(final Drawable drawable) {
        this.mForegroundDrawable = drawable;
    }

    public Drawable getForeground() {
        return this.mForegroundDrawable;
    }

    @Override
    protected int[] onCreateDrawableState(final int extraSpace) {
        final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
        if (isChecked()) {
            mergeDrawableStates(drawableState, CHECKED_STATE_SET);
        }
        return drawableState;
    }

    @Override
    protected void drawableStateChanged() {
        super.drawableStateChanged();
        final Drawable drawable = getBackground();
        boolean needRedraw = false;
        final int[] myDrawableState = getDrawableState();
        if (drawable != null) {
            drawable.setState(myDrawableState);
            needRedraw = true;
        }
        if (mForegroundDrawable != null) {
            mForegroundDrawable.setState(myDrawableState);
            needRedraw = true;
        }
        if (needRedraw)
            invalidate();
    }

    @Override
    protected void onSizeChanged(final int width, final int height, final int oldwidth, final int oldheight) {
        super.onSizeChanged(width, height, oldwidth, oldheight);
        if (mForegroundDrawable != null)
            mForegroundDrawable.setBounds(0, 0, width, height);
    }

    @Override
    protected void dispatchDraw(final Canvas canvas) {
        super.dispatchDraw(canvas);
        if (mForegroundDrawable != null)
            mForegroundDrawable.draw(canvas);
    }

    @Override
    public boolean isChecked() {
        return mChecked;
    }

    @Override
    public void setChecked(final boolean checked) {
        setChecked(checked, true);
    }

    public void setChecked(final boolean checked, final boolean alsoRecursively) {
        mChecked = checked;
        refreshDrawableState();
        if (alsoRecursively)
            ViewUtil.setCheckedRecursively(this, checked);
    }

    @Override
    public void toggle() {
        setChecked(!mChecked);
    }

    @Override
    public Parcelable onSaveInstanceState() {
        // Force our ancestor class to save its state
        final Parcelable superState = super.onSaveInstanceState();
        final SavedState savedState = new SavedState(superState);
        savedState.checked = isChecked();
        return savedState;
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    @Override
    public void drawableHotspotChanged(final float x, final float y) {
        super.drawableHotspotChanged(x, y);
        if (mForegroundDrawable != null) {
            mForegroundDrawable.setHotspot(x, y);
        }
    }

    @Override
    public void onRestoreInstanceState(final Parcelable state) {
        final SavedState savedState = (SavedState) state;
        super.onRestoreInstanceState(savedState.getSuperState());
        setChecked(savedState.checked);
        requestLayout();
    }

    // /////////////
    // SavedState //
    // /////////////

    private static class SavedState extends BaseSavedState {
        boolean checked;

        SavedState(final Parcelable superState) {
            super(superState);
        }

        private SavedState(final Parcel in) {
            super(in);
            checked = (Boolean) in.readValue(null);
        }

        @Override
        public void writeToParcel(final Parcel out, final int flags) {
            super.writeToParcel(out, flags);
            out.writeValue(checked);
        }

        @Override
        public String toString() {
            return TAG + ".SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked
                    + "}";
        }

        @SuppressWarnings("unused")
        public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() {
            @Override
            public SavedState createFromParcel(final Parcel in) {
                return new SavedState(in);
            }

            @Override
            public SavedState[] newArray(final int size) {
                return new SavedState[size];
            }
        };
    }
}

संपादित करें: मैंने जो लेआउट बनाया है, उसके लिए अगली पंक्तियां तय करना था:

@SuppressLint("ClickableViewAccessibility")
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public boolean onTouchEvent(final MotionEvent e) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && //
            e.getActionMasked() == MotionEvent.ACTION_DOWN && //
            mForeground != null)
        mForeground.setHotspot(e.getX(), e.getY());
    return super.onTouchEvent(e);
}

आप 9 पैच छवियों को नीचे कोड की तरह कुछ संभाल सकते हैं:

 <?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="?attr/colorControlHighlight" >

    <item android:id="@android:id/mask"
     android:drawable="@drawable/comment_background">
    </item>

</ripple>

जहां comment_background 9 पैच छवि है


आपको लहर में एक मुखौटा परत सेट करना होगा।

कुछ इस तरह:

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="?attr/colorControlHighlight">
    <item android:id="@id/mask">
        <color android:color="@color/myColor" />
    </item>
</ripple>

एक लहर बनाने के लिए सरल तरीका एक XML को drawable-v21 फ़ोल्डर में बनाते हैं और xml के लिए इस कोड का उपयोग करते हैं।

android:backgroung="@drawable/ripple_xyz"

और यदि, जावा / गतिशील रूप से उपयोग के माध्यम से।

View.setBackgroundResource(R.drawable.ripple_xyz);

यहाँ ripple_xyz.xml है।

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#228B22" >
// ^ THIS IS THE COLOR FOR RIPPLE
<item>
    <shape
        android:shape="rectangle"
        android:useLevel="false" >
        <solid android:color="#CCFFFFFF" />
// ^ THIS IS THE COLOR FOR BACK GROUND
    </shape>
</item>


RippleDrawable LayerDrawable विस्तारित करता LayerDrawable । टच फीडबैक टच करने में कई बाल परतें हो सकती हैं, जिनमें एक विशेष मुखौटा परत भी शामिल है जो स्क्रीन पर नहीं खींची जाती है। मास्क के रूप में android:id मान को अपने android:id निर्दिष्ट करके मास्क के रूप में एक परत को सेट किया जा सकता है। दूसरी परत राज्य सूची हो सकती है।

उदाहरण के लिए, यहां हमारा StateListDrawable संसाधन है जिसका नाम item_selectable.xml :

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="..." android:state_selected="true"/>
    <item android:drawable="..." android:state_activated="true"/>
    <item android:drawable="..." android:state_focused="true" android:state_pressed="true"/>
    <item android:drawable="..." android:state_pressed="true"/>
    <item android:drawable="..."/>
</selector>

चयनकर्ताओं के साथ तरंग प्रभाव प्राप्त करने के लिए हम नाम list_selector_ripple.xml नाम के साथ RippleDrawable की एक परत के रूप में ऊपर RippleDrawable योग्य सेट कर सकते हैं:

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="@color/colorControlHighlight">
    <item android:id="@android:id/mask">
        <color android:color="@android:color/white"/>
    </item>
    <item android:drawable="@drawable/item_selectable"/>
</ripple>

युपीडी:

1) CardView साथ इस CardView उपयोग करने के लिए बस इसे android:foreground रूप में सेट करें android:foreground , इस तरह:

<android.support.v7.widget.CardView
    ...
    android:foreground="@drawable/list_selector_ripple"
    />

2) लहर-प्रभाव को 9-पैच की सीमाओं के भीतर काम करने के लिए हमें इस 9-पैच को तरंग list_selector_ripple_nine_patch.xml योग्य ( list_selector_ripple_nine_patch.xml ) के मुखौटा के रूप में list_selector_ripple_nine_patch.xml जाना चाहिए:

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="@color/colorControlHighlight">
    <item android:id="@android:id/mask" android:drawable="@drawable/your_nine_patch" />
    <item android:drawable="@drawable/your_nine_patch" />
</ripple>

फिर दृश्य की पृष्ठभूमि सेट करें:

<LinearLayout
    ...
    android:background="@drawable/list_selector_ripple_nine_patch"
    />




rippledrawable