Reputation: 702
Hello everyone I am trying to make my customView i.e SlideButton
So my question is when i am adding my customView as xml in activity_main and implementing callback in MainActivity all thinks works perfectly(i.e my listener is working good).
But when i do this same thing in Fragment then i get ClassCastException so i surround my code with try/catch inside init method then the error has gone.
But when i run my app and press the button does not show any Toast (i.e listener not working in Fragment)
Here is the Exception Code
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.greenlab.hackme.swipebutton, PID: 462
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.greenlab.hackme.swipebutton/com.greenlab.hackme.swipebutton.MainActivity}: android.view.InflateException: Binary XML file line #10: Binary XML file line #10: Error inflating class com.greenlab.hackme.slidebutton.SlideButton
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2723)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2784)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1523)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:163)
at android.app.ActivityThread.main(ActivityThread.java:6238)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:933)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)
Caused by: android.view.InflateException: Binary XML file line #10: Binary XML file line #10: Error inflating class com.greenlab.hackme.slidebutton.SlideButton
Caused by: android.view.InflateException: Binary XML file line #10: Error inflating class com.greenlab.hackme.slidebutton.SlideButton
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:430)
at android.view.LayoutInflater.createView(LayoutInflater.java:652)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:812)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:752)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:883)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:846)
at android.view.LayoutInflater.inflate(LayoutInflater.java:522)
at android.view.LayoutInflater.inflate(LayoutInflater.java:430)
at com.greenlab.hackme.swipebutton.ButtonFragment.onCreateView(ButtonFragment.java:28)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:2439)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1460)
at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1784)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1852)
at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:802)
at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2625)
at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2411)
at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2366)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2273)
at android.support.v4.app.FragmentManagerImpl.dispatchStateChange(FragmentManager.java:3273)
at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:3229)
at android.support.v4.app.FragmentController.dispatchActivityCreated(FragmentController.java:201)
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:620)
at android.support.v7.app.AppCompatActivity.onStart(AppCompatActivity.java:178)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1249)
at android.app.Activity.performStart(Activity.java:6883)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2686)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2784)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1523)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:163)
at android.app.ActivityThread.main(ActivityThread.java:6238)
at java.lang.reflect.Method.invoke(Native Method)
E/AndroidRuntime: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:933)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)
Caused by: java.lang.ClassCastException: com.greenlab.hackme.swipebutton.MainActivity cannot be cast to com.greenlab.hackme.slidebutton.SlideButton$SlideListener
at com.greenlab.hackme.slidebutton.SlideButton.init(SlideButton.java:81)
at com.greenlab.hackme.slidebutton.SlideButton.<init>(SlideButton.java:51)
Here is my CustomView Class
public class SlideButton extends LinearLayout implements View.OnClickListener
{
LinearLayout linearLayout;
TextView centerText;
ImageButton slidingButton;
View view;
TypedArray typedArray;
//shapes
GradientDrawable buttonCollapse,buttonExpand,backgroundButton;
String mAttrText;
Drawable disabledDrawable,enabledDrawable;
int mAttrId,mAttrButtonPadding,mAttrTextPadding,
mAttrTextSize,mAttrTextColor,mAttrRadius,mAttrCollapse,
mAttrStrokeWidth,mAttrStrokeColor,mAttrExpand,mAttrBackColor,
mAttrBackStrokeColor,mAttrBackStrokeWidth;
//it is the variable that says that the button is expand or not.
private boolean active;
//it is the initial width of the button. we need to save it so we can back to the initial position.
private int initialButtonWidth;
SlideListener listener;
public SlideButton(Context context) {
super(context);
init(context,null,-1,-1);
}
public SlideButton(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs, -1, -1);
}
public SlideButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs, defStyleAttr, -1);
}
@TargetApi(21)
public SlideButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs, defStyleAttr, defStyleRes);
}
public void init(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
attrValue(context,attrs);
btnCollapse();
btnExpand();
backButton();
dynamicLayout(context);
dynamicButton(context);
dynamicTextView(context);
new ShineEffect(centerText);
try {
listener = (SlideListener) context;
}catch (ClassCastException e){
e.printStackTrace();
}
}
/*
-----------------------------------------getting attr values---------------------------------------------------------
*/
private void attrValue(Context context,AttributeSet attrs){
typedArray=context.getTheme().obtainStyledAttributes(attrs,R.styleable.SlideButton,0,0);
try {
//attribute for id
mAttrId=typedArray.getResourceId(R.styleable.SlideButton_id,0);
//attribute for text
mAttrText = typedArray.getString(R.styleable.SlideButton_text);
mAttrTextPadding=typedArray.getDimensionPixelSize(R.styleable.SlideButton_textPadding,0);
mAttrTextSize=typedArray.getDimensionPixelSize(R.styleable.SlideButton_textSize,0);
mAttrTextColor=typedArray.getColor(R.styleable.SlideButton_textColor, Color.GRAY);
//attribute for button
mAttrButtonPadding =typedArray.getDimensionPixelSize(R.styleable.SlideButton_buttonPadding,0);
mAttrRadius=typedArray.getDimensionPixelSize(R.styleable.SlideButton_cornerRadius,45);
mAttrCollapse=typedArray.getColor(R.styleable.SlideButton_collapseColor,Color.WHITE);
mAttrExpand=typedArray.getColor(R.styleable.SlideButton_expandColor,Color.WHITE);
disabledDrawable=typedArray.getDrawable(R.styleable.SlideButton_collapseIcon);
enabledDrawable=typedArray.getDrawable(R.styleable.SlideButton_expandIcon);
mAttrStrokeColor=typedArray.getColor(R.styleable.SlideButton_strokeColor,Color.parseColor("#ee071a32"));
mAttrStrokeWidth=typedArray.getDimensionPixelSize(R.styleable.SlideButton_strokeWidth,3);
//attribute for background
mAttrBackColor=typedArray.getColor(R.styleable.SlideButton_backColor,Color.parseColor("#ee071a32"));
mAttrBackStrokeColor=typedArray.getColor(R.styleable.SlideButton_backStrokeColor,Color.WHITE);
mAttrBackStrokeWidth=typedArray.getDimensionPixelSize(R.styleable.SlideButton_backStrokeWidth,3);
}
finally {
typedArray.recycle();
}
}
/*
-----------------------------------------btn collapse shape---------------------------------------------------------
*/
private void btnCollapse(){
buttonCollapse = new GradientDrawable();
buttonCollapse.setShape(GradientDrawable.RECTANGLE);
buttonCollapse.setCornerRadius(mAttrRadius);
buttonCollapse.setColor(mAttrCollapse);
buttonCollapse.setStroke(mAttrStrokeWidth,mAttrStrokeColor);
}
/*
-----------------------------------------btn expand shape---------------------------------------------------------
*/
private void btnExpand(){
buttonExpand = new GradientDrawable();
buttonExpand.setShape(GradientDrawable.RECTANGLE);
buttonExpand.setCornerRadius(mAttrRadius);
buttonExpand.setColor(mAttrExpand);
buttonExpand.setStroke(mAttrStrokeWidth,mAttrStrokeColor);
}
/*
-----------------------------------------btn background shape---------------------------------------------------------
*/
private void backButton(){
backgroundButton = new GradientDrawable();
backgroundButton.setShape(GradientDrawable.RECTANGLE);
backgroundButton.setCornerRadius(mAttrRadius);
backgroundButton.setColor(mAttrBackColor);
backgroundButton.setStroke(mAttrBackStrokeWidth,mAttrBackStrokeColor);
}
/*
-----------------------------------------dynamic linear layout---------------------------------------------------------
*/
private void dynamicLayout(Context context) {
linearLayout=new LinearLayout(context);
//LayoutParams are used by views to tell their parents how big the view wants to be for both in width and height
linearLayout.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
linearLayout.setOrientation(LinearLayout.HORIZONTAL);
linearLayout.setBackground(backgroundButton);
linearLayout.setGravity(Gravity.START);
//add the view to parent layout
addView(linearLayout);
}
/*
-----------------------------------------dynamic text view---------------------------------------------------------
*/
private void dynamicTextView(Context context) {
centerText=new TextView(context);
centerText.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT));
centerText.setGravity(Gravity.CENTER);
centerText.setText(mAttrText);
centerText.setPadding(mAttrTextPadding,0,0,0);
centerText.setTextSize(mAttrTextSize);
centerText.setTextColor(mAttrTextColor);
linearLayout.addView(centerText);
}
/*
-----------------------------------------dynamic image button--------------------------------------------------------
*/
private void dynamicButton(Context context) {
slidingButton=new ImageButton(context);
LayoutParams params=new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.setMargins(3,3,3,3);
slidingButton.setLayoutParams(params);
slidingButton.setImageDrawable(disabledDrawable);
slidingButton.setId(mAttrId);
slidingButton.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
slidingButton.setPadding(mAttrButtonPadding,mAttrButtonPadding,mAttrButtonPadding,mAttrButtonPadding);
slidingButton.setBackground(buttonCollapse);
linearLayout.addView(slidingButton);
slidingButton.setOnClickListener(this);
}
/*
-----------------------------------------listener---------------------------------------------------------
*/
@Override
public void onClick(View view) {
this.view=view;
if(active){
collapseButton();
}
else {
initialButtonWidth=slidingButton.getWidth();
expandButton();
}
}
public interface SlideListener{
void onClick(boolean active,View v);
}
public void setOnSlideListener(SlideListener listener){
this.listener=listener;
}
/*
-----------------------------------------expand animation---------------------------------------------------------
*/
private void expandButton()
{
final ValueAnimator widthAnimator = ValueAnimator.ofInt(slidingButton.getWidth(),getWidth()-6);
widthAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation)
{
ViewGroup.LayoutParams params = slidingButton.getLayoutParams();
params.width = (Integer) widthAnimator.getAnimatedValue();
slidingButton.setLayoutParams(params);
slidingButton.setEnabled(false);
}
});
widthAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
active = true;
if (listener!=null) {
listener.onClick(true,view);
}
slidingButton.setEnabled(true);
slidingButton.setImageDrawable(enabledDrawable);
slidingButton.setBackground(buttonExpand);
}
});
widthAnimator.start();
}
/*
-----------------------------------------collapse animation---------------------------------------------------------
*/
private void collapseButton() {
final ValueAnimator widthAnimator = ValueAnimator.ofInt(slidingButton.getWidth(), initialButtonWidth);
widthAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation)
{
ViewGroup.LayoutParams params = slidingButton.getLayoutParams();
params.width = (Integer) widthAnimator.getAnimatedValue();
slidingButton.setLayoutParams(params);
slidingButton.setEnabled(false);
}
});
widthAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
active = false;
if(listener!=null){
listener.onClick(false,view);
}
slidingButton.setEnabled(true);
if(disabledDrawable!=null){
slidingButton.setImageDrawable(disabledDrawable);
}
slidingButton.setBackground(buttonCollapse);
}
});
widthAnimator.start();
}
}
Here is my customView in fragment.xml
<com.greenlab.hackme.slidebutton.SlideButton
android:layout_width="260dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="100dp"
custom:id="@+id/btnDown"
custom:buttonPadding="15dp"
custom:cornerRadius="25dp"
custom:collapseColor="@android:color/white"
custom:expandColor="@android:color/white"
custom:collapseIcon="@drawable/collapsed"
custom:expandIcon="@drawable/expanded"
custom:strokeColor="#ee071a32"
custom:strokeWidth="3dp"
custom:backStrokeColor="@android:color/white"
custom:backColor="#ee071a32"
custom:backStrokeWidth="2dp"
custom:text="Tap to Activate"
custom:textPadding="20dp"
custom:textSize="8dp"
custom:textColor="#b3a9a9">
</com.greenlab.hackme.slidebutton.SlideButton>
Here is my SlideButton Listener(CallBack) in Fragment
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
view= inflater.inflate(R.layout.fragment_button, container, false);
slideButton1=new SlideButton(getActivity());
slideButton2=new SlideButton(getActivity());
slideButton1.setOnSlideListener(this);
slideButton2.setOnSlideListener(this);
return view;
}
@Override
public void onClick(boolean active, View v) {
if(v.getId()==R.id.btnUp) {
if(active){
Toast.makeText(getContext(), "Active Up", Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(getContext(), "Deactivate Up", Toast.LENGTH_SHORT).show();
}
}else if(v.getId()==R.id.btnDown){
if(active){
Toast.makeText(getContext(), "Active Down", Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(getContext(), "Deactivate Down", Toast.LENGTH_SHORT).show();
}
}
}
After fixing ClassCastException the second problem arise is that when i click on any button btnDown is never called.
Here is update code
MainActivity implement Listener
public class MainActivity extends AppCompatActivity implements SlideButton.SlideListener {
SlideButton slideButton1,slideButton2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
slideButton1=findViewById(R.id.btnUp);
slideButton2=findViewById(R.id.btnDown);
slideButton1.setOnSlideListener(this);
slideButton2.setOnSlideListener(this);
}
@Override
public void onClick(boolean active) {
if(slideButton1.getId()==R.id.btnUp) {
if(active){
Toast.makeText(this, "Active Up", Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(this, "Deactivate Up", Toast.LENGTH_SHORT).show();
}
}else if(slideButton2.getId()==R.id.btnDown){
if(active){
Toast.makeText(this, "Active Down", Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(this, "Deactivate Down", Toast.LENGTH_SHORT).show();
}
}
}
}
activity_main.xml Update
<com.greenlab.hackme.slidebutton.SlideButton
android:id="@+id/btnUp"
android:layout_width="260dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
custom:buttonPadding="20dp"
custom:cornerRadius="45dp"
custom:collapseColor="@android:color/white"
custom:expandColor="@android:color/white"
custom:collapseIcon="@drawable/collapsed"
custom:expandIcon="@drawable/expanded"
custom:strokeColor="#ee071a32"
custom:strokeWidth="3dp"
custom:backStrokeColor="@android:color/white"
custom:backColor="#ee071a32"
custom:backStrokeWidth="2dp"
custom:text="Tap to Activate"
custom:textPadding="20dp"
custom:textSize="8dp"
custom:textColor="#a39c9c">
</com.greenlab.hackme.slidebutton.SlideButton>
<com.greenlab.hackme.slidebutton.SlideButton
android:id="@+id/btnDown"
android:layout_width="260dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="100dp"
custom:buttonPadding="15dp"
custom:cornerRadius="25dp"
custom:collapseColor="@android:color/white"
custom:expandColor="@android:color/white"
custom:collapseIcon="@drawable/collapsed"
custom:expandIcon="@drawable/expanded"
custom:strokeColor="#ee071a32"
custom:strokeWidth="3dp"
custom:backStrokeColor="@android:color/white"
custom:backColor="#ee071a32"
custom:backStrokeWidth="2dp"
custom:text="Tap to Activate"
custom:textPadding="20dp"
custom:textSize="8dp"
custom:textColor="#b3a9a9">
</com.greenlab.hackme.slidebutton.SlideButton>
CustomView class is same as above
Upvotes: 0
Views: 83
Reputation: 702
Solution of Update code i.e Listener now working for btnDown
CustomView Listener(Callback) with multiple button and different id
Upvotes: 0
Reputation: 992
The main problem is that you are creating a new object of SlideButton
in onCreateView
and setting listeners on it rather than the actual instance. To get the actual instance you need to use findViewById
but in your xml you have assigned id as custom:id
which is an additional attribute required for your component. You should assign it an id with android:id="@+id/slideButton"
and then use that id in the onCreateView like slideButton1 = view.findViewById(R.id.slideButtton)
Upvotes: 1