I am trying to fetch the value of a Datepicker inside one of my fragments . I've read the documentation about Fragments in the Android Developer Guide.
Here is my Fragment layout :
<ir.smartlab.persindatepicker.PersianDatePicker
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<Button
android:id="#+id/btnCheckFal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/relativeLayout1"
android:layout_centerHorizontal="true"
android:layout_marginTop="19dp"
android:text="#string/CheckFal" />
</RelativeLayout>
This is my java class for the fragment :
import ir.smartlab.persindatepicker.util.PersianCalendar;
public class HomeFragment extends Fragment {
private View btnCheckFalAction;
private PersianDatePicker persianDatePicker;
public HomeFragment(){}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_home, container, false);
btnCheckFalAction = (Button) rootView.findViewById(R.id.btnCheckFal);
PersianCalendar pCal = persianDatePicker.getDisplayPersianDate();
btnCheckFalAction.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v)
{
Toast.makeText(getActivity(), "Date is : " + pCal , Toast.LENGTH_LONG).show();
}
});
return rootView;
}
}
pCal in above class return error "Cannot refer to a non-final variable pCal inside an inner class ..."
and here is the DatePicker class:
package ir.smartlab.persindatepicker;
import info.androidhive.slidingmenu.R;
import ir.smartlab.persindatepicker.util.PersianCalendar;
import ir.smartlab.persindatepicker.util.PersianCalendarConstants;
import ir.smartlab.persindatepicker.util.PersianCalendarUtils;
import java.util.Date;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.NumberPicker;
public class PersianDatePicker extends LinearLayout {
private NumberPicker yearNumberPicker;
private NumberPicker monthNumberPicker;
private NumberPicker dayNumberPicker;
private int minYear;
private int maxYear;
private int yearRange;
public PersianDatePicker(Context context) {
this(context, null, -1);
}
public PersianDatePicker(Context context, AttributeSet attrs) {
this(context, attrs, -1);
}
public PersianDatePicker(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.sl_persian_date_picker, this);
yearNumberPicker = (NumberPicker) view.findViewById(R.id.yearNumberPicker);
monthNumberPicker = (NumberPicker) view.findViewById(R.id.monthNumberPicker);
dayNumberPicker = (NumberPicker) view.findViewById(R.id.dayNumberPicker);
PersianCalendar pCalendar = new PersianCalendar();
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PersianDatePicker, 0, 0);
yearRange = a.getInteger(R.styleable.PersianDatePicker_yearRange, 10);
/*
* Initializing yearNumberPicker min and max values If minYear and
* maxYear attributes are not set, use (current year - 10) as min and
* (current year + 10) as max.
*/
minYear = a.getInt(R.styleable.PersianDatePicker_minYear, pCalendar.getPersianYear() - yearRange);
maxYear = a.getInt(R.styleable.PersianDatePicker_maxYear, pCalendar.getPersianYear() + yearRange);
yearNumberPicker.setMinValue(minYear);
yearNumberPicker.setMaxValue(maxYear);
int selectedYear = a.getInt(R.styleable.PersianDatePicker_selectedYear, pCalendar.getPersianYear());
if (selectedYear > maxYear || selectedYear < minYear) {
throw new IllegalArgumentException(String.format("Selected year (%d) must be between minYear(%d) and maxYear(%d)", selectedYear, minYear, maxYear));
}
yearNumberPicker.setValue(selectedYear);
yearNumberPicker.setOnValueChangedListener(dateChangeListener);
/*
* initializng monthNumberPicker
*/
boolean displayMonthNames = a.getBoolean(R.styleable.PersianDatePicker_displayMonthNames, false);
monthNumberPicker.setMinValue(1);
monthNumberPicker.setMaxValue(12);
if (displayMonthNames) {
monthNumberPicker.setDisplayedValues(PersianCalendarConstants.persianMonthNames);
}
int selectedMonth = a.getInteger(R.styleable.PersianDatePicker_selectedMonth, pCalendar.getPersianMonth());
if (selectedMonth < 1 || selectedMonth > 12) {
throw new IllegalArgumentException(String.format("Selected month (%d) must be between 1 and 12", selectedMonth));
}
monthNumberPicker.setValue(selectedMonth);
monthNumberPicker.setOnValueChangedListener(dateChangeListener);
/*
* initializiing dayNumberPicker
*/
dayNumberPicker.setMinValue(1);
dayNumberPicker.setMaxValue(31);
int selectedDay = a.getInteger(R.styleable.PersianDatePicker_selectedDay, pCalendar.getPersianDay());
if (selectedDay > 31 || selectedDay < 1) {
throw new IllegalArgumentException(String.format("Selected day (%d) must be between 1 and 31", selectedDay));
}
if (selectedMonth > 6 && selectedMonth < 12 && selectedDay == 31) {
selectedDay = 30;
} else {
boolean isLeapYear = PersianCalendarUtils.isPersianLeapYear(selectedYear);
if (isLeapYear && selectedDay == 31) {
selectedDay = 30;
} else if (selectedDay > 29) {
selectedDay = 29;
}
}
dayNumberPicker.setValue(selectedDay);
dayNumberPicker.setOnValueChangedListener(dateChangeListener);
a.recycle();
}
NumberPicker.OnValueChangeListener dateChangeListener = new NumberPicker.OnValueChangeListener() {
#Override
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
int year = yearNumberPicker.getValue();
boolean isLeapYear = PersianCalendarUtils.isPersianLeapYear(year);
int month = monthNumberPicker.getValue();
int day = dayNumberPicker.getValue();
if (month < 7) {
dayNumberPicker.setMinValue(1);
dayNumberPicker.setMaxValue(31);
} else if (month > 6 && month < 12) {
if (day == 31) {
dayNumberPicker.setValue(30);
}
dayNumberPicker.setMinValue(1);
dayNumberPicker.setMaxValue(30);
} else if (month == 12) {
if (isLeapYear) {
if (day == 31) {
dayNumberPicker.setValue(30);
}
dayNumberPicker.setMinValue(1);
dayNumberPicker.setMaxValue(30);
} else {
if (day > 29) {
dayNumberPicker.setValue(29);
}
dayNumberPicker.setMinValue(1);
dayNumberPicker.setMaxValue(29);
}
}
}
};
public Date getDisplayDate() {
PersianCalendar displayPersianDate = new PersianCalendar();
displayPersianDate.setPersianDate(yearNumberPicker.getValue(), monthNumberPicker.getValue(), dayNumberPicker.getValue());
return displayPersianDate.getTime();
}
public void setDisplayDate(Date displayDate) {
setDisplayPersianDate(new PersianCalendar(displayDate.getTime()));
}
public PersianCalendar getDisplayPersianDate() {
PersianCalendar displayPersianDate = new PersianCalendar();
displayPersianDate.setPersianDate(yearNumberPicker.getValue(), monthNumberPicker.getValue(), dayNumberPicker.getValue());
return displayPersianDate;
}
public void setDisplayPersianDate(PersianCalendar displayPersianDate) {
int year = displayPersianDate.getPersianYear();
int month = displayPersianDate.getPersianMonth();
int day = displayPersianDate.getPersianDay();
if (month > 6 && month < 12 && day == 31) {
day = 30;
} else {
boolean isLeapYear = PersianCalendarUtils.isPersianLeapYear(year);
if (isLeapYear && day == 31) {
day = 30;
} else if (day > 29) {
day = 29;
}
}
dayNumberPicker.setValue(day);
minYear = year - yearRange;
maxYear = year + yearRange;
yearNumberPicker.setMinValue(minYear);
yearNumberPicker.setMaxValue(maxYear);
yearNumberPicker.setValue(year);
monthNumberPicker.setValue(month);
dayNumberPicker.setValue(day);
}
#Override
protected Parcelable onSaveInstanceState() {
// begin boilerplate code that allows parent classes to save state
Parcelable superState = super.onSaveInstanceState();
SavedState ss = new SavedState(superState);
// end
ss.datetime = this.getDisplayDate().getTime();
return ss;
}
#Override
protected void onRestoreInstanceState(Parcelable state) {
// begin boilerplate code so parent classes can restore state
if (!(state instanceof SavedState)) {
super.onRestoreInstanceState(state);
return;
}
SavedState ss = (SavedState) state;
super.onRestoreInstanceState(ss.getSuperState());
// end
setDisplayDate(new Date(ss.datetime));
}
static class SavedState extends BaseSavedState {
long datetime;
SavedState(Parcelable superState) {
super(superState);
}
private SavedState(Parcel in) {
super(in);
this.datetime = in.readLong();
}
#Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeLong(this.datetime);
}
// required field that makes Parcelables from a Parcel
public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() {
#Override
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
#Override
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
}
It's simple.
Make pCal final, if you don't have to change its value during execution.
OR
Make pCal a class variable if you don't have any problems with a wider scope.
Declare pCal variable as final and initialise persianDatePicker view using findViewById().
You can change the code like this,
btnCheckFalAction = (Button) rootView.findViewById(R.id.btnCheckFal);
persianDatePicker = (PersianDatePicker) rootView.findViewById(R.id.persianDatePicker);
PersianCalendar pCal = persianDatePicker.getDisplayPersianDate();
and also edit your xml like this,
<ir.smartlab.persindatepicker.PersianDatePicker
android:id="#+id/persianDatePicker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
Related
I want to know something...
What's wrong about my ListView, the problem is when I perform a fast scroll sometimes my application stopped...
In my MainActivity extending the a4 class ----> that extends Activity class:
ArrayList<a> AL;
static ListView LV;
SearchView SV;
Toast TOAST;
TextView TV;
static boolean isEnglish;
private static boolean isSearching, canClear;
static MultiList newAdapter;
LinearLayout NV;
static RelativeLayout.LayoutParams PR;
ImageButton IB;
ImageView IV;
public void closeSearch(View view) {
if (!isSearching) return;
TV.setVisibility(0);
IB.setVisibility(8);
SV.onActionViewCollapsed();
PR.removeRule(9);
isSearching = false;
}
public void d(View view) {
num(true, 5, 0, 8);
}
public void e(View view) {
num(false, 6, 8, 0);
}
public void goInfo(View view) {
co(3);
}
public void goIns(View view) {
co(2);
}
public void goSet(View view) {
co(4);
}
public void goTools(View view) {
co(1);
}
void num(boolean bl, final int n, int n2, int n3) {
int n4 = 0;
isEnglish = bl;
AL = new ArrayList<a>();
newAdapter = new MultiList(this, true, AL);
findViewById(R.id.l1).setVisibility(n2);
findViewById(R.id.l2).setVisibility(n3);
LV.setAdapter(newAdapter);
LV.setOnItemClickListener(new AdapterView.OnItemClickListener(){
public void onItemClick(AdapterView<?> adapterView, View view, int ol, long l) {
rt(n, ol);
}
});
do {
if(bl){
if(n4 >= songs_e.length || n4 >= singers_e.length) return;
AL.add(new a(songs_e[n4], singers_e[n4]));
} else {
if(n4 >= artists.length) return;
AL.add(new a(artists[n4]));
}
++n4;
} while (true);
}
public void onBackPressed() {
if(isSearching) {
closeSearch(isViewed);
} else {
if (b0 < System.currentTimeMillis() - 1600L) {
TOAST = Toast.makeText(this, "Tap again to exit " + app, 0);
TOAST.show();
b0 = System.currentTimeMillis();
return;
} else {
if (TOAST != null) {
TOAST.cancel();
finish();
return;
}
}
}
}
#Override
protected void onCreate(Bundle bundle) {
show(4, R.layout.slist, q + app, 0);
LV = findViewById(R.id.lv);
SV = findViewById(R.id.search);
TV = findViewById(R.id.mytv);
NV = findViewById(R.id.llp);
PR = (RelativeLayout.LayoutParams)SV.getLayoutParams();
IB = findViewById(R.id.search_close);
IV = (ImageView)findViewById((View)SV, "android:id/search_close_btn");
final TextView actv = (TextView)findViewById(SV, "android:id/search_src_text");
actv.setBackgroundColor(-1);
ImageView imageView2 = (ImageView)findViewById((View)SV, "android:id/search_button");
imageView2.setImageResource(R.drawable.ic_search);
imageView2.setBackgroundColor(-12369085);
LV.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener(){
public boolean onItemLongClick(AdapterView<?> av, View v, int n, long l){
return true;
}
});
IV.setOnClickListener(new View.OnClickListener(){
public void onClick(View view) {
if(canClear){
actv.setText("");
}
}
});
d(isViewed);
newAdapter.initForMulti(R.layout.abc_listview, R.id.txt1, R.id.txt2, R.id.image, R.drawable.abc_tab);
SV.setLayoutParams(PR);
SV.setQueryHint(" Search songs and artists . . .");
SV.setOnSearchClickListener(new View.OnClickListener(){
public void onClick(View view) {
IV.setImageResource(R.drawable.search_clear_inactive);
TV.setVisibility(8);
canClear = false;
isSearching = true;
IB.setVisibility(0);
PR.addRule(9);
}
});
SV.setOnQueryTextListener(new SearchView.OnQueryTextListener(){
public boolean onQueryTextChange(String string2) {
ArrayList<a> arrayList = new ArrayList<a>();
if(string2.equals((Object)"")) {
IV.setImageResource(R.drawable.search_clear_inactive);
canClear = false;
} else {
IV.setImageResource(R.drawable.search_clear_active);
canClear = true;
}
//Error for Tagalog, text is not for multi
for (a aa : MainActivity.this.AL) {
if (isEnglish && !aa.getFirst().toLowerCase().contains(string2) && !aa.getFirst().toUpperCase().contains(string2) && !aa.getFirst().contains(string2) && !aa.getLast().toLowerCase().contains(string2) && !aa.getLast().toUpperCase().contains(string2) && !aa.getLast().contains(string2) || !isEnglish && !aa.getLast().toLowerCase().contains(string2) && !aa.getLast().toUpperCase().contains(string2) && !aa.getLast().contains(string2)) continue;
arrayList.add(aa);
}
newAdapter.filterResult((ArrayList<a>)arrayList);
return false;
}
public boolean onQueryTextSubmit(String string2) {
return true;
}
});
MusicUtils.playAsset(this, "audios/a.ogg");
IV.setBackgroundColor(-12369085);
super.onCreate(bundle);
}
public void onPause() {
super.onPause();
closeSearch(isViewed);
if (in != 5 && in != 6) {
LV.setVisibility(4);
int n = 0;
do {
if (n >= 10) return;
LV.scrollListBy(-999999999);
++n;
} while (true);
}
}
//onRestart not included because it basically contains setVisibility
final void rt(int n, int n2) {
in = n;
Bundle bundle = new Bundle();
newAdapter.getLC(n2);
bundle.putString("First", newAdapter.list.getFirst());
bundle.putString("Last", newAdapter.list.getLast());
go(new Intent(this, ContProv.class).putExtras(bundle));
}
And for the custom list adapter:
private static Context Context;
private static ArrayList<a> ab;
private static int view, mText, mText1, mText2, mImage, mDrawable;
private static boolean listType;
public a list;
public MultiList(Context c, boolean isMultiText, ArrayList<a> array) {
if(c != null || array != null) {
Context = c;
listType = isMultiText;
ab = array;
}
}
public final void initForMulti(int layout, int text1ID, int text2ID, int imageID, int imageDrawable) {
view = layout;
mText1 = text1ID;
mText2 = text2ID;
mImage = imageID;
mDrawable = imageDrawable;
}
public final void initForNonMulti(int layout, int textID, int imageID, int imageDrawable){
view = layout;
mText = textID;
mImage = imageID;
mDrawable = imageDrawable;
}
public void filterResult(ArrayList<a> arrayList) {
ab = new ArrayList<a>();
ab.addAll((ArrayList<a>)arrayList);
notifyDataSetChanged();
}
public int getCount() {
return ab.size();
}
public Object getItem(int n) {
return null;
}
public long getItemId(int n) {
return 0L;
}
public a getLC(int n) {
return list = ab.get(n);
}
public View getView(int n, View v, ViewGroup vg) {
a newList = getLC(n);
v = View.inflate(Context, view, null);
((ImageView)v.findViewById(mImage)).setImageResource(mDrawable);
if(listType) {
((TextView)v.findViewById(mText1)).setText(newList.getFirst());
((TextView)v.findViewById(mText2)).setText(newList.getLast());
} else ((TextView)v.findViewById(mText)).setText(newList.getText());
return v;
}
Thank you for your help... I will really appreciate it... Also I need tips about the performance of my existing code and please write your answer in java and don't use support libraries cuz I want my application work for android phones below android 5...
Final:
I've found out that the problem is at my list adapter so I edited it into this:
package dn.widget;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import dn.widget.ListAdapter;
import dn.widget.a.a;
import java.util.ArrayList;
public class ListAdapter extends BaseAdapter {
private ArrayList<a> AR;
private static int N, N2, N3, N4, N5, N6;
private boolean LT;
public a L;
public ListAdapter(ArrayList<a> ar, boolean b) {
AR = ar;
LT = b;
}
public void isDual(int n, int n2, int n3, int n4, int n5) {
if (LT) {
N = n;
N3 = n2;
N4 = n3;
N5 = n4;
N6 = n5;
}
}
public void isSingle(int n, int n2, int n3, int n4){
if (!LT) {
N = n;
N2 = n2;
N4 = n3;
N5 = n4;
}
}
public void filterResult(ArrayList<a> ar) {
if(AR != null) {
AR = new ArrayList<a>();
AR.addAll((ArrayList<a>)ar);
notifyDataSetChanged();
}
}
public int getCount() {
return AR.size();
}
public Object getItem(int n) {
return null;
}
public long getItemId(int n) {
return 0L;
}
public a getLC(int n) {
L = AR.get(n);
return L;
}
static class LH {
private ImageView I;
private TextView T, T1, T2;
}
#Override
public View getView(int n, View v, ViewGroup g) {
getLC(n);
final LH h;
if(v == null) {
v = View.inflate(g.getContext(), N, null);
h = new LH();
h.I = v.findViewById(N5);
h.T = v.findViewById(N2);
h.T1 = v.findViewById(N3);
h.T2 = v.findViewById(N4);
h.I.setImageResource(N6);
v.setTag(h);
} else {
h = (LH)v.getTag();
}
if(LT) {
h.T1.setText(L.f());
h.T2.setText(L.l());
} else h.T.setText(L.t());
return v;
}
}
I'm trying to convert a TimePicker preference dialog extended from android.support.v7.preference.DialogPreference to the same but extended from androidx.preference.DialogPreference.
Here is the code of the original custom preference :
package com.example.example;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import android.content.Context;
import android.content.res.TypedArray;
import android.preference.DialogPreference;
import android.util.AttributeSet;
import android.view.View;
import android.widget.TimePicker;
public class TimePreference extends DialogPreference {
private int mHour = 0;
private int mMinute = 0;
private TimePicker picker = null;
private final String DEFAULT_VALUE = "00:00";
public static int getHour(String time) {
String[] pieces = time.split(":");
return Integer.parseInt(pieces[0]);
}
public static int getMinute(String time) {
String[] pieces = time.split(":");
return Integer.parseInt(pieces[1]);
}
public TimePreference(Context context) {
this(context, null);
}
public TimePreference(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public TimePreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setPositiveButtonText("Set");
setNegativeButtonText("Cancel");
}
public void setTime(int hour, int minute) {
mHour = hour;
mMinute = minute;
String time = toTime(mHour, mMinute);
persistString(time);
notifyDependencyChange(shouldDisableDependents());
notifyChanged();
}
public String toTime(int hour, int minute) {
return hour + ":" + minute;
}
public void updateSummary() {
String time = mHour + ":" + mMinute;
setSummary(time24to12(time));
}
#Override
protected View onCreateDialogView() {
picker = new TimePicker(getContext());
return picker;
}
#Override
protected void onBindDialogView(View v) {
super.onBindDialogView(v);
picker.setCurrentHour(mHour);
picker.setCurrentMinute(mMinute);
}
#Override
protected void onDialogClosed(boolean positiveResult) {
super.onDialogClosed(positiveResult);
if (positiveResult) {
int currHour = picker.getCurrentHour();
int currMinute = picker.getCurrentMinute();
if (!callChangeListener(toTime(currHour, currMinute))) {
return;
}
// persist
setTime(currHour, currMinute);
updateSummary();
}
}
#Override
protected Object onGetDefaultValue(TypedArray a, int index) {
return a.getString(index);
}
#Override
protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
String time = null;
if (restorePersistedValue) {
if (defaultValue == null) {
time = getPersistedString(DEFAULT_VALUE);
}
else {
time = getPersistedString(DEFAULT_VALUE);
}
}
else {
time = defaultValue.toString();
}
int currHour = getHour(time);
int currMinute = getMinute(time);
// need to persist here for default value to work
setTime(currHour, currMinute);
updateSummary();
}
public static Date toDate(String inTime) {
try {
DateFormat inTimeFormat = new SimpleDateFormat("HH:mm", Locale.US);
return inTimeFormat.parse(inTime);
} catch(ParseException e) {
return null;
}
}
public static String time24to12(String inTime) {
Date inDate = toDate(inTime);
if(inDate != null) {
DateFormat outTimeFormat = new SimpleDateFormat("hh:mm a", Locale.US);
return outTimeFormat.format(inDate);
} else {
return inTime;
}
}
}
If I try to use that directly in my preference fragment, the app crashed with the following error :
android.view.InflateException: Binary XML file line #27: Error inflating class com.example.example.TimePreference
...
Caused by: java.lang.ClassCastException: com.example.example.TimePreference cannot be cast to androidx.preference.Preference
That's normal, considering the fact that my custom preference is not an androidx.preference
I haven't found any information on how to convert an old android.support.v7.preference to a new androidx.preference. Does anyone know how to do so ?
Thanks a lot !
I am using PullToRefreshListView to provide data reload when pulling the listview.
But my problem is that after refreshing, the layout leaves a space on top of the listview. See the image below:
I want to remove the space on top. I tried setting the view to View.GONE but it still leaves a small space in it.
Here's the code for the PullToRefreshListView.java:
package com.markupartist.android.widget;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.AbsListView.OnScrollListener;
public class PullToRefreshListView extends ListView implements OnScrollListener {
private static final int TAP_TO_REFRESH = 1;
private static final int PULL_TO_REFRESH = 2;
private static final int RELEASE_TO_REFRESH = 3;
private static final int REFRESHING = 4;
private static final String TAG = "PullToRefreshListView";
private OnRefreshListener mOnRefreshListener;
/**
* Listener that will receive notifications every time the list scrolls.
*/
private OnScrollListener mOnScrollListener;
private LayoutInflater mInflater;
private RelativeLayout mRefreshView;
private TextView mRefreshViewText;
private ImageView mRefreshViewImage;
private ProgressBar mRefreshViewProgress;
private TextView mRefreshViewLastUpdated;
private int mCurrentScrollState;
private int mRefreshState;
private RotateAnimation mFlipAnimation;
private RotateAnimation mReverseFlipAnimation;
private int mRefreshViewHeight;
private int mRefreshOriginalTopPadding;
private int mLastMotionY;
private boolean mBounceHack;
public PullToRefreshListView(Context context) {
super(context);
init(context);
}
public PullToRefreshListView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public PullToRefreshListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
private void init(Context context) {
// Load all of the animations we need in code rather than through XML
mFlipAnimation = new RotateAnimation(0, -180,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
mFlipAnimation.setInterpolator(new LinearInterpolator());
mFlipAnimation.setDuration(250);
mFlipAnimation.setFillAfter(true);
mReverseFlipAnimation = new RotateAnimation(-180, 0,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
mReverseFlipAnimation.setInterpolator(new LinearInterpolator());
mReverseFlipAnimation.setDuration(250);
mReverseFlipAnimation.setFillAfter(true);
mInflater = (LayoutInflater) context.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
mRefreshView = (RelativeLayout) mInflater.inflate(
R.layout.pull_to_refresh_header, this, false);
mRefreshViewText =
(TextView) mRefreshView.findViewById(R.id.pull_to_refresh_text);
mRefreshViewImage =
(ImageView) mRefreshView.findViewById(R.id.pull_to_refresh_image);
mRefreshViewProgress =
(ProgressBar) mRefreshView.findViewById(R.id.pull_to_refresh_progress);
mRefreshViewLastUpdated =
(TextView) mRefreshView.findViewById(R.id.pull_to_refresh_updated_at);
mRefreshViewImage.setMinimumHeight(50);
mRefreshView.setOnClickListener(new OnClickRefreshListener());
mRefreshOriginalTopPadding = mRefreshView.getPaddingTop();
mRefreshState = TAP_TO_REFRESH;
addHeaderView(mRefreshView);
super.setOnScrollListener(this);
measureView(mRefreshView);
mRefreshViewHeight = mRefreshView.getMeasuredHeight();
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
setSelection(1);
}
#Override
public void setAdapter(ListAdapter adapter) {
super.setAdapter(adapter);
setSelection(1);
}
/**
* Set the listener that will receive notifications every time the list
* scrolls.
*
* #param l The scroll listener.
*/
#Override
public void setOnScrollListener(OnScrollListener l) {
mOnScrollListener = l;
}
/**
* Register a callback to be invoked when this list should be refreshed.
*
* #param onRefreshListener The callback to run.
*/
public void setOnRefreshListener(OnRefreshListener onRefreshListener) {
mOnRefreshListener = onRefreshListener;
}
/**
* Set a text to represent when the list was last updated.
* #param lastUpdated Last updated at.
*/
public void setLastUpdated(CharSequence lastUpdated) {
if (lastUpdated != null) {
mRefreshViewLastUpdated.setVisibility(View.VISIBLE);
mRefreshViewLastUpdated.setText(lastUpdated);
} else {
mRefreshViewLastUpdated.setVisibility(View.GONE);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
final int y = (int) event.getY();
mBounceHack = false;
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
if (!isVerticalScrollBarEnabled()) {
setVerticalScrollBarEnabled(true);
}
if (getFirstVisiblePosition() == 0 && mRefreshState != REFRESHING) {
if ((mRefreshView.getBottom() >= mRefreshViewHeight
|| mRefreshView.getTop() >= 0)
&& mRefreshState == RELEASE_TO_REFRESH) {
// Initiate the refresh
mRefreshState = REFRESHING;
prepareForRefresh();
onRefresh();
} else if (mRefreshView.getBottom() < mRefreshViewHeight
|| mRefreshView.getTop() <= 0) {
// Abort refresh and scroll down below the refresh view
resetHeader();
setSelection(1);
}
}
break;
case MotionEvent.ACTION_DOWN:
mLastMotionY = y;
break;
case MotionEvent.ACTION_MOVE:
applyHeaderPadding(event);
break;
}
return super.onTouchEvent(event);
}
private void applyHeaderPadding(MotionEvent ev) {
// getHistorySize has been available since API 1
int pointerCount = ev.getHistorySize();
for (int p = 0; p < pointerCount; p++) {
if (mRefreshState == RELEASE_TO_REFRESH) {
if (isVerticalFadingEdgeEnabled()) {
setVerticalScrollBarEnabled(false);
}
int historicalY = (int) ev.getHistoricalY(p);
// Calculate the padding to apply, we divide by 1.7 to
// simulate a more resistant effect during pull.
int topPadding = (int) (((historicalY - mLastMotionY)
- mRefreshViewHeight) / 1.7);
mRefreshView.setPadding(
mRefreshView.getPaddingLeft(),
topPadding,
mRefreshView.getPaddingRight(),
mRefreshView.getPaddingBottom());
}
}
}
/**
* Sets the header padding back to original size.
*/
private void resetHeaderPadding() {
Log.i("top padding", "" + mRefreshOriginalTopPadding);
mRefreshView.setPadding(
mRefreshView.getPaddingLeft(),
0,
mRefreshView.getPaddingRight(),
mRefreshView.getPaddingBottom());
}
/**
* Resets the header to the original state.
*/
private void resetHeader() {
if (mRefreshState != TAP_TO_REFRESH) {
mRefreshState = TAP_TO_REFRESH;
resetHeaderPadding();
// Set refresh view text to the pull label
//mRefreshViewText.setText(R.string.pull_to_refresh_tap_label);
//mRefreshViewText.setVisibility(View.GONE);
// Replace refresh drawable with arrow drawable
mRefreshViewImage.setImageResource(R.drawable.ic_pulltorefresh_arrow);
// Clear the full rotation animation
mRefreshViewImage.clearAnimation();
// Hide progress bar and arrow.
mRefreshViewImage.setVisibility(View.GONE);
mRefreshViewProgress.setVisibility(View.GONE);
//this.setSelectionAfterHeaderView();
}
}
private void measureView(View child) {
ViewGroup.LayoutParams p = child.getLayoutParams();
if (p == null) {
p = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
}
int childWidthSpec = ViewGroup.getChildMeasureSpec(0,
0 + 0, p.width);
int lpHeight = p.height;
int childHeightSpec;
if (lpHeight > 0) {
childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
} else {
childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
}
child.measure(childWidthSpec, childHeightSpec);
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// When the refresh view is completely visible, change the text to say
// "Release to refresh..." and flip the arrow drawable.
if (mCurrentScrollState == SCROLL_STATE_TOUCH_SCROLL
&& mRefreshState != REFRESHING) {
if (firstVisibleItem == 0) {
mRefreshViewImage.setVisibility(View.VISIBLE);
if ((mRefreshView.getBottom() >= mRefreshViewHeight + 20
|| mRefreshView.getTop() >= 0)
&& mRefreshState != RELEASE_TO_REFRESH) {
mRefreshViewText.setText(R.string.pull_to_refresh_release_label);
mRefreshViewImage.clearAnimation();
mRefreshViewImage.startAnimation(mFlipAnimation);
mRefreshState = RELEASE_TO_REFRESH;
} else if (mRefreshView.getBottom() < mRefreshViewHeight + 20
&& mRefreshState != PULL_TO_REFRESH) {
mRefreshViewText.setText(R.string.pull_to_refresh_pull_label);
if (mRefreshState != TAP_TO_REFRESH) {
mRefreshViewImage.clearAnimation();
mRefreshViewImage.startAnimation(mReverseFlipAnimation);
}
mRefreshState = PULL_TO_REFRESH;
}
} else {
mRefreshViewImage.setVisibility(View.GONE);
resetHeader();
}
} else if (mCurrentScrollState == SCROLL_STATE_FLING
&& firstVisibleItem == 0
&& mRefreshState != REFRESHING) {
Log.i("I am here", "");
setSelection(1);
mBounceHack = true;
} else if (mBounceHack && mCurrentScrollState == SCROLL_STATE_FLING) {
setSelection(1);
}
if (mOnScrollListener != null) {
mOnScrollListener.onScroll(view, firstVisibleItem,
visibleItemCount, totalItemCount);
}
}
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
mCurrentScrollState = scrollState;
if (mCurrentScrollState == SCROLL_STATE_IDLE) {
mBounceHack = false;
}
if (mOnScrollListener != null) {
mOnScrollListener.onScrollStateChanged(view, scrollState);
}
}
public void prepareForRefresh() {
resetHeaderPadding();
mRefreshViewImage.setVisibility(View.GONE);
// We need this hack, otherwise it will keep the previous drawable.
mRefreshViewImage.setImageDrawable(null);
mRefreshViewProgress.setVisibility(View.VISIBLE);
// Set refresh view text to the refreshing label
mRefreshViewText.setText(R.string.pull_to_refresh_refreshing_label);
mRefreshState = REFRESHING;
}
public void onRefresh() {
Log.d(TAG, "onRefresh");
if (mOnRefreshListener != null) {
mOnRefreshListener.onRefresh();
}
}
/**
* Resets the list to a normal state after a refresh.
* #param lastUpdated Last updated at.
*/
public void onRefreshComplete(CharSequence lastUpdated) {
setLastUpdated(lastUpdated);
onRefreshComplete();
}
/**
* Resets the list to a normal state after a refresh.
*/
public void onRefreshComplete() {
Log.d(TAG, "onRefreshComplete");
resetHeader();
// If refresh view is visible when loading completes, scroll down to
// the next item.
if (getFirstVisiblePosition() == 0) {
invalidateViews();
setSelection(1);
}
resetHeader();
}
/**
* Invoked when the refresh view is clicked on. This is mainly used when
* there's only a few items in the list and it's not possible to drag the
* list.
*/
private class OnClickRefreshListener implements OnClickListener {
#Override
public void onClick(View v) {
if (mRefreshState != REFRESHING) {
prepareForRefresh();
onRefresh();
}
}
}
/**
* Interface definition for a callback to be invoked when list should be
* refreshed.
*/
public interface OnRefreshListener {
/**
* Called when the list should be refreshed.
* <p>
* A call to {#link PullToRefreshListView #onRefreshComplete()} is
* expected to indicate that the refresh has completed.
*/
public void onRefresh();
}
}
I would suggest you to Just disable listview onrefresh listener and
use android.support.v4.widget.SwipeRefreshLayout instead of pull to refresh listview . It is very easy to use.
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/refreshLater"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
***Place Your listview here***
</android.support.v4.widget.SwipeRefreshLayout >
you can set refresh listener on it like this:
public SwipeRefreshLayout swipeRefreshLayout;
swipeRefreshLayout = (SwipeRefreshLayout)findViewById(R.id.refreshLater);
swipeRefreshLayout.setOnRefreshListener(this);
you can do needed code in the below override method:
#Override
public void onRefresh()
{
swipeRefreshLayout.setRefreshing(false);
}
I am using PagerSlidingTabStrip in an Android project.
When I swipe through the tabs, it is working correctly.
However, when I click on a tab, the tab does not change.
Here is the activity XML:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<au.edu.me.meandroidapplication.view.thirdparty.PagerSlidingTabStrip
android:id="#+id/progress_pager_tab_strip"
android:layout_width="match_parent"
android:layout_height="48dip"
app:pstsShouldExpand="true"
app:pstsIndicatorColor="#color/meTabIndicator"
app:pstsDividerColor="#color/meTabSeparator"
android:background="#color/meTabBackground" />
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/progressViewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="au.edu.me.meandroidapplication.view.activity.MyProgressActivity" />
</RelativeLayout>
Here is my code in onCreate():
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_progress);
this.viewPager = (ViewPager)this.findViewById(R.id.progressViewPager);
this.pagerAdapter = new MyProgressFragmentPagerAdapter(this.getSupportFragmentManager());
this.viewPager.setAdapter(this.pagerAdapter);
PagerSlidingTabStrip pagerTabStrip = (PagerSlidingTabStrip)this.findViewById(R.id.progress_pager_tab_strip);
pagerTabStrip.setViewPager(this.viewPager);
pagerTabStrip.setTextColorResource(R.color.meTabText);
}
Any advice on how to click the buttons to also change the tabs would be greatly appreciated!
Edit: yes the importing is from this project and not any other one. here is the code for PagerSlidingTabStrip
package au.edu.me.meandroidapplication.view.thirdparty;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Typeface;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.HorizontalScrollView;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.Locale;
import au.edu.me.meandroidapplication.R;
public class PagerSlidingTabStrip extends HorizontalScrollView {
public interface IconTabProvider {
public int getPageIconResId(int position);
}
// #formatter:off
private static final int[] ATTRS = new int[] {
android.R.attr.textSize,
android.R.attr.textColor
};
// #formatter:on
private LinearLayout.LayoutParams defaultTabLayoutParams;
private LinearLayout.LayoutParams expandedTabLayoutParams;
private final PageListener pageListener = new PageListener();
public OnPageChangeListener delegatePageListener;
private LinearLayout tabsContainer;
private ViewPager pager;
private int tabCount;
private int currentPosition = 0;
private float currentPositionOffset = 0f;
private Paint rectPaint;
private Paint dividerPaint;
private int indicatorColor = 0xFF666666;
private int underlineColor = 0x1A000000;
private int dividerColor = 0x1A000000;
private boolean shouldExpand = false;
private boolean textAllCaps = true;
private int scrollOffset = 52;
private int indicatorHeight = 8;
private int underlineHeight = 2;
private int dividerPadding = 12;
private int tabPadding = 24;
private int dividerWidth = 1;
private int tabTextSize = 12;
private int tabTextColor = 0xFF666666;
private Typeface tabTypeface = null;
private int tabTypefaceStyle = Typeface.BOLD;
private int lastScrollX = 0;
private int tabBackgroundResId = -1; // ### REMOVED
private Locale locale;
public PagerSlidingTabStrip(Context context) {
this(context, null);
}
public PagerSlidingTabStrip(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public PagerSlidingTabStrip(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setFillViewport(true);
setWillNotDraw(false);
tabsContainer = new LinearLayout(context);
tabsContainer.setOrientation(LinearLayout.HORIZONTAL);
tabsContainer.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
addView(tabsContainer);
DisplayMetrics dm = getResources().getDisplayMetrics();
scrollOffset = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, scrollOffset, dm);
indicatorHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, indicatorHeight, dm);
underlineHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, underlineHeight, dm);
dividerPadding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dividerPadding, dm);
tabPadding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, tabPadding, dm);
dividerWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dividerWidth, dm);
tabTextSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, tabTextSize, dm);
// get system attrs (android:textSize and android:textColor)
TypedArray a = context.obtainStyledAttributes(attrs, ATTRS);
tabTextSize = a.getDimensionPixelSize(0, tabTextSize);
tabTextColor = a.getColor(1, tabTextColor);
a.recycle();
// get custom attrs
a = context.obtainStyledAttributes(attrs, R.styleable.PagerSlidingTabStrip);
indicatorColor = a.getColor(R.styleable.PagerSlidingTabStrip_pstsIndicatorColor, indicatorColor);
underlineColor = a.getColor(R.styleable.PagerSlidingTabStrip_pstsUnderlineColor, underlineColor);
dividerColor = a.getColor(R.styleable.PagerSlidingTabStrip_pstsDividerColor, dividerColor);
indicatorHeight = a.getDimensionPixelSize(R.styleable.PagerSlidingTabStrip_pstsIndicatorHeight, indicatorHeight);
underlineHeight = a.getDimensionPixelSize(R.styleable.PagerSlidingTabStrip_pstsUnderlineHeight, underlineHeight);
dividerPadding = a.getDimensionPixelSize(R.styleable.PagerSlidingTabStrip_pstsDividerPadding, dividerPadding);
tabPadding = a.getDimensionPixelSize(R.styleable.PagerSlidingTabStrip_pstsTabPaddingLeftRight, tabPadding);
tabBackgroundResId = a.getResourceId(R.styleable.PagerSlidingTabStrip_pstsTabBackground, tabBackgroundResId);
shouldExpand = a.getBoolean(R.styleable.PagerSlidingTabStrip_pstsShouldExpand, shouldExpand);
scrollOffset = a.getDimensionPixelSize(R.styleable.PagerSlidingTabStrip_pstsScrollOffset, scrollOffset);
textAllCaps = a.getBoolean(R.styleable.PagerSlidingTabStrip_pstsTextAllCaps, textAllCaps);
a.recycle();
rectPaint = new Paint();
rectPaint.setAntiAlias(true);
rectPaint.setStyle(Style.FILL);
dividerPaint = new Paint();
dividerPaint.setAntiAlias(true);
dividerPaint.setStrokeWidth(dividerWidth);
defaultTabLayoutParams = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
expandedTabLayoutParams = new LinearLayout.LayoutParams(0, LayoutParams.MATCH_PARENT, 1.0f);
if (locale == null) {
locale = getResources().getConfiguration().locale;
}
}
public void setViewPager(ViewPager pager) {
this.pager = pager;
if (pager.getAdapter() == null) {
throw new IllegalStateException("ViewPager does not have adapter instance.");
}
pager.setOnPageChangeListener(pageListener);
notifyDataSetChanged();
}
public void setOnPageChangeListener(OnPageChangeListener listener) {
this.delegatePageListener = listener;
}
public void notifyDataSetChanged() {
tabsContainer.removeAllViews();
tabCount = pager.getAdapter().getCount();
for (int i = 0; i < tabCount; i++) {
if (pager.getAdapter() instanceof IconTabProvider) {
addIconTab(i, ((IconTabProvider) pager.getAdapter()).getPageIconResId(i));
} else {
addTextTab(i, pager.getAdapter().getPageTitle(i).toString());
}
}
updateTabStyles();
getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#SuppressWarnings("deprecation")
#SuppressLint("NewApi")
#Override
public void onGlobalLayout() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
getViewTreeObserver().removeGlobalOnLayoutListener(this);
} else {
getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
currentPosition = pager.getCurrentItem();
scrollToChild(currentPosition, 0);
}
});
}
private void addTextTab(final int position, String title) {
TextView tab = new TextView(getContext());
tab.setText(title);
tab.setGravity(Gravity.CENTER);
tab.setSingleLine();
addTab(position, tab);
}
private void addIconTab(final int position, int resId) {
ImageButton tab = new ImageButton(getContext());
tab.setImageResource(resId);
addTab(position, tab);
}
private void addTab(final int position, View tab) {
tab.setFocusable(true);
tab.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
pager.setCurrentItem(position);
}
});
tab.setPadding(tabPadding, 0, tabPadding, 0);
tabsContainer.addView(tab, position, shouldExpand ? expandedTabLayoutParams : defaultTabLayoutParams);
}
private void updateTabStyles() {
for (int i = 0; i < tabCount; i++) {
View v = tabsContainer.getChildAt(i);
// v.setBackgroundResource(tabBackgroundResId); // ### removed
if (v instanceof TextView) {
TextView tab = (TextView) v;
tab.setTextSize(TypedValue.COMPLEX_UNIT_PX, tabTextSize);
tab.setTypeface(tabTypeface, tabTypefaceStyle);
tab.setTextColor(tabTextColor);
// setAllCaps() is only available from API 14, so the upper case is made manually if we are on a
// pre-ICS-build
if (textAllCaps) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
tab.setAllCaps(true);
} else {
tab.setText(tab.getText().toString().toUpperCase(locale));
}
}
}
}
}
private void scrollToChild(int position, int offset) {
if (tabCount == 0) {
return;
}
int newScrollX = tabsContainer.getChildAt(position).getLeft() + offset;
if (position > 0 || offset > 0) {
newScrollX -= scrollOffset;
}
if (newScrollX != lastScrollX) {
lastScrollX = newScrollX;
scrollTo(newScrollX, 0);
}
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (isInEditMode() || tabCount == 0) {
return;
}
final int height = getHeight();
// draw indicator line
rectPaint.setColor(indicatorColor);
// default: line below current tab
View currentTab = tabsContainer.getChildAt(currentPosition);
float lineLeft = currentTab.getLeft();
float lineRight = currentTab.getRight();
// if there is an offset, start interpolating left and right coordinates between current and next tab
if (currentPositionOffset > 0f && currentPosition < tabCount - 1) {
View nextTab = tabsContainer.getChildAt(currentPosition + 1);
final float nextTabLeft = nextTab.getLeft();
final float nextTabRight = nextTab.getRight();
lineLeft = (currentPositionOffset * nextTabLeft + (1f - currentPositionOffset) * lineLeft);
lineRight = (currentPositionOffset * nextTabRight + (1f - currentPositionOffset) * lineRight);
}
canvas.drawRect(lineLeft, height - indicatorHeight, lineRight, height, rectPaint);
// draw underline
rectPaint.setColor(underlineColor);
canvas.drawRect(0, height - underlineHeight, tabsContainer.getWidth(), height, rectPaint);
// draw divider
dividerPaint.setColor(dividerColor);
for (int i = 0; i < tabCount - 1; i++) {
View tab = tabsContainer.getChildAt(i);
canvas.drawLine(tab.getRight(), dividerPadding, tab.getRight(), height - dividerPadding, dividerPaint);
}
}
private class PageListener implements OnPageChangeListener {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
currentPosition = position;
currentPositionOffset = positionOffset;
scrollToChild(position, (int) (positionOffset * tabsContainer.getChildAt(position).getWidth()));
invalidate();
if (delegatePageListener != null) {
delegatePageListener.onPageScrolled(position, positionOffset, positionOffsetPixels);
}
}
#Override
public void onPageScrollStateChanged(int state) {
if (state == ViewPager.SCROLL_STATE_IDLE) {
scrollToChild(pager.getCurrentItem(), 0);
}
if (delegatePageListener != null) {
delegatePageListener.onPageScrollStateChanged(state);
}
}
#Override
public void onPageSelected(int position) {
if (delegatePageListener != null) {
delegatePageListener.onPageSelected(position);
}
}
}
public void setIndicatorColor(int indicatorColor) {
this.indicatorColor = indicatorColor;
invalidate();
}
public void setIndicatorColorResource(int resId) {
this.indicatorColor = getResources().getColor(resId);
invalidate();
}
public int getIndicatorColor() {
return this.indicatorColor;
}
public void setIndicatorHeight(int indicatorLineHeightPx) {
this.indicatorHeight = indicatorLineHeightPx;
invalidate();
}
public int getIndicatorHeight() {
return indicatorHeight;
}
public void setUnderlineColor(int underlineColor) {
this.underlineColor = underlineColor;
invalidate();
}
public void setUnderlineColorResource(int resId) {
this.underlineColor = getResources().getColor(resId);
invalidate();
}
public int getUnderlineColor() {
return underlineColor;
}
public void setDividerColor(int dividerColor) {
this.dividerColor = dividerColor;
invalidate();
}
public void setDividerColorResource(int resId) {
this.dividerColor = getResources().getColor(resId);
invalidate();
}
public int getDividerColor() {
return dividerColor;
}
public void setUnderlineHeight(int underlineHeightPx) {
this.underlineHeight = underlineHeightPx;
invalidate();
}
public int getUnderlineHeight() {
return underlineHeight;
}
public void setDividerPadding(int dividerPaddingPx) {
this.dividerPadding = dividerPaddingPx;
invalidate();
}
public int getDividerPadding() {
return dividerPadding;
}
public void setScrollOffset(int scrollOffsetPx) {
this.scrollOffset = scrollOffsetPx;
invalidate();
}
public int getScrollOffset() {
return scrollOffset;
}
public void setShouldExpand(boolean shouldExpand) {
this.shouldExpand = shouldExpand;
requestLayout();
}
public boolean getShouldExpand() {
return shouldExpand;
}
public boolean isTextAllCaps() {
return textAllCaps;
}
public void setAllCaps(boolean textAllCaps) {
this.textAllCaps = textAllCaps;
}
public void setTextSize(int textSizePx) {
this.tabTextSize = textSizePx;
updateTabStyles();
}
public int getTextSize() {
return tabTextSize;
}
public void setTextColor(int textColor) {
this.tabTextColor = textColor;
updateTabStyles();
}
public void setTextColorResource(int resId) {
this.tabTextColor = getResources().getColor(resId);
updateTabStyles();
}
public int getTextColor() {
return tabTextColor;
}
public void setTypeface(Typeface typeface, int style) {
this.tabTypeface = typeface;
this.tabTypefaceStyle = style;
updateTabStyles();
}
public void setTabBackground(int resId) {
this.tabBackgroundResId = resId;
}
public int getTabBackground() {
return tabBackgroundResId;
}
public void setTabPaddingLeftRight(int paddingPx) {
this.tabPadding = paddingPx;
updateTabStyles();
}
public int getTabPaddingLeftRight() {
return tabPadding;
}
#Override
public void onRestoreInstanceState(Parcelable state) {
SavedState savedState = (SavedState) state;
super.onRestoreInstanceState(savedState.getSuperState());
currentPosition = savedState.currentPosition;
requestLayout();
}
#Override
public Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
SavedState savedState = new SavedState(superState);
savedState.currentPosition = currentPosition;
return savedState;
}
static class SavedState extends BaseSavedState {
int currentPosition;
public SavedState(Parcelable superState) {
super(superState);
}
private SavedState(Parcel in) {
super(in);
currentPosition = in.readInt();
}
#Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeInt(currentPosition);
}
public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() {
#Override
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
#Override
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
}
Im following the tutorial of In-app Billing from the following link:
Android Studio Google Play In-app Billing Tutorial.
Im implementing this logic in a Contact Adapter class which extends Base Adapter. In tutorial it is implemented in a class which extends Activity.
Error comes on onActivityResult(). I read several questions on this and I understand this method should be written in class which extends Activity but in my case the scenario is different.
Is there any way to solve this without writing onActivityResult method in MainActivity class.. and if not what should I do?
Heres ContactAdapter.java
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.TextView;
import android.widget.Toast;
import com.neirx.myco.smsproject.util.IabHelper;
import com.neirx.myco.smsproject.util.IabResult;
import com.neirx.myco.smsproject.util.Inventory;
import com.neirx.myco.smsproject.util.Purchase;
import java.util.List;
public class ContactAdapter extends BaseAdapter {
private static final java.lang.String CLASS_NAME = "<ContactAdapter> ";
Context context;
List<Contact> objects;
LayoutInflater lInflater;
MainActivity activity;
static final String ITEM_SKU = "android.test.purchased";
IabHelper mHelper;
int count = 0;
int get_limit;
private int limit_counter = 0;
private int max_limit = 2;
boolean testbool = true;
public ContactAdapter(Context context, List<Contact> contact) {
this.context = context;
objects = contact;
lInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
activity = (MainActivity) context;
}
#Override
public int getCount() {
int selectedCount = 0;
int nonSelectedCount = 0;
int size = 0;
for(Contact contact : objects){
if(contact.isChecked()) selectedCount++;
else nonSelectedCount++;
}
if(activity.isShowSelected()) size += selectedCount;
if(activity.isShowNonSelected()) size += nonSelectedCount;
return size;
}
#Override
public Object getItem(int position) {
return objects.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
public void buyClick() {
mHelper.launchPurchaseFlow(activity, ITEM_SKU, 10001, mPurchaseFinishedListener, "mypurchasetoken");
}
#Override
protected void onActivityResult(int requestCode, int resultCode,Intent data)
{
if (!mHelper.handleActivityResult(requestCode,resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data);
}
}
IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() {
public void onIabPurchaseFinished(IabResult result,Purchase purchase)
{
if (result.isFailure()) {
// Handle error
Log.d("----FAILURE 1---", "FAIL 1");
return;
}
else if (purchase.getSku().equals(ITEM_SKU)) {
consumeItem();
//buyButton.setEnabled(false);
}
}
};
public void consumeItem() {
mHelper.queryInventoryAsync(mReceivedInventoryListener);
}
IabHelper.QueryInventoryFinishedListener mReceivedInventoryListener = new IabHelper.QueryInventoryFinishedListener() {
public void onQueryInventoryFinished(IabResult result,Inventory inventory) {
if (result.isFailure()) {
// Handle failure
Log.d("----FAILURE 2---", "FAIL 2");
} else {
mHelper.consumeAsync(inventory.getPurchase(ITEM_SKU),mConsumeFinishedListener);
}
}
};
IabHelper.OnConsumeFinishedListener mConsumeFinishedListener = new IabHelper.OnConsumeFinishedListener() {
public void onConsumeFinished(Purchase purchase,IabResult result) {
if (result.isSuccess()) {
//clickButton.setEnabled(true);
Log.d("----Success ----", "Success");
} else {
// handle error
Log.d("----FAILURE 3---", "FAIL 3");
}
}
};
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
String base64EncodedPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxW650UixX2dLFECVdOpTh5OpBTqHwsznQAKd/cVcqKhrXROy4+Gj6B7M6wbkhTaloNSzTOf+nw9t1LZZ19Vlr6kcwmtxP+V/HOFwjf/NB69StOONogXtGKDyRrxtVaPM5es3yGy/aP/LXWfTLFQYJvur4AePonuRXz33iufBq5ITDQJ0+0D/o/mGtadJv0ZMsP9LV/qrMqruoqpSdaIiw5TGXdzYlJTuoP3GwS9kRyZKDeG/70KZ28W/ZclVWAdnZ7aCeDURYDV3a4pmGp5/cIvKwbex6Y7KbQYENX5ObSgNoFHLdyPTdkYaeuU9O6pet2TjGUCKr8n4M5KUMZVm8QIDAQAB";
mHelper = new IabHelper(context, base64EncodedPublicKey);
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
public void onIabSetupFinished(IabResult result)
{
if (!result.isSuccess()) {
Log.d("---MY TAG---", "In-app Billing setup failed: " +
result);
} else {
Log.d("---MY TAG---", "In-app Billing is set up OK");
}
}
});
SharedPreferences limit_pref = context.getSharedPreferences(Statical.PREF_LIMIT, Context.MODE_PRIVATE);
get_limit = limit_pref.getInt("LIMIT_KEY",0);
//Log.d("----- STORED VALUE-----", "Value is: "+get_limit);
Log.d("----- Max VALUE-----", "Value is: "+max_limit);
if (view == null) {
view = lInflater.inflate(R.layout.view_contact, parent, false);//create view file
}
if (position == 0) {
count = 0;
}
if (!activity.isShowSelected()) {
while (objects.get(position + count).isChecked()) {
count++;
}
}
if (!activity.isShowNonSelected()) {
while (!objects.get(position + count).isChecked()) {
count++;
}
}
final Contact contact = objects.get(position + count);
String contactFirstName = contact.getFirstName();
String contactSecondName = contact.getSecondName();
String contactMiddleName = contact.getMiddleName();
String[] contactNumbers = contact.getNumbers();
TextView tvName = (TextView) view.findViewById(R.id.tvName);
TextView tvNumber = (TextView) view.findViewById(R.id.tvNumber);
final CheckBox checkBox = (CheckBox) view.findViewById(R.id.checkBox);
if(get_limit == max_limit)
{
//checkBox.setChecked(contact.isChecked());
//testbool = false;
limit_counter = get_limit;
}
else if (get_limit == 1)
{
limit_counter = 1;
}
String fullName;
switch (MainActivity.sortMode) {
case Contact.COMPARE_SECOND_NAME:
fullName = getFullName(contactSecondName, contactFirstName);
break;
case Contact.COMPARE_MIDDLE_NAME:
fullName = getFullName(contactMiddleName, contactFirstName, contactSecondName);
break;
default:
fullName = getFullName(contactFirstName, contactSecondName);
break;
}
tvName.setText(fullName);
StringBuilder sbNumber = new StringBuilder();
for (int i = 0; i < contactNumbers.length; i++) {
sbNumber.append(contactNumbers[i]);
if (i < contactNumbers.length - 1) {
sbNumber.append(", ");
}
}
tvNumber.setText(sbNumber);
if (testbool) {
//Log.d("Check Boolean Tag 2 ", "testbool: "+testbool);
checkBox.setChecked(contact.isChecked());
}
checkBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
SharedPreferences selected = context.getSharedPreferences(Statical.CONTACTS_SELECTED, Context.MODE_PRIVATE);
SharedPreferences.Editor editSelected = selected.edit();
SharedPreferences limit_pref = context.getSharedPreferences(Statical.PREF_LIMIT, Context.MODE_PRIVATE);
SharedPreferences.Editor edit_limit_pref = limit_pref.edit();
int k = 0;
if(limit_counter == max_limit)
{
checkBox.setChecked(false);
//Toast.makeText(context,"Limit reached !! ", Toast.LENGTH_SHORT).show();
Log.d("-------LIMIT REACH-----", "value: "+limit_counter);
edit_limit_pref.putInt("LIMIT_KEY",limit_counter);
showAlertDialog();
}
if (contact.isChecked() && limit_counter <= max_limit && limit_counter >= 0) {
limit_counter = limit_counter - 1;
editSelected.putBoolean(contact.getContactId(), false);
edit_limit_pref.putInt("LIMIT_KEY",limit_counter);
contact.setChecked(false);
Log.d("-------UN CHECKED-----", "Un Checked value: "+limit_counter);
k = -1;
}
else if(!contact.isChecked() && limit_counter < max_limit){
limit_counter = limit_counter + 1;
editSelected.putBoolean(contact.getContactId(), true);
edit_limit_pref.putInt("LIMIT_KEY",limit_counter);
contact.setChecked(true);
Log.d("------- CHECKED -----", "Checked value: "+limit_counter);
k = 1;
}
editSelected.apply();
edit_limit_pref.apply();
activity.updateCount(k);
}
});
return view;
}
public void showAlertDialog()
{
Log.d("-------VALUE-----", "value: "+limit_counter);
AlertDialog.Builder alertDialog = new AlertDialog.Builder(context);
alertDialog.setTitle("Limit Reached!");
alertDialog.setMessage("Buy Pro Version");
alertDialog.setIcon(R.drawable.action_bar_logo);
alertDialog.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
buyClick();
Log.d("-------OK PRESSED -----", "value: " + limit_counter);
dialog.cancel();
}
});
alertDialog.setNegativeButton("Later", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Log.d("----LATER PRESSED -----", "value: " + limit_counter);
dialog.cancel();
}
});
alertDialog.show();
}
private String getFullName(String first, String second, String third) {
StringBuilder sbName = new StringBuilder();
if (!first.isEmpty()) {
sbName.append(first).append(" ");
}
if (!second.isEmpty()) {
sbName.append(second).append(" ");
}
if (!third.isEmpty()) {
sbName.append(third);
}
return sbName.toString();
}
private String getFullName(String first, String second) {
StringBuilder sbName = new StringBuilder();
if (!first.isEmpty()) {
sbName.append(first).append(" ");
}
if (!second.isEmpty()) {
sbName.append(second);
}
return sbName.toString();
}
}
I recommend you to create an activity just to process this payment and then you can back to your normal flow.