oligazar
6/10/2017 - 1:53 AM

Buttons

Buttons

  1. Custom background
  2. Basic layout xml
  3. System buttons
  4. ImageToggleButton
  5. bg_btn_ripple.xml
  6. styles.xml

Android design guides metrics: https://material.io/guidelines/layout/metrics-keylines.html# min button size = 48dp styles: https://stackoverflow.com/a/29848987/4656400 Custom Radio buttons https://crosp.net/blog/android/creating-custom-radio-groups-radio-buttons-android/

<resources>
    <style name="button" parent="@android:style/Widget.Button">
        <item name="android:gravity">center_vertical|center_horizontal</item>
        <item name="android:textColor">#FFFFFFFF</item>
        <item name="android:shadowColor">#FF000000</item>
        <item name="android:shadowDx">0</item>
        <item name="android:shadowDy">-1</item>
        <item name="android:shadowRadius">0.2</item>
        <item name="android:textSize">16dip</item>
        <item name="android:textStyle">bold</item>
        <item name="android:background">@drawable/button</item>
        <item name="android:focusable">true</item>
        <item name="android:clickable">true</item>
    </style>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="@color/colorLightGray">
    <item>
        <shape
            android:shape="rectangle">
            <solid
                android:color="@color/colorGrayAlpha" />
        </shape>
    </item>
</ripple>

/**
 * Created by Admin on 11/4/16.
 * custom toggle button with pictures instead of text
 */

class ImageToggleButton: ImageButton, Checkable {

    private var mBroadcasting: Boolean = false
    private var mChecked: Boolean = false
    var drawableOn: Drawable? = null
    var drawableOff: Drawable? = null

    private var mOnCheckedChangeListener: OnCheckedChangeListener? = null

    constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int): super(context, attrs, defStyleAttr) {
        obtainStyledAttributes(context, attrs)
    }

    constructor(context: Context, attrs: AttributeSet): super(context, attrs) {
        obtainStyledAttributes(context, attrs)
    }

    constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int): super(context, attrs, defStyleAttr, defStyleRes) {
        obtainStyledAttributes(context, attrs)
    }

    private fun obtainStyledAttributes(context: Context, attrs: AttributeSet) {
        val a = context.obtainStyledAttributes(attrs, R.styleable.ImageToggleButton, 0, 0)
        drawableOn = a.getDrawable(R.styleable.ImageToggleButton_drawable_on)
        drawableOff = a.getDrawable(R.styleable.ImageToggleButton_drawable_off)


        isChecked = a.getBoolean(R.styleable.ImageToggleButton_checked, false)
        a.recycle()
    }

    // Checkable methods

    override fun isChecked() = mChecked

    override fun toggle() {
        isChecked = !mChecked
    }

    override fun setChecked(checked: Boolean) {
        if (mChecked != checked) {
            mChecked = checked
            refreshDrawableState()
            // Avoid infinite recursions if setChecked() is called from a listener
            if (mBroadcasting) return
            mBroadcasting = true

            if (mOnCheckedChangeListener != null) {
                mOnCheckedChangeListener?.onCheckedChanged(this, mChecked)
            }

            mBroadcasting = false
        }
        syncDrawableState()
    }

    private fun syncDrawableState() {
        val checked = isChecked
        if (checked && drawableOn != null) {
            setImageDrawable(drawableOn)
        } else if (!checked && drawableOff != null) {
            setImageDrawable(drawableOff)
        }
    }

    // helper stuff
    override fun performClick(): Boolean {
        toggle()

        val handled = super.performClick()
        if (!handled) {
            // View only makes a sound effect if the onClickListener was
            // called, so we'll need to make one here instead.
            playSoundEffect(SoundEffectConstants.CLICK)
        }

        return handled
    }

