I have customised progressbar.
HorizontalSlider class which inherits from ProgressBar is:
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ProgressBar;
public class HorizontalSlider extends ProgressBar {
private OnProgressChangeListener listener;
private static final int padding = 2;
private static final int getMin = 11;
public interface OnProgressChangeListener {
void onProgressChanged(View v, int progress);
}
public HorizontalSlider(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, android.R.attr.progressBarStyleHorizontal);
}
public HorizontalSlider(Context context, AttributeSet attrs) {
super(context, attrs);
}
public HorizontalSlider(Context context) {
super(context);
}
public void setOnProgressChangeListener(OnProgressChangeListener l) {
listener = l;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_MOVE) {
float x_mouse = event.getX() - padding;
float width = getWidth() - 2 * padding;
int progress = Math.round((float) getMax() * (x_mouse / width));
if (progress < getMin)
progress = getMin;
if (progress > getMax())
progress = getMax();
this.setProgress(progress);
if (listener != null)
listener.onProgressChanged(this, progress);
}
return true;
}
}
UI in xml format is:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingLeft="10dip"
android:paddingRight="10dip"
android:paddingTop="100dip"
android:gravity="center_horizontal" >
<com.astro.mania.classes.HorizontalSlider
android:id = "#+id/slider"
android:layout_width = "fill_parent"
android:layout_height= "wrap_content"
android:max="100"
android:layout_centerHorizontal="true"
style="?android:attr/progressBarStyleHorizontal" />
<com.astro.mania.classes.HorizontalSlider
android:id="#+id/progressBar"
android:progressDrawable="#drawable/progressbar"
android:layout_width="fill_parent"
android:layout_height="24dip"
style="?android:attr/progressBarStyleHorizontal"
android:indeterminateOnly="false"
android:max="100"
android:layout_below="#id/slider"
android:layout_marginTop="20dip" />
</RelativeLayout>
Progressbar customised as below:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#android:id/background">
<shape>
<gradient
android:startColor="#fffffe"
android:centerColor="#0b131e"
android:centerY="0.75"
android:endColor="#0d1522"
android:angle="270" />
</shape>
</item>
<item android:id="#android:id/secondaryProgress">
<clip>
<shape>
<gradient
android:startColor="#234"
android:centerColor="#234"
android:centerY="0.75"
android:endColor="#a24"
android:angle="270"
/>
</shape>
</clip>
</item>
<item android:id="#android:id/progress">
<bitmap android:src="#drawable/btn_slide_arrow" android:dither="true" />
</item>
</layer-list>
Finally the activity is like this:
public class LensaMania extends Activity {
private HorizontalSlider slider, slider2;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_PROGRESS);
setContentView(R.layout.activity_lensamania);
Log.i("LensaMania", "LensaMania activity started...");
setProgressBarVisibility(true);
slider = (HorizontalSlider) this.findViewById(R.id.slider);
slider.setOnProgressChangeListener(changeListener);
slider2 = (HorizontalSlider) this.findViewById(R.id.progressBar);
slider2.setVisibility(View.VISIBLE);
slider2.setMax(100);
slider2.setProgress(11);
slider2.setOnProgressChangeListener(changeListener);
}
private OnProgressChangeListener changeListener = new OnProgressChangeListener() {
public void onProgressChanged(View v, int progress) {
setProgress(progress);
Log.i("Progress is:", "=>" + progress);
}
};
}
When I run the application and slide progreebar, the image is repeated like image below. I want to have just one image and when I slide it to left want to see just one arrow. How to ask progressbar to don't repeat the image?
Related
I am adding the border around tabs as shown in the second image.
I am able to add the borders on top and the bottom as shown in first image but not able to add the border on left/right side of each tab individually.
main_activity.xml
<android.support.design.widget.TabLayout
android:id="#+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#drawable/tab_border"
android:theme="#style/AppTheme.ActionBar"
android:visibility="invisible"
app:tabIndicatorColor="#color/colorPrimary">
</android.support.design.widget.TabLayout>
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="50dp"
app:layout_constraintTop_toTopOf="parent" />
#drawable/tab_border.xml
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#efefef"/>
<stroke android:width="2dp" android:color="#c0c6cc"/>
<corners android:radius="0dp" />
<padding android:left="10dp" android:top="5dp"
android:right="10dp" android:bottom="5dp" />
</shape>
I am adding the tabs programmatically in activity class as i have to decide the no of tabs on run-time.
Using CustomTabLayout:
public class CustomTabLayout extends TabLayout {
public CustomTabLayout(Context context) {
this(context, null);
}
public CustomTabLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomTabLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
#Override
public void setupWithViewPager(#Nullable ViewPager viewPager) {
super.setupWithViewPager(viewPager);
initCustomTab();
}
#SuppressWarnings({ "ConstantConditions" })
private void initCustomTab() {
int totalTab = getTabCount();
for (int i = 0; i < totalTab; i++) {
Tab tab = getTabAt(i);
if (tab == null) continue;
View view = LayoutInflater.from(getContext())
.inflate(R.layout.item_custom_tab, this, false);
tab.setCustomView(view);
}
}
}
item_custom_tab.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="#dimen/dp_48"
android:background="#drawable/tab_border"
>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
/>
</RelativeLayout>
hope this helps
In my Android app I have a GridView which displays a set of images, each one in a custom subclass of ImageView (TickedImageView), which displays a tick when the image is selected.
What I want to achieve is to display a ripple when the image gets touched. I have tried setting background to
?android:attr/selectableItemBackground
with no luck, also adding a wrapper layout with this background, but nothing seems to work.
My code is as follows:
<GridView
android:id="#+id/photos_grid"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:horizontalSpacing="2dp"
android:numColumns="#integer/photos_grid_num_columns"
android:stretchMode="columnWidth"
android:verticalSpacing="2dp"
android:layout_below="#id/spinner_toolbar" />
The layout of each GridView item is the following:
<utils.TickedImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/thumb"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:attr/selectableItemBackground"
android:focusable="true"
android:clickable="true" />
And the ImageView subclass (TickedImageView) is the following:
package utils;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import app.R;
public class TickedImageView extends ImageView {
private boolean selected;
private Bitmap mTickBmp;
private Paint mDarkerPaint;
private View.OnClickListener onImageClickListener;
private int x, y;
public TickedImageView(Context context) {
super(context);
init();
}
public TickedImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
super.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
setSelected(!isSelected());
if (onImageClickListener != null)
onImageClickListener.onClick(TickedImageView.this);
}
});
mDarkerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mDarkerPaint.setStyle(Paint.Style.FILL);
mDarkerPaint.setColor(0x80142030);
mTickBmp = BitmapFactory.decodeResource(getResources(), R.drawable.ic_done_white_48px);
}
public void setSelected(boolean selected) {
this.selected = selected;
invalidate();
}
public boolean isSelected() {
return selected;
}
#Override
protected void onDraw(#NonNull Canvas canvas) {
super.onDraw(canvas);
if (selected) {
canvas.drawRect(0, 0, canvas.getWidth(), getMeasuredWidth(), mDarkerPaint);
canvas.drawBitmap(mTickBmp, x, y, null);
}
}
#Override
public void setOnClickListener(OnClickListener listener) {
onImageClickListener = listener;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
x = (getMeasuredWidth() / 2) - (mTickBmp.getWidth() / 2);
y = (getMeasuredWidth() / 2) - (mTickBmp.getHeight() / 2);
}
}
Thank you.
To add your ripple effect, add the following :
Step 1 : Create a shape (drawable/defaultBackground.xml)
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#color/colorAccent" />
<stroke
android:width="3dp"
android:color="#color/colorAccent" />
<corners android:radius="8dp" />
Obviously you can customize it to your needs. This will be our default background.
Step 2 : Create the ripple background (drawable/rippleBackground.xml)
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#color/selectedRed">
<item android:drawable="#drawable/defaultBackground"/>
Once again, you can change the color to whatever you need.
Step 3 : Add the ripple to your view :
<utils.TickedImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/thumb"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/rippleBackground"
android:focusable="true"
android:clickable="true" />
when i use android:progressDrawable="#drawable/barcolor",it works properly, but when i use setProgressDrawable, it looks wrong
my layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<ProgressBar
android:id="#+id/firstProgressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="300dip"
android:layout_height="30dip"
android:layout_centerHorizontal="true"
android:layout_above="#+id/text_first"
android:max="300"
android:progress="0" />
<TextView
android:id="#+id/text_first"
android:textColor="#fff"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="10dp"
android:gravity="center"
/>
</RelativeLayout>
and my java codes:
firstProgressBar = (ProgressBar)findViewById(resId4);
resId = getResources().getIdentifier("barcolor","drawable",packageName);
Rect bounds = firstProgressBar.getProgressDrawable().getBounds();
firstProgressBar.setProgressDrawable(getResources().getDrawable(resId));
firstProgressBar.getProgressDrawable().setBounds(bounds);
and the barcolor.xml:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#android:id/background">
<nine-patch android:src="#drawable/progress_bar_bg">
</nine-patch>
</item>
<item android:id="#android:id/progress">
<clip>
<nine-patch android:src="#drawable/progress_bar">
</nine-patch>
</clip>
</item>
</layer-list>
thank you all !
Try this:
firstProgressBar.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
Rect bounds = firstProgressBar.getProgressDrawable().getBounds();
Drawable drawable = getResources().getDrawable(resId);
drawable.setBounds(bounds);
firstProgressBar.setProgressDrawable(drawable);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
firstProgressBar.getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
firstProgressBar.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
}
});
hoomi, thank you for your help! I have solved this problem with custom ProgressBar, it calls CustomPorgressBar:
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.util.AttributeSet;
import android.widget.ProgressBar;
public class CustomProgressBar extends ProgressBar {
public CustomProgressBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public CustomProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomProgressBar(Context context) {
super(context);
}
#Override
public void draw(Canvas canvas) {
Drawable d = getProgressDrawable();
if (d instanceof LayerDrawable) {
LayerDrawable layerDrawable = (LayerDrawable) d;
Drawable progressDrawable = layerDrawable
.findDrawableByLayerId(android.R.id.progress);
//
layerDrawable.setBounds(0, 0, progressRight, progressBottom);
progressDrawable.setBounds(0, 0, progressRight, progressBottom);
}
super.draw(canvas);
}
private int progressRight;
private int progressBottom;
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
progressRight = getWidth() - getPaddingRight() - getPaddingLeft();
progressBottom = getHeight() - getPaddingBottom() - getPaddingTop();
}
}
I'm trying to figure out how to set up a custom listSelector to my listView. The code is more-or-less copy&paste from solutions that worked for others in stackoverflow, but it doesn't work for me.
When I turn on the CAB mode, then I can select and deselect the items, and I see the number of selected items in the CAB navbar, but I don't see any indication in the list. I would like to see which items are selected. Any idea why it doesn't work?
layout/category_list.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/categories_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="#+id/category_browser"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:dividerHeight="1dp"
android:listSelector="#drawable/list_selector"
android:drawSelectorOnTop="true"
tools:listitem="#layout/category_list_item" >
</ListView>
<include layout="#layout/ad"/>
</LinearLayout>
layout/category_list_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<com.fletech.smartbaby.api.CheckableLinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/category_browser_list_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="fill"
android:clickable="true"
android:gravity="fill"
android:orientation="horizontal">
<ImageView
android:id="#+id/category_item_icon"
android:layout_width="90dp"
android:layout_height="90dp"
android:layout_gravity="fill"
android:layout_weight="0"
android:background="#ffffff"
android:src="#drawable/ic_launcher" />
<TextView
android:id="#+id/category_browser_list_title"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical|start"
android:paddingLeft="10dp"
android:paddingRight="10dp"
tools:text="Category name"
android:textColor="#000000"
android:textSize="24sp" />
<include layout="#layout/category_features"
android:layout_centerInParent="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
/>
<include layout="#layout/category_status"
android:layout_centerInParent="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
/>
</com.fletech.smartbaby.api.CheckableLinearLayout>
drawable/list_selector.xml:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="#40777777"/>
</shape>
</item>
<item android:state_long_pressable="true">
<shape android:shape="rectangle">
<solid android:color="#400000ff"/>
</shape>
</item>
<item android:state_checkable="true">
<shape android:shape="rectangle">
<solid android:color="#400000ff"/>
</shape>
</item>
<item android:state_checked="true">
<shape android:shape="rectangle">
<solid android:color="#800000ff"/>
</shape>
</item>
</selector>
and CheckableLinearLayout.java:
package com.fletech.smartbaby.api;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
//import android.support.v7.widget.LinearLayoutCompat; // do I need this? I can't see any difference
import android.util.AttributeSet;
import android.util.Log;
import android.widget.Checkable;
import android.widget.LinearLayout;
public class CheckableLinearLayout extends LinearLayout implements Checkable {
private static final String TAG = CheckableLinearLayout.class.getSimpleName();
private static final int[] CHECKED_STATE_SET = {android.R.attr.state_checked};
private boolean mChecked;
public CheckableLinearLayout(Context context) {
super(context);
}
public CheckableLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public CheckableLinearLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
public void setChecked(boolean checked) {
Log.v(TAG, "setChecked: " + checked);
if (mChecked != checked) {
mChecked = checked;
refreshDrawableState();
}
}
#Override
public boolean isChecked() {
return mChecked;
}
#Override
public void toggle() {
Log.v(TAG, "toggle: " + mChecked + " -> " + (!mChecked));
setChecked(!mChecked);
}
#Override
// not sure if needed, as it seems to work without this as well
public boolean performClick() {
Log.v(TAG, "performClick");
toggle();
return super.performClick();
}
#Override
// this might be unnecessary
protected void drawableStateChanged() {
Log.v(TAG, "drawableStateChanged");
super.drawableStateChanged();
final Drawable drawable=getBackground();
if(drawable!=null)
{
final int[] myDrawableState=getDrawableState();
drawable.setState(myDrawableState);
invalidate();
}
}
#Override
protected int[] onCreateDrawableState(int extraSpace) {
Log.v(TAG, "onCreateDrawableState: " + extraSpace);
final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
if (isChecked()) {
mergeDrawableStates(drawableState, CHECKED_STATE_SET);
}
return drawableState;
}
#Override
protected Parcelable onSaveInstanceState() {
SavedState result = new SavedState(super.onSaveInstanceState());
result.checked = mChecked;
return result;
}
#Override
protected void onRestoreInstanceState(Parcelable state) {
if (!(state instanceof SavedState)) {
super.onRestoreInstanceState(state);
return;
}
SavedState ss = (SavedState) state;
super.onRestoreInstanceState(ss.getSuperState());
setChecked(ss.checked);
}
protected static class SavedState extends BaseSavedState {
protected boolean checked;
protected SavedState(Parcelable superState) {
super(superState);
}
#Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeInt(checked ? 1 : 0);
}
public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() {
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
private SavedState(Parcel in) {
super(in);
checked = in.readInt() == 1;
}
}
}
I took me more than a week to find out why this thing that works for everyone doesn't work for me. The answer is simple. I hope it'll help others.
The solution was to change the order of the items in the selector xml. The item without any states has to be the last one:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_long_pressable="true">
<shape android:shape="rectangle">
<solid android:color="#400000ff"/>
</shape>
</item>
<item android:state_checkable="true">
<shape android:shape="rectangle">
<solid android:color="#400000ff"/>
</shape>
</item>
<item android:state_checked="true">
<shape android:shape="rectangle">
<solid android:color="#800000ff"/>
</shape>
</item>
<!-- the item without any states has to be the last: -->
<item>
<shape android:shape="rectangle">
<solid android:color="#40777777"/>
</shape>
</item>
</selector>
The reason is that it seems that the parser looks for the 1st item in the xml file that matches. It means that if you have items with different number of states, then you should always have those that have more states defined in the top of the xml. For example:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checkable="true" android:state_long_pressable="true">
<shape android:shape="rectangle">
<solid android:color="#ffff00"/>
</shape>
</item>
<item android:state_long_pressable="true">
<shape android:shape="rectangle">
<solid android:color="#ff0000"/>
</shape>
</item>
<item android:state_checkable="true">
<shape android:shape="rectangle">
<solid android:color="#00ff00"/>
</shape>
</item>
<item>
<shape android:shape="rectangle">
<solid android:color="#40777777"/>
</shape>
</item>
</selector>
This way, and only this way, you'll see a different color on items that are:
- both checkable and long_pressable
- checkable, but not long_pressable
- long_pressable but not checkable
- everything else
My problem is when my CheckableLinearLayout is checked my draw from the selector can't overlap the unchecked image.
My CheckableLinearLayout
public class CheckableLinearLayout extends LinearLayout implements Checkable {
private boolean mChecked;
private static final String TAG = CheckableLinearLayout.class
.getCanonicalName();
private static final int[] CHECKED_STATE_SET =
{ android.R.attr.state_checked };
public CheckableLinearLayout(final Context context) {
super(context);
setClickable(true);
setLongClickable(true);
}
public CheckableLinearLayout(final Context context,
final AttributeSet attrs) {
super(context, attrs);
setClickable(true);
setLongClickable(true);
}
#TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
public CheckableLinearLayout(final Context context,
final AttributeSet attrs,
final int defStyle) {
super(context, attrs, defStyle);
setClickable(true);
setLongClickable(true);
}
#Override
public void setChecked(final boolean checked) {
mChecked = checked;
refreshDrawableState();
}
#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();
if (drawable != null) {
final int[] myDrawableState = getDrawableState();
drawable.setState(myDrawableState);
invalidate();
}
}
#Override
public boolean performClick() {
Toast.makeText(getContext(), "click", Toast.LENGTH_SHORT).show();
if (isChecked()) {
toggle();
return false;
} else
return super.performClick();
}
#Override
public boolean performLongClick() {
toggle();
Toast.makeText(getContext(), "long click", Toast.LENGTH_SHORT).show();
return super.performLongClick();
}
#Override
public boolean isChecked() {
return mChecked;
}
#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;
}
#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;
#SuppressWarnings("unused")
public static final Parcelable.Creator<SavedState> CREATOR;
static {
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];
}
};
}
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 + "}";
}
}
}
My layout.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/topics_preview_main_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:id="#+id/favorites_header_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="6dp"
android:layout_marginRight="6dp"
android:layout_marginTop="2dp"
android:orientation="vertical" >
<TextView
android:id="#+id/favorites_header_title"
style="#style/CardText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
android:layout_marginLeft="6dp"
android:layout_marginRight="6dp"
android:layout_marginTop="4dp"
android:background="#drawable/card"
android:gravity="left"
android:paddingBottom="10dp"
android:paddingLeft="5dp"
android:paddingTop="10dp"
android:text="#string/favorites_header" />
<ui.CheckableLinearLayout
android:id="#+id/favorites_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
android:layout_marginLeft="6dp"
android:layout_marginRight="6dp"
android:layout_marginTop="4dp"
android:background="#drawable/card_selector_w_shadow"
android:clickable="true"
android:longClickable="true"
android:orientation="vertical"
android:paddingBottom="16dp" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingLeft="8dp"
android:paddingRight="8dp" >
<TextView
android:id="#+id/favorites_title"
style="#style/CardTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="title" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="4dp"
android:background="#color/C_Favorites_Pink" />
<LinearLayout
android:id="#+id/favorites_description_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="vertical"
android:padding="4dp" >
<TextView
android:id="#+id/favorites_description"
style="#style/CardText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:ellipsize="end"
android:maxLines="4"
android:text="Lorem ipsum ..." />
</LinearLayout>
</ui.CheckableLinearLayout>
</LinearLayout>
</FrameLayout>
card_selector_w_shadow-> this draw will call the selector
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape
android:dither="true"
android:shape="rectangle" >
<corners android:radius="2dp" />
<solid android:color="#ccc" />
</shape>
</item>
<item android:bottom="2dp">
<shape
android:dither="true"
android:shape="rectangle" >
<corners android:radius="2dp" />
<solid android:color="#android:color/white" />
<padding
android:bottom="8dp"
android:left="8dp"
android:right="8dp"
android:top="8dp" />
</shape>
</item>
<item android:drawable="#drawable/drawable_states"/>
</layer-list>
My drawable_states
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/checked_background"
android:state_checked="true"/>
</selector>
This is what's happening:
This is what I intend:
I think this is because my CheckableLinearLayout only changes the state of the children, so the draw only overlap the children. Any advices?