Selected item not changed in the custom ListPreference - java

It seems setChecked is invoked every time I click the preference and the selected item changes but in the dialog the selected item remains unchanged for some reason. I have no idea what's going on. Relaunching the application can make the selected item change but that's not the expected behavior. :~
Here's the class:
public class IconListPreference extends ListPreference {
private Context mContext;
private LayoutInflater mInflater;
private Drawable[] mEntryIcons = null;
private String mKey;
private int selectedEntry = -1;
public IconListPreference(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public IconListPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs);
mContext = context;
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.IconPreference, defStyle, 0);
int entryIconsResId = a.getResourceId(R.styleable.IconPreference_entryIcons, -1);
if (entryIconsResId != -1) setEntryIcons(entryIconsResId);
mInflater = LayoutInflater.from(context);
mKey = getKey();
a.recycle();
}
public void setEntryIcons(Drawable[] entryIcons) {
mEntryIcons = entryIcons;
}
public void setEntryIcons(int entryIconsResId) {
TypedArray icons_array = mContext.getResources().obtainTypedArray(entryIconsResId);
Drawable[] icon_ids_array = new Drawable[icons_array.length()];
for (int i = 0; i < icons_array.length(); i++) icon_ids_array[i] = icons_array.getDrawable(i);
setEntryIcons(icon_ids_array);
icons_array.recycle();
}
#Override
protected void onPrepareDialogBuilder(Builder builder) {
CharSequence[] entries = getEntries(), entryValues = getEntryValues();
if (entries.length != entryValues.length) throw new IllegalStateException
("ListPreference requires an entries array and an entryValues array which are both the same length");
if (mEntryIcons != null && entries.length != mEntryIcons.length) throw new IllegalStateException
("IconListPreference requires the icons entries array be the same length than entries or null");
IconListPreferenceScreenAdapter iconListPreferenceAdapter = new IconListPreferenceScreenAdapter();
if (mEntryIcons != null) {
String selectedValue = getPreferenceManager().getSharedPreferences().getString(mKey, "");
for (int i = 0; i < entryValues.length; i++) {
if (selectedValue.compareTo((String) entryValues[i]) == 0) {
selectedEntry = i;
break;
}
}
builder.setAdapter(iconListPreferenceAdapter, null);
}
super.onPrepareDialogBuilder(builder);
}
private class IconListPreferenceScreenAdapter extends BaseAdapter {
public int getCount() {
return mEntryIcons.length;
}
class CustomHolder {
private CheckedTextView text = null;
CustomHolder(View row, int position) {
text = (CheckedTextView) row.findViewById(android.R.id.text1);
text.setText(getEntries()[position]);
text.setChecked(selectedEntry == position);
if (mEntryIcons != null)
text.setCompoundDrawablesWithIntrinsicBounds(mEntryIcons[position], null, null, null);
}
}
public Object getItem(int position) {
return getEntries()[position];
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) convertView = mInflater.inflate(Resources.getSystem()
.getIdentifier("select_dialog_singlechoice_holo", "layout", "android"), parent, false);
CustomHolder holder;
final int p = position;
holder = new CustomHolder(convertView, position);
convertView.setTag(holder);
convertView.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
v.requestFocus();
getDialog().dismiss();
IconListPreference.this.callChangeListener(getEntryValues()[p]);
SharedPreferences.Editor editor = getPreferenceManager().getSharedPreferences().edit();
editor.putString(mKey, getEntryValues()[p].toString());
selectedEntry = p;
editor.apply();
}
});
return convertView;
}
}
}
And res/values/attrs.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="IconPreference">
<attr name="entryIcons" format="reference" />
</declare-styleable>
</resources>
EDIT: Updated my code with a bugfix, but still don't work sthough. A temporary solution found: invoke setValue((String) newValue) in OnPreferenceChangeListener.onPreferenceChange.

OK I finally get it. You need to do the following to make your customized preference work:
callChangeListener before setting user-supplied values;
notifyChanged if you need to update user interface, i.e. whenever value changes.

Related

Listview- clicking on the title to show the description

