Search code examples
androidandroid-layoutswitch-statementandroid-custom-view

Android : Error occur on custom switch layout


I am using this approach. I did all thing which is shown in the step to show custom switch in android 2.3 or above. but when I run the application throw a error which i shown below. I also show the class which i used for that and mention the line where error occur.I applied the code also in attr and styles . please help me thanks in advance.

Class which put in com.app.widgets package.

public class Switch extends CompoundButton 
{
// left and right text
private CharSequence textLeft;
private CharSequence textRight;

public Context c;

// the background
private Drawable drawableBackground;
// the switch
private Drawable drawableSwitch;
// helper for left and right text
private Layout layoutLeft;
private Layout layoutRight;

// min width of the whole switch
private int switchMinWidth;

// actual width and height of the switch
private int width;
private int height;

// the padding left+right inside of the switch
private int innerPadding;

// the space between the text to the left of the switch and the switch
private int switchPadding;

// the colors for the text of the switch
private int textColorChecked;
private int textColorUnChecked;
private OnClickListener onClickListener;

public Switch(Context context) {
    this(context, null);
    c = context;
}

public Switch(Context context, AttributeSet attrs) {
    this(context, attrs, R.attr.switchStyle);
    Log.e("log", "in Switch(Context context, AttributeSet attrs)");
    c = context;
}

public Switch(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);

    c = context;

    this.getPaint().setAntiAlias(true);

    Log.e("log",
            "in Switch(Context context, AttributeSet attrs, int defStyle)");

    // load the default values
    TypedArray a = context.obtainStyledAttributes(attrs,
            R.styleable.Switch, defStyle, 0);
    this.textLeft = a.getText(R.styleable.Switch_textLeft);
    this.textRight = a.getText(R.styleable.Switch_textRight);
    this.switchMinWidth = a.getDimensionPixelSize(
            R.styleable.Switch_switchMinWidth, 250);
    this.textColorUnChecked = a.getColor(R.styleable.Switch_colorUnChecked,
            Color.WHITE);
    this.textColorChecked = a.getColor(R.styleable.Switch_colorChecked,
            Color.WHITE);
    this.drawableBackground = a
            .getDrawable(R.styleable.Switch_backgroundDrawable);
    this.drawableSwitch = a.getDrawable(R.styleable.Switch_switchDrawable);
    this.switchPadding = a.getDimensionPixelSize(
            R.styleable.Switch_switchPadding, 32);
    this.innerPadding = a.getDimensionPixelSize(
            R.styleable.Switch_innerPadding, 20);
    this.setChecked(a.getBoolean(R.styleable.Switch_isChecked, false));
    a.recycle();

    // throw an error if the texts have not been set
    if (this.textLeft == null || this.textRight == null)
        throw new IllegalStateException(
                "Either textLeft or textRight is null. Please them via the attributes with the same name in the layout");
}

public void setTextLeft(CharSequence textLeft) {
    if (textLeft == null)
        throw new IllegalArgumentException(
                "The text for the left side must not be null!");

    this.textLeft = textLeft;
    this.requestLayout();
}

public CharSequence getTextLeft() {
    return this.textLeft;
}

public CharSequence getTextRight() {
    return this.textRight;
}

public void setTextRight(CharSequence textRight) {

    if (textRight == null)
        throw new IllegalArgumentException(
                "The text for the right side must not be null!");

    this.textRight = textRight;
    this.requestLayout();
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    // create the helper layouts if necessary
    if (this.layoutLeft == null)
        this.layoutLeft = this.makeLayout(this.textLeft);

    if (this.layoutRight == null)
        this.layoutRight = this.makeLayout(this.textRight);

    // find the larger text so both halfs of the switch are equally wide
    final int maxTextWidth = Math.max(this.layoutLeft.getWidth(),
            this.layoutRight.getWidth());

    // calculate the width for the whole switch
    int actualWidth = Math.max(
            this.switchMinWidth,
            maxTextWidth * 2 + this.getPaddingLeft()
                    + this.getPaddingRight() + this.innerPadding * 4);



    final int switchHeight = Math.max(
            this.drawableBackground.getIntrinsicHeight(), // ****Error ON that line Which show the this.drawableBackground is null *******//
            this.drawableSwitch.getIntrinsicHeight());// ****Error ON that line Which show the this.drawableSwitch is null *******//

    this.width = actualWidth;
    this.height = switchHeight;

    // recalculate the width if there is a text
    if (this.getText() != null)
        actualWidth += this.makeLayout(this.getText()).getWidth()
                + this.switchPadding;

    // set the dimensions for this view
    setMeasuredDimension(actualWidth, switchHeight);
}