//    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
//        super.onLayout(changed, left, top, right, bottom)
//        syncDrawableState()
//    }

    // listener stuff

    /**
     * Register a callback to be invoked when the checked state of this button
     * changes.

     * @param listener the callback to call on checked state change
     */
    fun setOnCheckedChangeListener(listener: OnCheckedChangeListener) {
        mOnCheckedChangeListener = listener
    }

    fun setOnCheckedChangeListener(callback: (buttonView: ImageToggleButton, isChecked: Boolean) -> Unit) {
        mOnCheckedChangeListener = object: OnCheckedChangeListener {
            override fun onCheckedChanged(buttonView: ImageToggleButton, isChecked: Boolean) {
                callback(buttonView, isChecked)
            }

        }
    }

    /**
     * Interface definition for a callback to be invoked when the checked state
     * of a compound button changed.
     */
    interface OnCheckedChangeListener {
        /**
         * Called when the checked state of a compound button has changed.
         * @param buttonView The compound button view whose state has changed.
         * *
         * @param isChecked  The new checked state of buttonView.
         */
        fun onCheckedChanged(buttonView: ImageToggleButton, isChecked: Boolean)
    }

    override fun getAccessibilityClassName(): CharSequence {
        return ImageToggleButton::class.java.name
    }

    // Saving view state
    internal class SavedState : View.BaseSavedState {
        var checked: Boolean = false

        /**
         * Constructor called from [CompoundButton.onSaveInstanceState]
         */
        constructor(superState: Parcelable) : super(superState)

        /**
         * Constructor called from [.CREATOR]
         */
        private constructor(parcel: Parcel) : super(parcel) {
            checked = parcel.readValue(null) as Boolean
        }

        override fun writeToParcel(out: Parcel, flags: Int) {
            super.writeToParcel(out, flags)
            out.writeValue(checked)
        }

        override fun toString(): String {
            return "CompoundButton.SavedState{${Integer.toHexString(System.identityHashCode(this))} checked= $checked }"
        }

        companion object {

            val CREATOR: Parcelable.Creator<SavedState> = object : Parcelable.Creator<SavedState> {
                override fun createFromParcel(`in`: Parcel): SavedState {
                    return SavedState(`in`)
                }

                override fun newArray(size: Int): Array<SavedState?> {
                    return arrayOfNulls(size)
                }
            }
        }
    }
    public override fun onSaveInstanceState(): Parcelable {
        val superState = super.onSaveInstanceState()

        val ss = SavedState(superState)

        ss.checked = isChecked
        return ss
    }

    public override fun onRestoreInstanceState(state: Parcelable) {
        val ss = state as SavedState

        super.onRestoreInstanceState(ss.getSuperState())
        isChecked = ss.checked
        requestLayout()
    }
}
override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_codes)
        window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)

        //Listen for changes in the back stack
        supportFragmentManager.addOnBackStackChangedListener(this)
        //Handle when activity is recreated like on orientation Change
        shouldDisplayHomeUp()

        if (savedInstanceState == null) {
            //Подготавливаю фрагмент
            supportFragmentManager
                    .beginTransaction()
                    .add(R.id.container, GalleryFolderFragment())
                    .addToBackStack(null)
                    .commit()
        }
    }

    override fun onSupportNavigateUp(): Boolean {
        //This method is called when the up button is pressed. Just the pop back stack.
        if (supportFragmentManager.backStackEntryCount > 1) {
            supportFragmentManager.popBackStack()
        } else {
            onBackPressed()
        }
        return true
    }

    override fun onBackPressed() {
        if (supportFragmentManager.backStackEntryCount > 1) {
            supportFragmentManager.popBackStack()
        } else {
            super.onBackPressed()
        }
        super.onBackPressed()
    }

    override fun onBackStackChanged() {
        shouldDisplayHomeUp()
    }

    fun shouldDisplayHomeUp() {
        //Enable Up button only  if there are entries in the back stack
        val canBack = supportFragmentManager.backStackEntryCount > 0
        supportActionBar?.setDisplayHomeAsUpEnabled(canBack)
    }
// Transparent button's background
    android:background="?android:attr/selectableItemBackground"
    
// Consider using compound drawable to text views
<TextView
  android:drawableLeft
  android:drawableTop
  android:drawableRight
  android:drawableBottom
/>
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="false">
        <shape android:shape="rectangle">
            <corners android:radius="2.0dp"/>
            <stroke
                android:width="1dp"
                android:color="@color/colorPrimary" />
            <solid android:color="@color/colorBackground"/>
        </shape>
    </item>
    <item android:state_pressed="true">
        <shape android:shape="rectangle">
            <corners android:radius="2.0dp"/>
            <stroke
                android:width="1dp"
                android:color="@color/colorPrimary" />
            <solid android:color="@color/colorBackgroundDark"/>
        </shape>
    </item>
</selector>