Im doing Dream app on Android. I have a ListView view containing a title and description that are stored in separate TextView. I want the titles to be displayed in the listView view and only after clicking one of them to display the description. After pressing another title, I want the previous description to collapse and show another, attached to the given title.
I want to my notes look this way:
Android dream
This is my adapter class where I think I need to add a few lines to solve my problem
class SennikListAdapter extends BaseAdapter implements Filterable {
private ArrayList<Sennik> mOriginalValues; // Original Values
private ArrayList<Sennik> mDisplayedValues; // Values to be displayed
LayoutInflater inflater;
public SennikListAdapter(Context context, ArrayList<Sennik> mProductArrayList) {
this.mOriginalValues = mProductArrayList;
this.mDisplayedValues = mProductArrayList;
inflater = LayoutInflater.from(context);
}
#Override
public int getCount() {
return mDisplayedValues.size();
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
private class ViewHolder {
RelativeLayout llContainer;
TextView titleOfDream, descriptionOfDream;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.customlayout, null);
holder.llContainer = (RelativeLayout) convertView.findViewById(R.id.llContainer);
holder.titleOfDream = (TextView) convertView.findViewById(R.id.titleTextView);
holder.descriptionOfDream = (TextView) convertView.findViewById(R.id.descriptionTextView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.titleOfDream.setText(mDisplayedValues.get(position).getTitleOfDream());
holder.descriptionOfDream.setText(mDisplayedValues.get(position).getDescriptionOfDream() + "");
return convertView;
}
I wanted to do something like this in getView method, but there is an error "Veriable 'holder' is accessed from within inner class, needs to be declered final". If i change to final still doesn't work
holder.titleOfDream.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (holder.descriptionOfDream.getVisibility() == View.GONE)
{
//expandedChildList.set(arg2, true);
holder.descriptionOfDream.setVisibility(View.VISIBLE);
}
else
{
//expandedChildList.set(arg2, false);
holder.descriptionOfDream.setVisibility(View.GONE);
}
}
});
Do you have any ideas how to do this? I checked so many tutorials but didn't find, and im sure it isn't difficult :(
Maybe this would be helpful
this is Fragment class
public class SennikFragment extends Fragment {
private List<String> fileName;
private List<String> fileContent;
private ArrayList<Sennik> sen = new ArrayList<Sennik>();
private SennikListAdapter adapter;
private EditText editText;
private ListView listView;
private AssetManager assets;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_sennik, container, false);
// inicjalizacja pól
fileName = new ArrayList<>();
fileContent = new ArrayList<>();
editText=(EditText) view.findViewById(R.id.searchFilter);
listView=(ListView) view.findViewById(R.id.listView);
assets = getActivity().getAssets();
//dodanie do pola wyszukiwania obiektu nasłuchującego zmian w tekście
editText.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (adapter != null) {
adapter.getFilter().filter(s.toString());
} else {
Log.d("filter", "no filter availible");
}
}
#Override
public void afterTextChanged(Editable s) {
}
});
//uzupełnienie listy tytułów i opisów snu z folderu assets
try {
//Pobranie nazw wszystkich plików
String[] paths = assets.list("");
String text="";
/* Usunięcie z nazw plików ich rozszerzenia formatu */
for (String path : paths) {
if (path.equals("images") || path.equals("sounds") || path.equals("webkit"))
continue;
fileName.add(path.replace(".txt", " "));
InputStream is= assets.open(path);
int size=is.available();
byte[]buffer=new byte[size];
is.read(buffer);
is.close();
text=new String(buffer);
fileContent.add(text);
}
} catch (IOException ex) {
Log.e(TAG, "Bład podczas ładowania plików", ex);
}
//dodanie do listy z modelu Sennik tytułów i opisów snu
for(int i=0; i<fileName.size(); i++){
sen.add(new Sennik(fileName.get(i), fileContent.get(i)));
}
adapter=new SennikListAdapter((Context)getActivity(),sen);
listView.setAdapter(adapter);
return view;
}
}
this is description class
public class Sennik {
private String titleOfDream;
private String descriptionOfDream;
public Sennik(String titleOfDream, String descriptionOfDream) {
this.titleOfDream = titleOfDream;
this.descriptionOfDream = descriptionOfDream;
}
public String getTitleOfDream() {
return titleOfDream;
}
public void setTitleOfDream(String titleOfDream) {
this.titleOfDream = titleOfDream;
}
public String getDescriptionOfDream() {
return descriptionOfDream;
}
public void setDescriptionOfDream(String descriptionOfDream) {
this.descriptionOfDream = descriptionOfDream;
}
}
and my layouts:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent"
android:id="#+id/llContainer">
<TextView
android:id="#+id/titleTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:textSize="20dp"
android:textColor="#color/colorAccent"
android:text="TextView" />
<TextView
android:id="#+id/descriptionTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/titleTextView"
android:layout_centerHorizontal="true"
android:textColorHighlight="#color/colorPrimary"
android:textStyle="italic"
android:gravity="center"
android:textColor="#color/colorPrimary"
android:text="TextView" />
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:layout_width="match_parent"
android:layout_height="50dp"
android:id="#+id/searchFilter"></EditText>
<ListView
android:id="#+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/searchFilter">
</ListView>
EDIT
problem solved!
I just add a line to my Adapter class to hide the description
holder.descriptionOfDream.setVisibility(View.GONE);
so the whole Adapter class look like:
class SennikListAdapter extends BaseAdapter implements Filterable {
private ArrayList<Sennik> mOriginalValues; // Original Values
private ArrayList<Sennik> mDisplayedValues; // Values to be displayed
LayoutInflater inflater;
public SennikListAdapter(Context context, ArrayList<Sennik> mProductArrayList) {
this.mOriginalValues = mProductArrayList;
this.mDisplayedValues = mProductArrayList;
inflater = LayoutInflater.from(context);
}
#Override
public int getCount() {
return mDisplayedValues.size();
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
private class ViewHolder {
RelativeLayout llContainer;
TextView titleOfDream, descriptionOfDream;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.customlayout, null);
holder.llContainer = (RelativeLayout) convertView.findViewById(R.id.llContainer);
holder.titleOfDream = (TextView) convertView.findViewById(R.id.titleTextView);
holder.descriptionOfDream = (TextView) convertView.findViewById(R.id.descriptionTextView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.titleOfDream.setText(mDisplayedValues.get(position).getTitleOfDream());
holder.descriptionOfDream.setText(mDisplayedValues.get(position).getDescriptionOfDream() + "");
holder.descriptionOfDream.setVisibility(View.GONE);
return convertView;
}
And in Fragment class i use setOnItemClickListener method on listView (setOnClickListener doesn't work)
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
TextView descriptionOfDream= (TextView) view.findViewById(R.id.descriptionTextView);
if(descriptionOfDream.getVisibility()==view.GONE){
descriptionOfDream.setVisibility(view.VISIBLE);
}
else
{
descriptionOfDream.setVisibility(view.GONE);
}
}
});
So the whole Fragment class look like:
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_sennik, container, false);
// inicjalizacja pól
fileName = new ArrayList<>();
fileContent = new ArrayList<>();
editText=(EditText) view.findViewById(R.id.searchFilter);
listView=(ListView) view.findViewById(R.id.listView);
assets = getActivity().getAssets();
//dodanie do pola wyszukiwania obiektu nasłuchującego zmian w tekście
editText.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (adapter != null) {
adapter.getFilter().filter(s.toString());
} else {
Log.d("filter", "no filter availible");
}
}
#Override
public void afterTextChanged(Editable s) {
}
});
//uzupełnienie listy tytułów i opisów snu z folderu assets
try {
//Pobranie nazw wszystkich plików
String[] paths = assets.list("");
String text="";
/* Usunięcie z nazw plików ich rozszerzenia formatu */
for (String path : paths) {
if (path.equals("images") || path.equals("sounds") || path.equals("webkit"))
continue;
fileName.add(path.replace(".txt", " "));
InputStream is= assets.open(path);
int size=is.available();
byte[]buffer=new byte[size];
is.read(buffer);
is.close();
text=new String(buffer);
fileContent.add(text);
}
} catch (IOException ex) {
Log.e(TAG, "Bład podczas ładowania plików", ex);
}
//dodanie do listy z modelu Sennik tytułów i opisów snu
for(int i=0; i<fileName.size(); i++){
sen.add(new Sennik(fileName.get(i), fileContent.get(i)));
}
adapter=new SennikListAdapter((Context)getActivity(),sen);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
TextView descriptionOfDream= (TextView) view.findViewById(R.id.descriptionTextView);
if(descriptionOfDream.getVisibility()==view.GONE){
descriptionOfDream.setVisibility(view.VISIBLE);
}
else
{
descriptionOfDream.setVisibility(view.GONE);
}
}
});
return view;
}
}
Works excelent <3
First you need to create a class Extending LinearLayout and give some Expanding/collapsing
capabilities to It. Then define your description Textview as a child of that.
public class ExpandableLinearLayout extends LinearLayout {
private boolean expanded;
private int duration;
public ExpandableLinearLayout(Context context) {
super(context);
}
public ExpandableLinearLayout(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
init(attrs);
}
public ExpandableLinearLayout(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs);
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public ExpandableLinearLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(attrs);
}
private void init(AttributeSet attributeSet) {
TypedArray customValues = getContext().obtainStyledAttributes(attributeSet, R.styleable.ExpandableLinearLayout);
duration = customValues.getInt(R.styleable.ExpandableLinearLayout_expandDuration, -1);
customValues.recycle();
}
public boolean isExpanded() {
return expanded;
}
public void setExpanded(boolean expanded) {
this.expanded = expanded;
}
public void toggle() {
if (expanded)
expandView(this);
else
hideView(this);
}
private void expandView(final View view) {
view.measure(WindowManager.LayoutParams.MATCH_PARENT
, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
final int targetHeight = view.getMeasuredHeight();
// Older versions of android (pre API 21) cancel animations for views with a height of 0.
view.getLayoutParams().height = 1;
view.setVisibility(View.VISIBLE);
Animation a = new Animation() {
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
view.getLayoutParams().height = interpolatedTime == 1
? targetHeight : (int) (targetHeight * interpolatedTime);
view.requestLayout();
}
#Override
public boolean willChangeBounds() {
return true;
}
};
if (duration == -1)
a.setDuration((int) (targetHeight / view.getContext().getResources().getDisplayMetrics().density * 1.5));
else
a.setDuration(duration);
view.startAnimation(a);
}
private void hideView(final View view) {
final int initialHeight = view.getMeasuredHeight();
Animation a = new Animation() {
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
if (interpolatedTime == 1) {
view.setVisibility(View.GONE);
} else {
view.getLayoutParams().height = initialHeight - (int) (initialHeight * interpolatedTime);
view.requestLayout();
}
}
#Override
public boolean willChangeBounds() {
return true;
}
};
if (duration == -1)
a.setDuration((int) (initialHeight / view.getContext().getResources().getDisplayMetrics().density * 1.5));
else
a.setDuration(duration);
view.startAnimation(a);
}
}
Just Inflate this class into your xml layout file and create descriotion textView inside of it.
Add The following Code snippet into your Adapter class to call that when An Item gets a Click. It will Expand/Collapse the LinearLayout with an Animaiton.
private void initializeClicks() {
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (expandableLinearLayout.isExpanded()) {
expandableLinearLayout.setExpanded(false);
expandableLinearLayout.toggle();
orderList.get(getAdapterPosition()).setExpanded(false);
} else {
expandableLinearLayout.setExpanded(true);
orderList.get(getAdapterPosition()).setExpanded(true);
expandableLinearLayout.toggle();
if(lastExpandedCardPosition!=getAdapterPosition() && recyclerView.findViewHolderForAdapterPosition(lastExpandedCardPosition)!=null){
((ExpandableLinearLayout)recyclerView.findViewHolderForAdapterPosition(lastExpandedCardPosition).itemView.findViewById(R.id.expandedLinearLayout)).setExpanded(false);
orderList.get(lastExpandedCardPosition).setExpanded(false);
((ExpandableLinearLayout)recyclerView.findViewHolderForAdapterPosition(lastExpandedCardPosition).itemView.findViewById(R.id.expandedLinearLayout)).toggle();
}
else if(lastExpandedCardPosition!=getAdapterPosition() && recyclerView.findViewHolderForAdapterPosition(lastExpandedCardPosition)==null){
orderList.get(lastExpandedCardPosition).setExpanded(false);
}
lastExpandedCardPosition = getAdapterPosition();
}
}
});
}
Finally call the Method above in your Clicklistenr like this:
holder.titleOfDream.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (holder.descriptionOfDream.getVisibility() == View.GONE)
{
expandableLinearLayout.setVisibility(View.VISIBLE);
expandableLinearLayout.setExpanded(true);
}
else
{
expandableLinearLayout.setVisibility(View.GONE);
expandableLinearLayout.setExpanded(false);
}
}
});
For a more detailed Explanation about this Method see this post on Medium.com.
And dont forget to give a clap to this post.
You have to call this method in your code`
holder.descriptionOfDream.requestLayout();
So basically, your new code looks like this
holder.titleOfDream.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (holder.descriptionOfDream.getVisibility() == View.GONE)
{
//expandedChildList.set(arg2, true);
holder.descriptionOfDream.setVisibility(View.VISIBLE);
holder.descriptionOfDream.requestLayout();
}
else
{
//expandedChildList.set(arg2, false);
holder.descriptionOfDream.setVisibility(View.GONE);
holder.descriptionOfDream.requestLayout();
}
}
});
Hope that helps.
Keep in mind that the holder variable must be final like below
final ViewHolder holder = null;
if (convertView == null) {
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.customlayout, null);
holder.llContainer = (RelativeLayout) convertView.findViewById(R.id.llContainer);
holder.titleOfDream = (TextView) convertView.findViewById(R.id.titleTextView);
holder.descriptionOfDream = (TextView) convertView.findViewById(R.id.descriptionTextView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.titleOfDream.setText(mDisplayedValues.get(position).getTitleOfDream());
holder.descriptionOfDream.setText(mDisplayedValues.get(position).getDescriptionOfDream() + "");
return convertView;

Android RecyclerView fails to render a SurfaceView (SOLVED)

can a SurfaceView be rendered inside a RecyclerView
what i am trying to do is make a Grid of SurfaceView's
#Keep
public class NativeView {
String TAG = "EglSample";
public static native void nativeOnStart();
public static native void nativeOnResume();
public static native void nativeOnPause();
public static native void nativeOnStop();
// this is part of graphics manager
public native void nativeSetSurface(Surface surface);
View surfaceView = null;
SurfaceHolderCallback surfaceHolderCallback = null;
public NativeView(Context context) {
System.loadLibrary("nativeegl");
surfaceHolderCallback = new SurfaceHolderCallback();
surfaceView = new View(surfaceHolderCallback, context);
}
class View extends SurfaceView {
public View(SurfaceHolder.Callback callback, Context context) {
super(context);
getHolder().addCallback(callback);
}
public View(SurfaceHolder.Callback callback, Context context, AttributeSet attrs) {
super(context, attrs);
getHolder().addCallback(callback);
}
public View(SurfaceHolder.Callback callback, Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
getHolder().addCallback(callback);
}
public View(SurfaceHolder.Callback callback, Context context, AttributeSet attrs, int defStyle, int defStyleRes) {
super(context, attrs, defStyle, defStyleRes);
getHolder().addCallback(callback);
}
}
class SurfaceHolderCallback implements SurfaceHolder.Callback {
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
nativeSetSurface(holder.getSurface());
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
nativeSetSurface(null);
}
}
}
public ViewGroup onViewRequest(Context mContext) {
if (context == null) context = mContext;
if (n == null) n = new NativeView(context);
Log.i(n.TAG, "onViewRequest(Activity, Context)");
// build layout
RelativeLayout rel = new RelativeLayout(context);
rel.addView(n.surfaceView);
n.surfaceView.setOnClickListener(new MyListener());
// set text
TextView text = new TextView(context);
text.setText("Hello World! Try clicking the screen");
text.setTextSize(60f);
text.setTextColor(Color.WHITE);
rel.addView(text);
Log.i(n.TAG, "onCreate()");
// build layout
NativeView.nativeOnStart();
NativeView.nativeOnResume();
return rel;
}
full:
https://github.com/mgood7123/VSTDEMO/blob/0f5e7063d9ebef5ae5a05f128d548eec712b741f/vstdemoopengladdonscube/src/main/java/vst/demo/opengl/addons/cube/main.java
https://github.com/mgood7123/VSTDEMO/blob/0f5e7063d9ebef5ae5a05f128d548eec712b741f/vstdemoopengladdonscube/src/main/java/vst/demo/opengl/addons/cube/NativeView.java
as it renders corrupted in a recycler view (text but no surface view) (you can barely make out the white text but the fact that it is there means the view heirarchy IS being drawn)
(set USE_RECYCLER_VIEW = true)
https://github.com/mgood7123/VSTDEMO/blob/0f5e7063d9ebef5ae5a05f128d548eec712b741f/VstManager/src/main/java/vst/manager/VstGrid.java#L29
Boolean USE_RECYCLER_VIEW = false;
public LinearLayout getView() {
// this assumes the first available "*\.addons\.*" package
if (!USE_RECYCLER_VIEW) {
VST pkg = mVstMan.loadPackage(mActivity, mVstMan.getPackages(mActivity)[0].packageName, false);
VST.CLASS vstClass = mVstMan.loadClass(pkg, "main");
Object vstClassInstance = mVstMan.newInstance(vstClass, "main");
// android.widget.RelativeLayout cannot be cast to android.widget.LinearLayout
LinearLayout x = new LinearLayout(mActivity);
x.addView((ViewGroup) mVstMan.invokeMethod(
vstClass, vstClassInstance,
"onViewRequest", Context.class,
pkg.activityApplicationContext
)
);
return x;
} else {
if (recyclerViewMain == null)
recyclerViewMain = (LinearLayout) LayoutInflater.from(mActivity.getApplicationContext())
.inflate(R.layout.vst_grid, null, false);
if (recyclerView == null) {
recyclerView = recyclerViewMain
.findViewById(R.id.VstGrid);
// use this setting to improve performance if you know that changes
// in content do not change the layout size of the RecyclerView
recyclerView.setHasFixedSize(true);
}
if (layoutManager == null) {
// use a linear layout manager
layoutManager = new GridLayoutManager(mActivity, 1);
recyclerView.setLayoutManager(layoutManager);
}
if (mAdapter == null) {
// specify an adapter (see also next example)
mAdapter = new VstGridAdapter(mActivity, mVstMan, mVstUI);
recyclerView.setAdapter(mAdapter);
}
mAdapter.update();
return recyclerViewMain;
}
}
https://github.com/mgood7123/VSTDEMO/blob/0f5e7063d9ebef5ae5a05f128d548eec712b741f/VstManager/src/main/java/vst/manager/VstGridAdapter.java#L86
// Create new views (invoked by the layout manager)
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
VST pkg = mVstMan.loadPackage(mActivity, mVstMan.getPackages(mActivity)[0].packageName, false);
VST.CLASS vstClass = mVstMan.loadClass(pkg, "main");
Object vstClassInstance = mVstMan.newInstance(vstClass, "main");
// android.widget.RelativeLayout cannot be cast to android.widget.LinearLayout
LinearLayout x = new LinearLayout(mActivity);
x.addView((ViewGroup) mVstMan.invokeMethod(
vstClass, vstClassInstance,
"onViewRequest", Context.class,
pkg.activityApplicationContext
)
);
return new MyViewHolder(x);
}
https://github.com/mgood7123/VSTDEMO/blob/0f5e7063d9ebef5ae5a05f128d548eec712b741f/vstdemoopengladdonscube/src/main/cpp/RotatingSquares/jniapi.cpp
https://github.com/mgood7123/VSTDEMO/blob/0f5e7063d9ebef5ae5a05f128d548eec712b741f/vstdemoopengladdonscube/src/main/cpp/RotatingSquares/renderer.cpp#L153
meanwhile it renders perfectly fine if NOT in a recycler view (leave USE_RECYCLER_VIEW as false)
why?
apparently in order to get it to display i needed to give the view fixed size layout paramaters: mView.setLayoutParams(new ViewGroup.LayoutParams(500, 500));

ViewPager for images on SD card not working

I am a newbie in android app development and I am following this tutorial to create an image gallery.
https://deepshikhapuri.wordpress.com/2017/03/20/get-all-images-from-gallery-in-android-programmatically/.
It's working perfectly but now I want to display images in ViewPager for being able to display images by swiping left/right.I am using an adapter for doing it.
I have tried doing it but its not working I dont know why.I am not able to swipe images. Can anyone help me with it ? Am i using correct path for the images?
This project is available on github here :
https://github.com/avi003/MyApp0-master-master
ImageGallery.java:
public class ImageGallery extends AppCompatActivity {
public static ArrayList<Model_images> al_images = new ArrayList<>();
boolean boolean_folder;
Adapter_PhotosFolder obj_adapter;
GridView gv_folder;
private static final int REQUEST_PERMISSIONS = 100;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_image_gallery);
gv_folder = (GridView)findViewById(R.id.gv_folder);
gv_folder.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Intent intent = new Intent(getApplicationContext(), PhotosActivity.class);
intent.putExtra("value",i);
startActivity(intent);
}
});
if ((ContextCompat.checkSelfPermission(getApplicationContext(),
Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) && (ContextCompat.checkSelfPermission(getApplicationContext(),
Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)) {
if ((ActivityCompat.shouldShowRequestPermissionRationale(ImageGallery.this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)) && (ActivityCompat.shouldShowRequestPermissionRationale( ImageGallery.this,
Manifest.permission.READ_EXTERNAL_STORAGE))) {
} else {
ActivityCompat.requestPermissions( ImageGallery.this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE},
REQUEST_PERMISSIONS);
}
}else {
Log.e("Else","Else");
fn_imagespath();
}
}
public ArrayList<Model_images> fn_imagespath() {
al_images.clear();
int int_position = 0;
Uri uri;
Cursor cursor;
int column_index_data, column_index_folder_name;
String absolutePathOfImage;
uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
String[] projection = {MediaStore.MediaColumns.DATA, MediaStore.Images.Media.BUCKET_DISPLAY_NAME};
final String orderBy = MediaStore.Images.Media.DATE_TAKEN;
cursor = getApplicationContext().getContentResolver().query(uri, projection, null, null, orderBy + " DESC");
column_index_data = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
column_index_folder_name = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.BUCKET_DISPLAY_NAME);
while (cursor.moveToNext()) {
absolutePathOfImage = cursor.getString(column_index_data);
Log.e("Column", absolutePathOfImage);
Log.e("Folder", cursor.getString(column_index_folder_name));
for (int i = 0; i < al_images.size(); i++) {
if (al_images.get(i).getStr_folder().equals(cursor.getString(column_index_folder_name))) {
boolean_folder = true;
int_position = i;
break;
} else {
boolean_folder = false;
}
}
if (boolean_folder) {
ArrayList<String> al_path = new ArrayList<>();
al_path.addAll(al_images.get(int_position).getAl_imagepath());
al_path.add(absolutePathOfImage);
al_images.get(int_position).setAl_imagepath(al_path);
} else {
ArrayList<String> al_path = new ArrayList<>();
al_path.add(absolutePathOfImage);
Model_images obj_model = new Model_images();
obj_model.setStr_folder(cursor.getString(column_index_folder_name));
obj_model.setAl_imagepath(al_path);
al_images.add(obj_model);
}
}
for (int i = 0; i < al_images.size(); i++) {
Log.e("FOLDER", al_images.get(i).getStr_folder());
for (int j = 0; j < al_images.get(i).getAl_imagepath().size(); j++) {
Log.e("FILE", al_images.get(i).getAl_imagepath().get(j));
}
}
obj_adapter = new Adapter_PhotosFolder(getApplicationContext(),al_images);
gv_folder.setAdapter(obj_adapter);
return al_images;
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case REQUEST_PERMISSIONS: {
for (int i = 0; i < grantResults.length; i++) {
if (grantResults.length > 0 && grantResults[i] == PackageManager.PERMISSION_GRANTED) {
fn_imagespath();
} else {
Toast.makeText(ImageGallery.this, "The app was not allowed to read or write to your storage. Hence, it cannot function properly. Please consider granting it this permission", Toast.LENGTH_LONG).show();
}
}
}
}
}
}
PhotosActivity.java:
public class PhotosActivity extends AppCompatActivity {
int int_position;
private GridView gridView;
GridViewAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_image_gallery);
gridView = (GridView)findViewById(R.id.gv_folder);
int_position = getIntent().getIntExtra("value", 0);
adapter = new GridViewAdapter(this, al_images,int_position);
gridView.setAdapter(adapter);
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String abc = "file://" + al_images.get(int_position).getAl_imagepath().get(position);
Intent i = new Intent(getApplicationContext(), FullImageActivity.class);
i.putExtra("id", position);
i.putExtra("abc",abc);
startActivity(i);
}
});
}
}
GridViewAdapter.java:
public class GridViewAdapter extends ArrayAdapter<Model_images> {
Context context;
ViewHolder viewHolder;
ArrayList<Model_images> al_menu = new ArrayList<>();
int int_position;
public GridViewAdapter(Context context, ArrayList<Model_images> al_menu,int int_position) {
super(context, R.layout.activity_adapter__photos_folder, al_menu);
this.al_menu = al_menu;
this.context = context;
this.int_position = int_position;
}
#Override
public int getCount() {
Log.e("ADAPTER LIST SIZE", al_menu.get(int_position).getAl_imagepath().size() + "");
return al_menu.get(int_position).getAl_imagepath().size();
}
#Override
public int getItemViewType(int position) {
return position;
}
#Override
public int getViewTypeCount() {
if (al_menu.get(int_position).getAl_imagepath().size() > 0) {
return al_menu.get(int_position).getAl_imagepath().size();
} else {
return 1;
}
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
if (convertView == null) {
viewHolder = new ViewHolder();
convertView = LayoutInflater.from(getContext()).inflate(R.layout.activity_adapter__photos_folder, parent, false);
viewHolder.tv_foldern = (TextView) convertView.findViewById(R.id.tv_folder);
viewHolder.tv_foldersize = (TextView) convertView.findViewById(R.id.tv_folder2);
viewHolder.iv_image = (ImageView) convertView.findViewById(R.id.iv_image);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.tv_foldern.setVisibility(View.GONE);
viewHolder.tv_foldersize.setVisibility(View.GONE);
Glide.with(context).load("file://" + al_menu.get(int_position).getAl_imagepath().get(position))
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.into(viewHolder.iv_image);
return convertView;
}
private static class ViewHolder {
TextView tv_foldern, tv_foldersize;
ImageView iv_image;
}
}
Adapter_PhotosFolder.java:
public class Adapter_PhotosFolder extends ArrayAdapter<Model_images> {
Context context;
ViewHolder viewHolder;
ArrayList<Model_images> al_menu = new ArrayList<>();
public Adapter_PhotosFolder(Context context, ArrayList<Model_images> al_menu) {
super(context, R.layout.activity_adapter__photos_folder, al_menu);
this.al_menu = al_menu;
this.context = context;
}
#Override
public int getCount() {
Log.e("ADAPTER LIST SIZE", al_menu.size() + "");
return al_menu.size();
}
#Override
public int getItemViewType(int position) {
return position;
}
#Override
public int getViewTypeCount() {
if (al_menu.size() > 0) {
return al_menu.size();
} else {
return 1;
}
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
if (convertView == null) {
viewHolder = new ViewHolder();
convertView = LayoutInflater.from(getContext()).inflate(R.layout.activity_adapter__photos_folder, parent, false);
viewHolder.tv_foldern = (TextView) convertView.findViewById(R.id.tv_folder);
viewHolder.tv_foldersize = (TextView) convertView.findViewById(R.id.tv_folder2);
viewHolder.iv_image = (ImageView) convertView.findViewById(R.id.iv_image);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.tv_foldern.setText(al_menu.get(position).getStr_folder());
viewHolder.tv_foldersize.setText(al_menu.get(position).getAl_imagepath().size()+"");
Glide.with(context).load("file://" + al_menu.get(position).getAl_imagepath().get(0))
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.into(viewHolder.iv_image);
return convertView;
}
private static class ViewHolder {
TextView tv_foldern, tv_foldersize;
ImageView iv_image;
}
}
Model_images.java:
public class Model_images {
String str_folder;
ArrayList<String> al_imagepath;
public String getStr_folder() {
return str_folder;
}
public void setStr_folder(String str_folder) {
this.str_folder = str_folder;
}
public ArrayList<String> getAl_imagepath() {
return al_imagepath;
}
public void setAl_imagepath(ArrayList<String> al_imagepath) {
this.al_imagepath = al_imagepath;
}
}
FullImageActivity.java:
public class FullImageActivity extends AppCompatActivity {
ImageView images;
int position;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_full_image);
Intent i = getIntent();
images = (ImageView) findViewById(R.id.fullImage);
// Selected image id
position = i.getExtras().getInt("id");
Bundle extras = getIntent().getExtras();
String value = extras.getString("abc");
Glide.with(FullImageActivity.this)
.load(value)
.skipMemoryCache(false)
.into(images);
ViewPager mViewPager = (ViewPager) findViewById(R.id.viewpager);
mViewPager.setAdapter(new TouchImageAdapter(this,al_images));
}
}
activity_full_image.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/jazzy_pager"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/fullImage"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:scaleType="centerCrop"
/>
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
TouchImageAdapter.java:
class TouchImageAdapter extends PagerAdapter {
Context context;
String filename;
ArrayList<Model_images> al_menu = new ArrayList<>();
int position,int_position;
public TouchImageAdapter(Context context,ArrayList<Model_images> al_menu){
this.al_menu = al_menu;
this.context = context;
}
#Override
public int getCount() {
return al_menu.size();
}
#Override
public View instantiateItem(ViewGroup container, int position) {
ImageView img = new ImageView(container.getContext());
img.setImageDrawable(getImageFromSdCard(filename,position));
container.addView(img, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
return img;
}
public int getItemPosition(Object object) {
return POSITION_NONE;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
public Drawable getImageFromSdCard(String imageName,int position) {
Drawable d = null;
try {
String path = al_menu.get(int_position).getAl_imagepath().get(position)
+ "/";
Bitmap bitmap = BitmapFactory.decodeFile(path + "/" + imageName
+ ".jpeg");
d = new BitmapDrawable(context.getResources(),bitmap);
} catch (IllegalArgumentException e) {
// TODO: handle exception
}
return d;
}
}
Here you are not passing count of images inside that folder, So in TouchImageAdapter you have passing the count of folder like :
al_menu.size() // it always give you size of folder,
al_menu.get(int_position).getAl_imagepath().size();
// passing the folder position so that correct folder images are to be shown.
public TouchImageAdapter(Context context,ArrayList<Model_images> al_menu, int position){
this.al_menu = al_menu;
this.context = context;
this.int_position = position;
}
#Override
public int getCount() {
return al_menu.get(int_position).getAl_imagepath().size();
}
Here is the updated code I pushed on
https://github.com/redviper00/game
try this
String[] filenames = new String[0];
File path = new File(Environment.getExternalStorageDirectory() + "/your folder");
if (path.exists()) {
filenames = path.list();
}
for (int i = 0; i < filenames.length; i++) {
imagesPathArrayList.add(path.getPath() + "/" + filenames[i]);
Log.e("FAV_Images", imagesPathArrayList.get(i));
adapter = new ImageAdapter(FavActivity.this, imagesPathArrayList);
myviewpager.setAdapter(adapter);
}
create adapter class like this
public class ImageAdapter extends PagerAdapter {
Context context;
ArrayList<String> arrayList;
ImageAdapter(Context context, ArrayList<String> arrayList) {
this.context = context;
this.arrayList = arrayList;
}
#Override
public int getCount() {
return arrayList.size();
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == ((ImageView) object);
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
viewPagerImageView = new ImageView(context);
viewPagerImageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
Bitmap bitmap = BitmapFactory.decodeFile(arrayList.get(position));
viewPagerImageView.setImageBitmap(bitmap);
((ViewPager) container).addView(viewPagerImageView, 0);
return viewPagerImageView;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
((ViewPager) container).removeView((ImageView) object);
}
}
It seems like you are showing Imageview above view pager
images = (ImageView) findViewById(R.id.fullImage);
that is why when you are trying to swipe imageview handle your tocuh action instead of view pager. Remove it.

Android Custom ListPreference only allow 5 items

Im creating a custom ListPreference on the back of this example.
I've implemented it and it works. But I can only add a max of 5 item to the ListPreference. If I add 7 items they appears in the list but when I click it it does nothing, just closes the ListPref dialog and return to the pref screen
public class IconPickerPreference extends ListPreference {
private class CustomListPreferenceAdapter extends ArrayAdapter<IconItem> {
private Context context;
private List<IconItem> icons;
private int resource;
public CustomListPreferenceAdapter(Context context, int resource, List<IconItem> objects) {
super(context, resource, objects);
this.context = context;
this.resource = resource;
this.icons = objects;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(resource, parent, false);
holder = new ViewHolder();
holder.iconName = (TextView) convertView
.findViewById(R.id.iconName);
holder.iconImage = (ImageView) convertView
.findViewById(R.id.iconImage);
holder.radioButton = (RadioButton) convertView
.findViewById(R.id.iconRadio);
holder.position = position;
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.iconName.setText(icons.get(position).name);
int identifier = context.getResources().getIdentifier(
icons.get(position).file, "drawable",
context.getPackageName());
holder.iconImage.setImageResource(identifier);
holder.radioButton.setChecked(icons.get(position).isChecked);
convertView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
ViewHolder holder = (ViewHolder) v.getTag();
for (int i = 0; i < icons.size(); i++) {
if (i == holder.position)
icons.get(i).isChecked = true;
else
icons.get(i).isChecked = false;
}
getDialog().dismiss();
}
});
return convertView;
}
}
private static class IconItem {
private String file;
private boolean isChecked;
private String name;
public IconItem(CharSequence name, CharSequence file, boolean isChecked) {
this(name.toString(), file.toString(), isChecked);
}
public IconItem(String name, String file, boolean isChecked) {
this.name = name;
this.file = file;
this.isChecked = isChecked;
}
}
private static class ViewHolder {
protected ImageView iconImage;
protected TextView iconName;
protected int position;
protected RadioButton radioButton;
}
private Context context;
private ImageView icon;
private CharSequence[] iconFile;
private CharSequence[] iconName;
private List<IconItem> icons;
private SharedPreferences preferences;
private Resources resources;
private String selectedIconFile, defaultIconFile;
private TextView summary;
public IconPickerPreference(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
resources = context.getResources();
preferences = PreferenceManager.getDefaultSharedPreferences(context);
TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
R.styleable.attrs_icon, 0, 0);
try {
defaultIconFile = a.getString(R.styleable.attrs_icon_iconFile);
} finally {
a.recycle();
}
}
private String getEntry(String value) {
String[] entries = resources.getStringArray(R.array.iconName);
String[] values = resources.getStringArray(R.array.iconFile);
int index = Arrays.asList(values).indexOf(value);
return entries[index];
}
#Override
protected void onBindView(View view) {
super.onBindView(view);
selectedIconFile = preferences.getString(
resources.getString(R.string.custom_icon_key), defaultIconFile);
icon = (ImageView) view.findViewById(R.id.iconSelected);
updateIcon();
summary = (TextView) view.findViewById(R.id.summary);
summary.setText(getEntry(selectedIconFile));
}
#Override
protected void onDialogClosed(boolean positiveResult) {
super.onDialogClosed(positiveResult);
if (icons != null) {
for (int i = 0; i < icons.size(); i++) {
IconItem item = icons.get(i);
if (item.isChecked) {
Editor editor = preferences.edit();
editor.putString(
resources.getString(R.string.custom_icon_key),
item.file);
editor.apply();
selectedIconFile = item.file;
updateIcon();
summary.setText(item.name);
break;
}
}
}
}
#Override
protected void onPrepareDialogBuilder(Builder builder) {
builder.setNegativeButton("Cancel", null);
builder.setPositiveButton(null, null);
iconName = getEntries();
iconFile = getEntryValues();
if (iconName == null || iconFile == null
|| iconName.length != iconFile.length) {
throw new IllegalStateException(
"ListPreference requires an entries array "
+ "and an entryValues array which are both the same length");
}
String selectedIcon = preferences.getString(
resources.getString(R.string.custom_icon_key),
resources.getString(R.string.icon_default));
icons = new ArrayList<IconItem>();
for (int i = 0; i < iconName.length; i++) {
boolean isSelected = selectedIcon.equals(iconFile[i]) ? true
: false;
IconItem item = new IconItem(iconName[i], iconFile[i], isSelected);
icons.add(item);
}
CustomListPreferenceAdapter customListPreferenceAdapter = new CustomListPreferenceAdapter(
context, R.layout.item_picker, icons);
builder.setAdapter(customListPreferenceAdapter, null);
}
private void updateIcon() {
int identifier = resources.getIdentifier(selectedIconFile, "drawable",
context.getPackageName());
icon.setImageResource(identifier);
icon.setTag(selectedIconFile);
}
String values
<string-array name="iconName">
<item>CHESTNUT</item>
<item>POMEGRANATE</item>
<item>OLD BRICK</item>
<item>FLAMINGO</item>
<item>SNUFF</item>
<item>RAZZMATAZZ</item>
<item>NEW YORK PINK</item>
</string-array>
<string-array name="iconFile">
<item>ic_chestnut</item>
<item>ic_pomegranate</item>
<item>ic_old_brick</item>
<item>ic_flamingo</item>
<item>ic_snuff</item>
<item>ic_razzmatazz</item>
<item>ic_new_york_pink</item>
</string-array>
7 ic_ pngs for the items above in drawable...
Logs not showing any index error...
Stumped :P
Any help appreciated
Thanks in advance
I think that the problem could be caused because you are saving the position in your ViewHolder, why do you do that?
Mark final the position field, and use it directly in your OnClickListener.
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
...
#Override
public void onClick(View v) {
ViewHolder holder = (ViewHolder) v.getTag();
for (int i = 0; i < icons.size(); i++) {
if (i == position)
icons.get(i).isChecked = true;
else
icons.get(i).isChecked = false;
}
getDialog().dismiss();
}

Removing from ArrayList<Form> throws an UnsupportedOperationException

I'm developing an Android 3.1 application.
I have created my custom ArrayAdapter with an ArrayList. Form is a custom class with two fields: name and FormId.
Here is my ArrayAdapter code:
public class FormAdapter extends ArrayAdapter<Form>
{
private Context context;
private int layoutResourceId;
private List<Form> forms;
private ArrayList<Integer> checkedItemsPosition;
private Button downloadButton;
public ArrayList<Integer> getCheckedItemsPosition()
{
return checkedItemsPosition;
}
public String[] getSelectedFormsId()
{
String[] ids = new String[checkedItemsPosition.size()];
int i = 0;
for(Integer pos : checkedItemsPosition)
{
Form f = forms.get(pos.intValue());
ids[i] = f.FormId;
i++;
}
return ids;
}
/**
* Called when selected forms has been downloaded and save it locally correctly.
*/
public void updateFormsNotDownloaded()
{
for (Integer pos : checkedItemsPosition)
{
remove(forms.get(pos.intValue()));
}
checkedItemsPosition.clear();
notifyDataSetChanged();
}
public FormAdapter(Context context, int textViewResourceId,
List<Form> objects, Button downloadButton)
{
super(context, textViewResourceId, objects);
this.context = context;
this.layoutResourceId = textViewResourceId;
this.forms = objects;
this.checkedItemsPosition = new ArrayList<Integer>();
this.downloadButton = downloadButton;
}
#Override
public int getCount()
{
return forms.size();
}
#Override
public View getView(final int position, View convertView, ViewGroup parent)
{
Log.v("FormAdapter", "getView.postion: " + position);
View row = convertView;
if (row == null)
{
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
}
Form f = forms.get(position);
if (f != null)
{
CheckBox checkBox = (CheckBox)row.findViewById(R.id.itemCheckBox);
if (checkBox != null)
{
checkBox.setText(f.Name);
checkBox.setOnCheckedChangeListener(new OnCheckedChangeListener()
{
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked)
{
//Form f = forms.get(position);
if (isChecked)
{
//checkedItems.add(f.FormId);
checkedItemsPosition.add(new Integer(position));
}
else
{
//checkedItems.remove(checkedItems.indexOf(f.FormId));
checkedItemsPosition.remove(checkedItemsPosition.indexOf(new Integer(position)));
}
downloadButton.setEnabled(checkedItemsPosition.size() > 0);
}
});
}
}
return row;
}
}
List items are custom items with a checkbox. On checkedItemsPosition I store checked items position.
My problem is on updateFormsNotDownloaded method. Why am I getting an UnsupportedOperationException?
I can only think of one reason. The List<> implementation you pass into the ArrayAdapters constructor does not support remove(). You can use an ArrayList to fix that.
If for some reason you are using Arrays.asList() to construct your list from an array you are getting a list which cannot be modified.
The size of the
* {#code List} cannot be modified, i.e. adding and removing are unsupported

Categories