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?
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
I am wondering if it is possible in android studio to display text following a circular shape.
NORMAL RESULT
FINAL RESULT
layout:
<LinearLayout
android:id="#+id/layout2"
android:layout_width="260dp"
android:layout_height="250dp"
android:background="#drawable/shape"
android:textColor="#ffffff"
android:gravity="center_vertical|center_horizontal"
android:layout_alignParentRight="true"
android:layout_centerVertical="true">
<TextView
android:background="#drawable/shape"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Text"/>
</LinearLayout>
AND shape.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
<corners
android:radius="130dp"
android:bottomRightRadius="0dp"
android:topRightRadius="0dp"
/>
<solid
android:color="#color/colorPrimary5"
/>
<padding
android:left="8dp"
android:top="0dp"
android:right="8dp"
android:bottom="0dp"
/>
Try this
activity_main
<?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="match_parent" >
<TextView
android:id="#+id/num_txt"
android:layout_width="185dp"
android:layout_height="185dp"
android:layout_alignParentTop="true"
android:layout_marginTop="163dp"
android:background="#drawable/bg_red"
android:gravity="center"
android:text="My name is NON"
android:textColor="#FFFFFF"
android:layout_marginLeft="10dp"
android:textSize="10dp" />
<TextView
android:id="#+id/TextView02"
android:layout_width="90dp"
android:layout_height="90dp"
android:layout_alignParentRight="true"
android:layout_alignTop="#+id/TextView01"
android:layout_marginRight="90dp"
android:layout_marginTop="122dp"
android:background="#drawable/bg_red"
android:gravity="center"
android:text="My name is NON"
android:textColor="#FFFFFF"
android:textSize="10dp" />
<TextView
android:id="#+id/TextView01"
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_alignTop="#+id/num_txt"
android:layout_toRightOf="#+id/num_txt"
android:background="#drawable/bg_red"
android:gravity="center"
android:text="My name is NON"
android:textColor="#FFFFFF"
android:textSize="10dp" />
</RelativeLayout>
Create a X.M.L. file in file in drawable folder named as "bg_red"
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<corners android:radius="10dip"/>
<stroke android:color="#FF0000" android:width="5dip"/>
<solid android:color="#FF0000"/>
</shape>
Output
Try the following, It may be helpful.
1) CircularTextView.class:----------
Source: https://github.com/lisawray/circletextview
public class CircleTextView extends View {
private int maxLines;
private TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
private CharSequence charSequence = "";
private int[] leftIndents;
private int[] rightIndents;
private StaticLayout layout;
public CircleTextView(Context context) {
super(context);
}
public CircleTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CircleTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP) public CircleTextView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public int getRightIndent(int line, int width, int height) {
return getIndent(line, width, height);
}
public int getLeftIndent(int line, int width, int height) {
return getIndent(line, width, height);
}
public int getIndent(int line, int width, int height) {
int r = (int) (getSmallestDimension(width, height) / 2f);
float y = (r - line * getLineHeight());
return (int) (width / 2f - Math.sqrt((r * r) - y * y));
}
public void setTextSize(#DimenRes int dimenResId) {
textPaint.setTextSize(getPixels(TypedValue.COMPLEX_UNIT_PX, getResources().getDimension(dimenResId)));
}
int getPixels(int unit, float size) {
DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
return (int) TypedValue.applyDimension(unit, size, metrics);
}
#Override protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
maxLines = (int) Math.floor(getSmallestDimension(w, h) / getLineHeight());
leftIndents = new int[maxLines];
rightIndents = new int[maxLines];
for (int line = 0; line < maxLines; line++) {
leftIndents[line] = getLeftIndent(line, w, h);
rightIndents[line] = getRightIndent(line, w, h);
}
makeNewLayout();
}
public void setText(CharSequence charSequence) {
this.charSequence = charSequence;
makeNewLayout();
}
private void makeNewLayout() {
StaticLayout.Builder builder = StaticLayout.Builder.obtain(charSequence, 0, charSequence.length(), textPaint, getMeasuredWidth());
builder.setIndents(leftIndents, rightIndents);
builder.setMaxLines(maxLines);
layout = builder.build();
}
#Override protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
layout.draw(canvas);
}
private int getSmallestDimension(int width, int height) {
return Math.min(width, height);
}
public float getLineHeight() {
return textPaint.getFontMetrics().bottom - textPaint.getFontMetrics().top;
}
public TextPaint getTextPaint() {
return textPaint;
}
}
2) MainActivity_.class:-----
public class MainActivity_ extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout7);
CircleTextView textView = (CircleTextView) findViewById(R.id.circle_text_view);
textView.setTextSize(R.dimen.txt_size); // declare txt_size in dimens (14sp for example).
textView.setText("This is aasdadadad nice test to insure the reliability of this shit fdgggh hfhjg khk kjghk lh lhlj hl hllh ; ;l hkjjl hlhl hl lhljh lhl hhlh hlh llh lhhj l llhl lh l lh lh");
}
}
3) layout7.xml:-------
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<View
android:background="#drawable/s"
android:layout_width="205dp"
android:layout_height="205dp"
android:id="#+id/frame"
android:layout_centerInParent="true"
android:gravity="center" />
<com.example.admin.accessories.CircleTextView
android:layout_width="150dp"
android:layout_height="150dp"
android:id="#+id/circle_text_view"
android:layout_centerInParent="true"
android:gravity="center">
</com.example.admin.accessories.CircleTextView>
</RelativeLayout>
4) s.xml:---------
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval"
android:innerRadius="0dp"
android:thickness="100dp"
android:useLevel="false">
<solid
android:color="#android:color/holo_red_dark"/>
</shape>
5) Output:---------
6) Note: I'm not the author of the code for the CircleTextView class. So, please click on the link above to find more detailed information about this project (bugs-enhacements...).
I use :
public class CheckableRelativeLayout extends RelativeLayout implements Checkable {
private static final int[] CHECKED_STATE_SET = { android.R.attr.state_checked, };
private boolean mChecked;
public CheckableRelativeLayout(Context context) {
super(context);
}
public CheckableRelativeLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CheckableRelativeLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
public void setChecked(boolean checked) {
if (mChecked != checked) {
mChecked = checked;
refreshDrawableState();
}
}
#Override
public boolean isChecked() {
return mChecked;
}
#Override
public void toggle() {
setChecked(!mChecked);
}
#Override
protected int[] onCreateDrawableState(int extraSpace) {
final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
if (isChecked()) {
mergeDrawableStates(drawableState, CHECKED_STATE_SET);
}
return drawableState;
}
}
based on this and i use it like this :
<com.example.components.CheckableRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/CheckableRelativeLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/selector_background_navigation_item"
android:orientation="horizontal"
android:padding="10dp"
android:gravity="center_vertical" >
<ImageView
android:id="#+id/navigationDrawerItemImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/navigationDrawerItemTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="#+id/navigationDrawerItemImageView"
android:layout_margin="5dp"
android:layout_toRightOf="#+id/navigationDrawerItemImageView"
android:textColor="#drawable/selector_text_navigation_item"
android:textSize="#dimen/text_size_small" />
</com.example.components.CheckableRelativeLayout>
in a list item where selector_background_navigation_item defined like this :
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:state_checked="false" android:state_pressed="false" android:drawable="#color/darkblue"></item>
<item android:state_pressed="true" android:drawable="#color/sirinblue"></item>
<item android:state_checked="true" android:drawable="#color/white"></item>
</selector>
and selector_text_navigation_item defined like this :
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:state_checked="false" android:state_pressed="false" android:color="#color/white"></item>
<item android:state_pressed="true" android:color="#color/lightblue"></item>
<item android:state_checked="true" android:color="#color/lightblue"></item>
</selector>
Now, the problem is that the TextView Selector does not respond to the check events, while the CheckableRelativeLayout does, but both respond correctly to simple presses, whats the best way to fix this? maybe CheckableRelativeLayout missing some super call that handles its children checked state?
adding android:duplicateParentState="true" to the TextView did the trick!
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
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?