@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    // Display display = MyService.getScreenWidth(c);

    int right;
    if (AppConstants.ScreenWidth <= 480) {

        right = this.getWidth() - 10;
    } else {
        right = this.getWidth() - this.getPaddingRight();
    }
    // Log.e("LOG","width <>" + AppConstants.ScreenWidth);

    int left;
    if (AppConstants.ScreenWidth <= 480) {
        left = right - ((int) (this.width / 1.7));

    } else {
        left = right - this.width;
    }

    // draw background
    this.drawableBackground.setBounds(left, 0, right, this.height);
    this.drawableBackground.draw(canvas);

    if (AppConstants.ScreenWidth <= 480) {
        if (this.isChecked())
            this.drawableSwitch.setBounds(left, 0, left
                    + ((int) (this.width / 3.5)), this.height);
        else
            this.drawableSwitch.setBounds(left + (int) (this.width / 3.5),
                    0, right, this.height);

    } else {
        if (this.isChecked())
            this.drawableSwitch.setBounds(left, 0, left + (this.width / 2),
                    this.height);
        else
            this.drawableSwitch.setBounds(left + this.width / 2, 0, right,
                    this.height);

    }

    this.drawableSwitch.draw(canvas);

    // save canvas before translation (0x0)
    canvas.save();

    if (AppConstants.ScreenWidth <= 480) {

        // draw left text
        this.getPaint().setColor(
                this.isChecked() ? this.textColorChecked
                        : this.textColorUnChecked);
        this.getPaint().setTextSize(17);

        canvas.translate(
                (float) (left + ((this.width / 3.5) - (this.layoutLeft
                        .getWidth())) / 2), (this.height - this.layoutLeft
                        .getHeight()) / 2);
        this.layoutLeft.draw(canvas);
        canvas.restore();

        // draw right text
        this.getPaint().setColor(
                !this.isChecked() ? this.textColorChecked
                        : this.textColorUnChecked);
        this.getPaint().setTextSize(17);

        canvas.translate(
                (float) (left
                        + ((this.width / 3.5) - this.layoutRight.getWidth())
                        / 2 + (this.width / 3.5)),
                (this.height - this.layoutRight.getHeight()) / 2);
        this.layoutRight.draw(canvas);
        canvas.restore();

    } else {
        // draw left text
        this.getPaint().setColor(
                this.isChecked() ? this.textColorChecked
                        : this.textColorUnChecked);
        canvas.translate(
                left + (this.width / 2 - this.layoutLeft.getWidth()) / 2,
                (this.height - this.layoutLeft.getHeight()) / 2);
        this.layoutLeft.draw(canvas);
        canvas.restore();

        // draw right text
        this.getPaint().setColor(
                !this.isChecked() ? this.textColorChecked
                        : this.textColorUnChecked);
        canvas.translate(
                left + (this.width / 2 - this.layoutRight.getWidth()) / 2
                        + this.width / 2,
                (this.height - this.layoutRight.getHeight()) / 2);
        this.layoutRight.draw(canvas);
        canvas.restore();
    }
}

@Override
public int getCompoundPaddingRight() {
    int padding = super.getCompoundPaddingRight() + this.width;
    if (!TextUtils.isEmpty(getText()))
        padding += this.switchPadding;

    return padding;
}

@Override
public void setOnClickListener(OnClickListener l) {
    super.setOnClickListener(l);

    this.onClickListener = l;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
        this.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
        this.setChecked(!this.isChecked());
        invalidate();

        // call the onClickListener
        if (this.onClickListener != null)
            this.onClickListener.onClick(this);
        return false;
    }
    return super.onTouchEvent(event);
}

private Layout makeLayout(CharSequence text) {
    return new StaticLayout(text, this.getPaint(),
            (int) FloatMath.ceil(Layout.getDesiredWidth(text,
                    this.getPaint())), Layout.Alignment.ALIGN_NORMAL, 1f,
            0, true);
}

@Override
protected void drawableStateChanged() {
    // TODO don't use the 9-patches directly use a *.xml drawable instead
    super.drawableStateChanged();

    int[] myDrawableState = getDrawableState();

    if (this.drawableSwitch != null)
        this.drawableSwitch.setState(myDrawableState);

    invalidate();
}

public static class MyService {
    public static int getScreenWidth(Activity activity) {
        return activity.getWindowManager().getDefaultDisplay().getWidth();
    }
}
}

XML

  <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal" 
   android:background ="@drawable/sectionlist"
   xmlns:app="http://schemas.android.com/apk/res/com.example.app"
  >
 <TextView
    android:id="@+id/child_setting_header"
    android:layout_width="match_parent"
    android:layout_height="60dp"
    android:lines="1"
    android:layout_toRightOf="@+id/next"
    android:gravity="center_vertical"
    android:layout_centerVertical="true"
    android:layout_gravity="center_vertical"
    android:textColor="#FFFFFF"
    android:text="Setting"
    android:padding="8dp"
    android:textSize="@dimen/largexhdpi_menuframe_child_section_textsize"/>


<com.app.widgets.Switch
    android:id="@+id/btn_checked_unchecked"
     android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentRight="true"
    android:layout_centerVertical="true"
    android:layout_gravity="center_vertical"
    android:gravity="right"

    app:isChecked="true"
    app:textLeft="English"
    app:textRight="Hindi"
    android:visibility="visible" />

<CheckBox
    android:id="@+id/settings_check"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentRight="true"
    android:layout_centerVertical="true"
    android:layout_gravity="center_vertical"
    android:gravity="right"
    android:textColor="@color/menuframe_checkbox_textcolor"
    android:visibility="visible" />

Error

   03-07 12:32:24.141: E/AndroidRuntime(9984): FATAL EXCEPTION: main

   03-07 12:32:24.141: E/AndroidRuntime(9984): Process: com.example.app, PID: 9984
   03-07 12:32:24.141: E/AndroidRuntime(9984): java.lang.NullPointerException

    03-07 12:32:24.141: E/AndroidRuntime(9984):     at com.app.widgets.Switch.onMeasure(Switch.java:160)

    03-07 12:32:24.141: E/AndroidRuntime(9984):     at android.view.View.measure(View.java:16458)

    03-07 12:32:24.141: E/AndroidRuntime(9984):     at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:719)
    03-07 12:32:24.141: E/AndroidRuntime(9984):     at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:455)
    03-07 12:32:24.141: E/AndroidRuntime(9984):     at android.view.View.measure(View.java:16458)

    03-07 12:32:24.141: E/AndroidRuntime(9984):     at android.widget.ListView.measureScrapChild(ListView.java:1200)

    03-07 12:32:24.141: E/AndroidRuntime(9984):     at android.widget.ListView.measureHeightOfChildren(ListView.java:1265)

    03-07 12:32:24.141: E/AndroidRuntime(9984):     at android.widget.ListView.onMeasure(ListView.java:1175)

    03-07 12:32:24.141: E/AndroidRuntime(9984):     at android.view.View.measure(View.java:16458)

    03-07 12:32:24.141: E/AndroidRuntime(9984):     at android.support.v4.widget.DrawerLayout.onMeasure(DrawerLayout.java:666)
   03-07 12:32:24.141: E/AndroidRuntime(9984):  at android.view.View.measure(View.java:16458)

   03-07 12:32:24.141: E/AndroidRuntime(9984):  at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125)

   03-07 12:32:24.141: E/AndroidRuntime(9984):  at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)

   03-07 12:32:24.141: E/AndroidRuntime(9984):  at android.view.View.measure(View.java:16458)

   03-07 12:32:24.141: E/AndroidRuntime(9984):  at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125)

   03-07 12:32:24.141: E/AndroidRuntime(9984):  at com.android.internal.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java:327)

   03-07 12:32:24.141: E/AndroidRuntime(9984):  at android.view.View.measure(View.java:16458)

  03-07 12:32:24.141: E/AndroidRuntime(9984):   at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125)

  03-07 12:32:24.141: E/AndroidRuntime(9984):   at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)

  03-07 12:32:24.141: E/AndroidRuntime(9984):   at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2289)
 03-07 12:32:24.141: E/AndroidRuntime(9984):    at android.view.View.measure(View.java:16458)

 03-07 12:32:24.141: E/AndroidRuntime(9984):    at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:1914)

 03-07 12:32:24.141: E/AndroidRuntime(9984):    at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1111)

 03-07 12:32:24.141: E/AndroidRuntime(9984):    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1293)

 03-07 12:32:24.141: E/AndroidRuntime(9984):    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:998)

 03-07 12:32:24.141: E/AndroidRuntime(9984):    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5582)

 03-07 12:32:24.141: E/AndroidRuntime(9984):    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:749)

 03-07 12:32:24.141: E/AndroidRuntime(9984):    at android.view.Choreographer.doCallbacks(Choreographer.java:562)

 03-07 12:32:24.141: E/AndroidRuntime(9984):    at android.view.Choreographer.doFrame(Choreographer.java:532)

 03-07 12:32:24.141: E/AndroidRuntime(9984):    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:735)

 03-07 12:32:24.141: E/AndroidRuntime(9984):    at android.os.Handler.handleCallback(Handler.java:733)

 03-07 12:32:24.141: E/AndroidRuntime(9984):    at android.os.Handler.dispatchMessage(Handler.java:95)

 03-07 12:32:24.141: E/AndroidRuntime(9984):    at android.os.Looper.loop(Looper.java:137)

 03-07 12:32:24.141: E/AndroidRuntime(9984):    at android.app.ActivityThread.main(ActivityThread.java:4998)

 03-07 12:32:24.141: E/AndroidRuntime(9984):    at java.lang.reflect.Method.invokeNative(Native Method)

 03-07 12:32:24.141: E/AndroidRuntime(9984):    at java.lang.reflect.Method.invoke(Method.java:515)

   03-07 12:32:24.141: E/AndroidRuntime(9984):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:777)

  03-07 12:32:24.141: E/AndroidRuntime(9984):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:593)

  03-07 12:32:24.141: E/AndroidRuntime(9984):   at dalvik.system.NativeStart.main(Native Method)

Solution

  • After long time..I found the solution .sorry for disturb.just added the XML.like

      <com.app.widgets.Switch
        android:id="@+id/btn_checked_unchecked"
         android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:layout_gravity="center_vertical"
        android:gravity="right"
    
        app:isChecked="true"
        app:textLeft="English"
        app:textRight="Hindi"
        app:backgroundDrawable="@drawable/switch_bg_holo_light" // added
        app:switchDrawable="@drawable/switch_thumb_activated_holo_light"//added
        android:visibility="visible" />