Custom android component - java

I am trying to make a custom android component. For that reason I have make my class extend "View", but the class is already extending "BaseAdapter". The component should be something like this: http://www.brightec.co.uk/blog/android-listview-alphabet-scroller but it should appear in the Palette under the CustomView component.
This is the class that should inherit View instead of BaseElement:
public class AlphabetListAdapter extends BaseAdapter {
public static abstract class Row {}
public static final class Section extends Row {
public final String text;
public Section(String text) {
this.text = text;
}
}
public static final class Item extends Row {
public final String text;
public Item(String text) {
this.text = text;
}
}
private List<Row> rows;
public void setRows(List<Row> rows) {
this.rows = rows;
}
}
And this is the class that instantiates it, and uses it as an adapter.
public class MainActivity extends ListActivity {
private AlphabetListAdapter adapter = new AlphabetListAdapter();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.list_alphabet);
for (String country : countries) {
rows.add(new Item(country));
}
adapter.setRows(rows);
setListAdapter(adapter); //not able to do this with a class that extends View
updateList();
}
}
The whole source is available on: https://github.com/brightec/AlphabetScroller
(ths is not my code, it is an example I found online)
Is there a way to do that? I have tried to Google it, but it seems like it is not possible for a single class to extend two classes. Is there another way of making this project to act like a single component?

I think you need to create the class by extending View first then include your AlphabetListAdapter in as a member variable and expose that through getters and setters.
public class AlphabeticListView extends View {
private ListView mListView;
private LinearLayout mSideIndex;
private AlphabetListAdapter adapter;
private List<Object[]> alphabet;
private HashMap<String, Integer> sections;
private static float sideIndexX;
private static float sideIndexY;
private int sideIndexHeight;
private int indexListSize;
private GestureDetector mGestureDetector;
public AlphabeticListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public AlphabeticListView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public AlphabeticListView(Context context) {
super(context);
init();
}
private void init() {
Context context = getContext();
mGestureDetector = new GestureDetector(getContext(),
new SideIndexGestureListener());
mListView = new ListView(context); // TODO add layoutParams and other attributes you might need.
mSideIndex = new LinearLayout(context); // TODO add layoutParams and other attributes you might need.
}
public AlphabetListAdapter getAdapter() {
return adapter;
}
public void setAdapter(AlphabetListAdapter adapter) {
mListView.setAdapter(adapter);
this.adapter = adapter;
}
public List<Object[]> getAlphabet() {
return alphabet;
}
public void setAlphabet(List<Object[]> alphabet) {
this.alphabet = alphabet;
}
public HashMap<String, Integer> getSections() {
return sections;
}
public void setSections(HashMap<String, Integer> sections) {
this.sections = sections;
}
public void updateList() {
mSideIndex.removeAllViews();
indexListSize = alphabet.size();
if (indexListSize < 1) {
return;
}
int indexMaxSize = (int) Math.floor(mSideIndex.getHeight() / 20);
int tmpIndexListSize = indexListSize;
while (tmpIndexListSize > indexMaxSize) {
tmpIndexListSize = tmpIndexListSize / 2;
}
double delta;
if (tmpIndexListSize > 0) {
delta = indexListSize / tmpIndexListSize;
} else {
delta = 1;
}
TextView tmpTV;
for (double i = 1; i <= indexListSize; i = i + delta) {
Object[] tmpIndexItem = alphabet.get((int) i - 1);
String tmpLetter = tmpIndexItem[0].toString();
tmpTV = new TextView(getContext());
tmpTV.setText(tmpLetter);
tmpTV.setGravity(Gravity.CENTER);
tmpTV.setTextSize(15);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT, 1);
tmpTV.setLayoutParams(params);
mSideIndex.addView(tmpTV);
}
sideIndexHeight = mSideIndex.getHeight();
mSideIndex.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// now you know coordinates of touch
sideIndexX = event.getX();
sideIndexY = event.getY();
// and can display a proper item it country list
displayListItem();
return false;
}
});
}
public void displayListItem() {
sideIndexHeight = mSideIndex.getHeight();
// compute number of pixels for every side index item
double pixelPerIndexItem = (double) sideIndexHeight / indexListSize;
// compute the item index for given event position belongs to
int itemPosition = (int) (sideIndexY / pixelPerIndexItem);
// get the item (we can do it since we know item index)
if (itemPosition < alphabet.size()) {
Object[] indexItem = alphabet.get(itemPosition);
int subitemPosition = sections.get(indexItem[0]);
// ListView listView = (ListView) findViewById(android.R.id.list);
mListView.setSelection(subitemPosition);
}
}
class SideIndexGestureListener extends GestureDetector.SimpleOnGestureListener {
#Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
sideIndexX = sideIndexX - distanceX;
sideIndexY = sideIndexY - distanceY;
if (sideIndexX >= 0 && sideIndexY >= 0) {
displayListItem();
}
return super.onScroll(e1, e2, distanceX, distanceY);
}
}
}
And in your MainActivity add the following:
AlphabeticListView listView =
(AlphabeticListView) findViewById(R.id.alphabeticListView1);
listView.setAdapter(adapter);
listView.setAlphabet(alphabet);
listView.setSections(sections);
listView.updateList();

In Java, a Class can only extend one Class directly (but implement several interfaces).
Since you're not submitting your own code, it's hard to give you some substantial feedback, but here are some thoughts:
Can you make your custom View as an XML, and include your class with the "tools:context" attribute?
Can't you just build the functionality you want in an Activity or a Fragment? And does you class have to extend BaseAdapter? Can you use composition instead?
I don't know if this helps you at all, but best of luck.

Related

Passing context into a non-static method - I still can't get this right

I know that there are countless examples of this on the internet, but for some reason I can't get this to work in the particular code I'm working on, despite all the resources/answers I've read through. And I don't have anyone with Java skills around me to help out. So hopefully that changes here.
I'm updating an existing Android media picker plugin (for a cordova app) to make it show video thumbnails in addition to pictures in the device gallery. I'm stuck with a "non-static variable in static context" error, but I'm having a really hard time identifying what needs to be changed. Below is the meat of the code I have. I have removed some parts to hopefully focus on the relevant bits. Essentially, the error occurs inside decodeSampledBitmapFromUri when I'm trying to get the thumbnail of a video. The method I'm using is MediaStore.Video.Thumbnails.getThumbnail and its first argument is the context, which is where the error starts. You can see that in loadThumbnail I tried getting the context using cordova.getActivity() and then passing it to decodeSampledBitmapFromUri, but even inside loadThumbnail I'm still getting the non-static error. I'm not sure how to proceed from here (I'm very new to Java). This is the code (with some other parts stripped out because I think they're not relevant):
public class MediaPicker extends CordovaPlugin {
private static final String HEIGHT = "height";
private static final String COLUMNS = "columns";
private static final String SELECTION_LIMIT = "selectionLimit";
private MediaPickerView view;
public static int getResourceId(Context context, String group, String key) {
return context.getResources().getIdentifier(key, group, context.getPackageName());
}
public static int DP2PX(Context context, float dipValue) {
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dipValue, metrics);
}
#Override
public void initialize(CordovaInterface cordova, CordovaWebView webView) {
super.initialize(cordova, webView);
}
#Override
public boolean execute(String action, JSONArray data, CallbackContext callbackContext) throws JSONException {
if (action.equals("display")) {
JSONObject store = data.getJSONObject(0);
double height = Double.parseDouble(store.getString(HEIGHT));
int columns = Integer.parseInt(store.getString(COLUMNS));
int selectionLimit = Integer.parseInt(store.getString(SELECTION_LIMIT));
display(height, columns, selectionLimit, callbackContext);
return true;
} else {
return false;
}
}
private void display(final double height, final int columns, final int selectionLimit, final CallbackContext callbackContext) {
cordova.getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
if (view == null) {
view = new MediaPickerView(cordova.getActivity());
}
view.setOptions(height, columns, selectionLimit, callbackContext);
view.load();
cordova.getActivity().addContentView(view,
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
}
});
}
public static class MediaPickerView extends FrameLayout implements StateController {
private GridView grid;
private View balanceView;
private int selectionLimit;
private CallbackContext callbackContext;
private TreeMap<Integer, PictureInfo> selection = new TreeMap();
public MediaPickerView(Context context) {
super(context);
init();
}
public MediaPickerView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
LayoutInflater.from(getContext()).inflate(getResourceId(getContext(), "layout", "view_media"), this);
grid = (GridView)findViewById(getResourceId(getContext(), "id", "gridView"));
balanceView = findViewById(getResourceId(getContext(), "id", "vBalancer"));
}
public void setOptions(double height, int columns, int selectionLimit, CallbackContext callbackContext) {
this.selectionLimit = selectionLimit;
this.callbackContext = callbackContext;
grid.setNumColumns(columns);
LinearLayout.LayoutParams glp = (LinearLayout.LayoutParams) grid.getLayoutParams();
glp.weight = (float) height;
LinearLayout.LayoutParams blp = (LinearLayout.LayoutParams) balanceView.getLayoutParams();
blp.weight = (float) (1 - height);
requestLayout();
}
public void load() {
final GridAdapter adapter = new GridAdapter(getContext(), this);
grid.setAdapter(adapter);
new Thread() {
#Override
public void run() {
final String[] columns = new String[]{
MediaStore.Video.VideoColumns._ID,
MediaStore.Video.VideoColumns.DATA,
MediaStore.Video.VideoColumns.BUCKET_DISPLAY_NAME,
MediaStore.Video.VideoColumns.DISPLAY_NAME,
MediaStore.Video.VideoColumns.DATE_TAKEN,
MediaStore.Video.VideoColumns.MIME_TYPE,
MediaStore.Files.FileColumns.MEDIA_TYPE};
final String orderBy = MediaStore.Video.VideoColumns.DATE_TAKEN
+ " DESC";
final String selection = MediaStore.Files.FileColumns.MEDIA_TYPE + "="
+ MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO;
Uri queryUri = MediaStore.Files.getContentUri("external");
final Cursor cursor = getContext().getContentResolver().query(
queryUri,
columns,
selection, // Which rows to return (all rows)
null, // Selection arguments (none)
orderBy);
if (cursor.moveToFirst()) {
adapter.setCursor(cursor);
}
}
}.start();
}
}
public static class MediaCache extends LruCache<String, Bitmap> {
public MediaCache(int maxSize) {
super(maxSize);
}
#Override
protected int sizeOf(String key, Bitmap value) {
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
return value.getAllocationByteCount();
}
return value.getByteCount();
}
}
public static class GridAdapter extends BaseAdapter implements AsyncPictureLoader{
private Cursor cursor;
private Executor executor = Executors.newFixedThreadPool(4);
private MediaCache pictureCache;
private int dataColumn;
private StateController stateController;
private ArrayList<PictureView> createdViews = new ArrayList<PictureView>();
public GridAdapter(Context context, StateController stateController) {
this.stateController = stateController;
int memClass = ( (ActivityManager)context.getSystemService( Context.ACTIVITY_SERVICE ) ).getMemoryClass();
int cacheSize = 1024 * 1024 * memClass / 10;
pictureCache = new MediaCache(cacheSize);
}
#Override
public int getCount() {
return cursor != null ? cursor.getCount() : 0;
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
PictureView view;
if (convertView != null) {
view = (PictureView) convertView;
} else {
view = new PictureView(pictureCache, parent.getContext(), this, stateController);
createdViews.add(view);
}
view.load(position);
return view;
}
public void setCursor(Cursor cursor) {
this.cursor = cursor;
dataColumn = cursor
.getColumnIndex(MediaStore.Video.VideoColumns.DATA);
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
notifyDataSetChanged();
}
});
}
#Override
public void loadThumbnail(final PictureInfo pictureInfo, final AsyncPictureLoaderCallback callback) {
if (cursor == null) {
return;
}
executor.execute(new Runnable() {
#Override
public void run() {
if (cursor == null || pictureInfo.cancelled) {
return;
}
synchronized (cursor) {
cursor.moveToPosition(pictureInfo.position);
pictureInfo.uri = cursor.getString(dataColumn);
}
if (pictureInfo.uri == null) {
return;
}
synchronized (pictureCache) {
Bitmap cachedBitmap = pictureCache.get(pictureInfo.uri);
if (cachedBitmap != null) {
pictureInfo.thumbnail = cachedBitmap;
callback.onLoad(pictureInfo);
return;
}
}
int thumbSideSize = callback.getThumbnailSideSize();
if (thumbSideSize <= 0) {
thumbSideSize = 128;
}
// the next 4 variables are needed for videos, see https://stackoverflow.com/a/29555484/7987987
int type = cursor.getColumnIndex(MediaStore.Files.FileColumns.MEDIA_TYPE);
int tInt = cursor.getInt(type);
int colId = cursor.getColumnIndex(MediaStore.Video.VideoColumns._ID);
int id = cursor.getInt(colId);
pictureInfo.thumbnail = decodeSampledBitmapFromUri(pictureInfo.uri, thumbSideSize, thumbSideSize, tInt, id, cordova.getActivity());
if (pictureInfo.thumbnail != null) {
callback.onLoad(pictureInfo);
synchronized (pictureCache) {
pictureCache.put(pictureInfo.uri, pictureInfo.thumbnail);
}
} else {
}
}
});
}
private Bitmap decodeSampledBitmapFromUri(String path, int reqWidth, int reqHeight, int typeInt, int id, Context context) {
Bitmap bm = null;
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
if (typeInt == 3) {
// this is a video, handle according to https://stackoverflow.com/a/29555484/7987987
// using BitmapFactory options as seen in the link above
options.inSampleSize = 4; // hardcoded for now until this works, then I'll make it dynamic
options.inPurgeable = true;
bm = MediaStore.Video.Thumbnails.getThumbnail(
context.getContentResolver(), id,
MediaStore.Video.Thumbnails.MINI_KIND, options);
} else {
// this is an image
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
// Calculate inSampleSize
options.inSampleSize = calculateSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
bm = BitmapFactory.decodeFile(path, options);
}
return bm;
}
public int calculateSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
if (width > height) {
inSampleSize = Math.round((float)height / (float)reqHeight);
} else {
inSampleSize = Math.round((float)width / (float)reqWidth);
}
}
return inSampleSize;
}
}
public interface AsyncPictureLoader {
void loadThumbnail(PictureInfo position, AsyncPictureLoaderCallback callback);
}
public interface AsyncPictureLoaderCallback {
void onLoad(PictureInfo picture);
int getThumbnailSideSize();
}
public interface StateController {
// stuff here that controls selection
}
public static class PictureInfo {
public int position;
public String uri;
public Bitmap thumbnail;
public volatile boolean cancelled = false;
}
public static class PictureView extends FrameLayout implements AsyncPictureLoaderCallback, CompoundButton.OnCheckedChangeListener {
private final AsyncPictureLoader loader;
private final CheckBox checkBox;
private final StateController stateController;
private final MediaCache pictureCache;
private ImageView vImage;
private PictureInfo pictureInfo;
public PictureView(MediaCache pictureCache, Context context, AsyncPictureLoader loader, StateController stateController) {
super(context);
this.pictureCache = pictureCache;
this.loader = loader;
this.stateController = stateController;
LayoutInflater.from(getContext()).inflate(getResourceId(getContext(), "layout", "view_media_item"), this);
vImage = (ImageView)findViewById(getResourceId(getContext(), "id", "vImage"));
checkBox = (CheckBox)findViewById(getResourceId(getContext(), "id", "checkBox"));
}
public void load(int position) {
if (pictureInfo != null) {
pictureInfo.cancelled = true;
}
pictureInfo = new PictureInfo();
pictureInfo.position = position;
pictureInfo.thumbnail = null;
pictureInfo.uri = null;
vImage.setImageResource(0);
vImage.setVisibility(INVISIBLE);
loader.loadThumbnail(pictureInfo, this);
updateSelection();
}
#Override
public void onLoad(PictureInfo picture) {
if (this.pictureInfo != picture) {
return;
}
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
vImage.setImageBitmap(pictureInfo.thumbnail);
vImage.setVisibility(VISIBLE);
}
});
}
}
}

Why are swipes not being recognized in my code?

Im making an android game that only needs to recognize swipes. However, the onFling method is never called for some reason. I have no issue with modifying onScroll or other methods just so that onFling works. The GestureDetectGridView is just a basic class that calls the gridView super constructor. The Movement Controller is definitely correct as well. So the issue has to be in this class.
public class TwentyGestureDetectGridView extends GestureDetectGridView implements View.OnTouchListener, GestureDetector.OnGestureListener {
private static final int SWIPE_MIN_DISTANCE = 100;
private final GestureDetector gDetector;
private TwentyMovementController mController;
public TwentyGestureDetectGridView(Context context) {
super(context);
gDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener());
mController = new TwentyMovementController();
}
public TwentyGestureDetectGridView(Context context, AttributeSet attrs) {
super(context, attrs);
gDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener());
mController = new TwentyMovementController();
}
public TwentyGestureDetectGridView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
gDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener());
mController = new TwentyMovementController();
}
public void onSwipeUp(){}
public void onSwipeDown(){}
public void onSwipeLeft() {}
public void onSwipeRight() {}
public boolean onTouch(View v, MotionEvent event) {
return gDetector.onTouchEvent(event);
}
#Override
public boolean onDown(MotionEvent e) {
return true;
}
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
float distanceX = e2.getX() - e1.getX();
float distanceY = e2.getY() - e1.getY();
if (Math.abs(distanceX) > Math.abs(distanceY) && Math.abs(distanceX) > SWIPE_MIN_DISTANCE) {
if (distanceX > 0) {
onSwipeRight();
} else {
onSwipeLeft();
}
return true;
} else if (Math.abs(distanceY) > Math.abs(distanceX) && Math.abs(distanceY) > SWIPE_MIN_DISTANCE) {
if (distanceY > 0) {
onSwipeUp();
} else {
onSwipeDown();
}
return true;
}
return false;
}
#Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {return true;}
You are missing a call to View.setOnTouchListener
For the view you want to register swipes in (probably your base layout), call view.setOnTouchListener(your listener here)
Maybe like this:
#Override
public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstance){
View root = somehowCreateView();
root.setOnTouchListener(this);
return root;
}
public class TwentyGameActivity extends GameActivity implements Observer {
TwentyBoardManager twentyBoardManager;
private TwentyGestureDetectGridView gridView;
private static int columnWidth, columnHeight;
ArrayList<Button> tileButtons;
public void display() {
updateTileButtons();
gridView.setAdapter(new CustomAdapter(tileButtons, columnWidth, columnHeight));
}
private void createTileButtons(Context context){
TwentyBoard board = twentyBoardManager.getBoard();
tileButtons = new ArrayList<>();
for (int row = 0; row != board.getNumRows(); row++) {
for (int col = 0; col != board.getNumCols(); col++) {
Button tmp = new Button(context);
tmp.setBackgroundResource(board.getTile(row, col).getBackground());
this.tileButtons.add(tmp);
}
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
twentyBoardManager = (TwentyBoardManager) Savable.loadFromFile(TEMP_SAVE_FILENAME);
createTileButtons(this);
setContentView(R.layout.activity_twenty_game);
gridView = findViewById(R.id.gridTwenty);
gridView.setNumColumns(twentyBoardManager.getSize());
gridView.setBoardManager(twentyBoardManager);
twentyBoardManager.addObserver(this);
gridView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
gridView.getViewTreeObserver().removeOnGlobalLayoutListener(
this);
int displayWidth = gridView.getMeasuredWidth();
int displayHeight = gridView.getMeasuredHeight();
columnWidth = displayWidth / twentyBoardManager.twentyBoard.getNumCols();
columnHeight = displayHeight / twentyBoardManager.twentyBoard.getNumCols();
display();
}
});
addUndoButtonListener();
twentyBoardManager.twentyBoard.generateRandomTile();
}
private void addUndoButtonListener(){
Button undoButton = findViewById(R.id.undoTwentyButton);
undoButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
twentyBoardManager.undo();
}
});
}
#Override
public void update(Observable o, Object arg) {
display();
}
private void updateTileButtons() {
TwentyBoard board = twentyBoardManager.getBoard();
int nextPos = 0;
for (Button b : tileButtons) {
int row = nextPos / board.getNumCols();
int col = nextPos % board.getNumCols();
b.setBackgroundResource(board.getTile(row, col).getBackground());
nextPos++;
}
}
}

How to Delete Item Without Deleting Position in Recycler View?

I really need your help. I've searched Google many days with many keywords, but I couldn't get it. So, I decided to ask to you.
So, here it is. Actually, I have one button in RecyclerView, but this button is repeated as much amount of data available, there are: Button with text "Baca 3x", "Baca 4x", and so on. I want, if I click button with text "Baca 3x" 3 times, it will change to "Baca 2x" >> "Baca 1x" >> remove item. Also if I click button with text "Baca 4x" 4 times, it will change to "Baca 3x" >> "Baca 2x" >> "Baca 1x" >> remove item.
But my problem is, I can't treat every button with different treatment, because every time the item has been deleted, position of data changes automatically. Because of this, I can't get specific button. For example: There is two button,
1. Button "Baca 3x" on position 0
2. Button "Baca 4x" on position 1
If button "Baca 3x" on position 0 has been deleted, so button "Baca 4x" changed it's position automatically to 0. The problem lays here.
Until now I just get every button based on their positions, which is a problem for me. Because of this I am thinking about How to Delete Item Without Deleting Position in Recycler View? Can you guys solve my problem? Should I use DiffUtil?And how to use it? Below the complete code I use:
ModelDoa.java
public class ModelDoa {
public static final int DOA_PAGI = 0;
public static final int DOA_SORE = 1;
public static final int DOA_MASJID = 2;
public static final int DOA_BANGUNT = 3;
public static final int DOA_MAU_TIDUR = 4;
private String mName;
private String bName;
private int mType;
public ModelDoa(String name, String butong, int type) {
this.mName = name;
this.bName = butong;
this.mType = type;
}
public String getName() {
return mName;
}
public void setName(String name) {
this.mName = name;
}
public int getType() {
return mType;
}
public void setType(int type) { this.mType = type; }
public String ambilName() {
return bName;
}
public void setNama(String butonk) {
this.bName = butonk;
}
}
AdapterDoa.java
public class AdapterDoa extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public List<ModelDoa> mList;
public AdapterDoa(List<ModelDoa> list) {
this.mList = list;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case DOA_PAGI:
View vieu = LayoutInflater.from(parent.getContext()).inflate(R.layout.content_doa, parent, false);
PagiViewHolder rcv = new PagiViewHolder(vieu, this);
return rcv;
case DOA_SORE:
View doa = LayoutInflater.from(parent.getContext()).inflate(R.layout.content_doa, parent, false);
SoreViewHolder mdoa = new SoreViewHolder(doa);
return mdoa;
case DOA_MASJID:
View dMasjid = LayoutInflater.from(parent.getContext()).inflate(R.layout.content_doa, parent, false);
MasjidViewHolder mMasjid = new MasjidViewHolder(dMasjid);
return mMasjid;
case DOA_BANGUNT:
View dBangunt = LayoutInflater.from(parent.getContext()).inflate(R.layout.content_doa, parent, false);
BanguntViewHolder mBangunt = new BanguntViewHolder(dBangunt);
return mBangunt;
case DOA_MAU_TIDUR:
View regut = LayoutInflater.from(parent.getContext()).inflate(R.layout.content_doa, parent, false);
MauTidurViewHolder turu = new MauTidurViewHolder(regut);
return turu;
}
return null;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
ModelDoa object = mList.get(position);
if (object != null) {
switch (object.getType()) {
case DOA_PAGI:
((PagiViewHolder) holder).mTitle.setText(object.getName());
((PagiViewHolder) holder).tombolbaca.setText(object.ambilName());
break;
case DOA_SORE:
((SoreViewHolder) holder).mTitle.setText(object.getName());
((SoreViewHolder) holder).tombolbaca.setText(object.ambilName());
break;
case DOA_MASJID:
((MasjidViewHolder) holder).mTitle.setText(object.getName());
((MasjidViewHolder) holder).tombolbaca.setText(object.ambilName());
break;
case DOA_BANGUNT:
((BanguntViewHolder) holder).mTitle.setText(object.getName());
((BanguntViewHolder) holder).tombolbaca.setText(object.ambilName());
break;
case DOA_MAU_TIDUR:
((MauTidurViewHolder) holder).mTitle.setText(object.getName());
((MauTidurViewHolder) holder).tombolbaca.setText(object.ambilName());
break;
}
}
}
public void deleteItem(int position) {
mList.remove(position); // hapus list
notifyItemRemoved(position); // hapus tampilan
// notifyItemRangeChanged( position, mList.size());
}
#Override
public int getItemCount() {
if (mList == null)
return 0;
return mList.size();
}
#Override
public int getItemViewType(int position) {
if (mList != null) {
ModelDoa object = mList.get(position);
if (object != null) {
return object.getType();
}
}
return 0;
}
}
PagiViewHolder.java
public class PagiViewHolder extends RecyclerView.ViewHolder {
public TextView mTitle;
public Button tombolbaca;
public Button teksbaca;
public Button tombolshare;
private RelativeLayout rl2;
private int klik10 = 10;
private AdapterDoa myAdapter;
public PagiViewHolder(View itemView, AdapterDoa myAdapter) {
super(itemView);
this.myAdapter = myAdapter;
itemView.setOnClickListener(mainViewClickListener);
mTitle = (TextView) itemView.findViewById(R.id.titleTextView);
tombolbaca = (Button) itemView.findViewById(R.id.buttonbaca);
tombolshare = (Button) itemView.findViewById(R.id.buttonshare);
tombolbaca.setOnClickListener(bacaClickListener);
tombolshare.setOnClickListener(shareClickListener);
rl2 = (RelativeLayout) itemView.findViewById(R.id.relmasjid);
}
private View.OnClickListener bacaClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
teksbaca = (Button) v.findViewById(R.id.buttonbaca);
// Baca 10x
if( getAdapterPosition() ==0 ) {
klik10--;
teksbaca.setText("Baca " + klik10 + "x");
if (klik10 <= 0)
{
// modify listItems however you want... add, delete, shuffle, etc
myAdapter.deleteItem(getAdapterPosition());
}
}
} // onclick
};
private View.OnClickListener shareClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
// Do button click handling here
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, mTitle.getText().toString() + "\n \n download aplikasinya di: http://www.tauhid.or.id" );
sendIntent.setType("text/plain");
Intent.createChooser(sendIntent,"Share via");
v.getContext().startActivity(sendIntent);
}
};
private View.OnClickListener mainViewClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
// Do button click handling here
}
};
}
DoaPagi.java
public class DoaPagi extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_doa_pagi);
// toolbar
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
//this line shows back button
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
List<ModelDoa> rowListItem = getData();
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(DoaPagi.this);
RecyclerView mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
mRecyclerView.setLayoutManager(linearLayoutManager);
mRecyclerView.setHasFixedSize(true);
AdapterDoa rcAdapter = new AdapterDoa(rowListItem);
mRecyclerView.setAdapter(rcAdapter);
}
private List<ModelDoa> getData() {
String[] data = getResources().getStringArray(R.array.doapagi);
String[] baca = getResources().getStringArray(R.array.bacapagi);
List<ModelDoa> list = new ArrayList<ModelDoa>();
for (int i = 0; i < data.length; i++) {
list.add(new ModelDoa(data[i], baca[i], ModelDoa.DOA_PAGI));
}
return list;
}
// Agar back button pada halaman induk settings berfungsi
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
this.finish();
return true;
}
return super.onOptionsItemSelected(item);
}
}
UPDATE (FIX CODE) By: Krishna Sharma:
https://github.com/seadclark/RecyclerViewWithButtonClicks
Here is the fix. just update the ModelDoa constructor as below. I have verified myself and working as expected now. Also sent you pull request on github.
public ModelDoa(String name, String butong, int type) {
this.mName = name;
this.bName = butong;
this.mType = type;
String[] data = butong.split("\\s");
if (data.length > 0) {
String count = data[1].substring(0, data[1].length() - 1);
read10 = Integer.parseInt(count);
}
}
Instead of removing the item from your list AND updating the interface, have two methods. One of them (deleteItem) will only delete the item and the other (deleteItemAndUpdate) will delete the item and update the interface.
public void deleteItem(int position) {
mList.remove(position); // hapus list
}
public void deleteItemAndUpdate(int position) {
mList.remove(position); // hapus list
notifyItemRemoved(position); // hapus tampilan
}
In the future, you can decide whether you want to only remove the item from your list OR remove the item and update the UI.
EDIT 1:
You need to keep track of the amount of times that each item was clicked. We can call this value readCount. Every time that the item is clicked, we subtract 1 from this value. When this value reaches 0, we remove it from the list.
ModelDoa:
public class ModelDoa {
private int readCount = 10;
public int getReadCount() {
return this.readCount;
}
public void setReadCount(int readCount) {
this.readCount = readCount;
}
}
PagiViewHolder:
private View.OnClickListener bacaClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
teksbaca = (Button) v.findViewById(R.id.buttonbaca);
ModelDoa modelDoa = mAdapter.getItem(getAdapterPosition());
if (modelDoa != null) {
modelDoa.setReadCount(modelDoa.getReadCount() - 1);
if (modelDoa.getReadCount() <= 0) {
myAdapter.deleteItem(getAdapterPosition());
}
teksbaca.setText("Baca " + modelDoa.getReadCount() + "x");
}
}
};
AdapterDoa:
public ModelDoa getItem(int position) {
if (position > -1 && position < getItemCount()) {
return this.mList.get(position);
} else {
return null;
}
}
EDIT 2:
The idea is to set the readCount variable when you instantiate the object. You do not have multiple variables that do the same thing. You just change the single readCount variable to be either 7 or 10 when you are creating it and use the same getItem method when retrieving the model (not variable!) itself.
ModelDoa:
public class ModelDoa {
private String name;
private String butong;
private int type;
private int readCount;
public ModelDoa(String name, String butong, int type, int readCount) {
this.mName = name;
this.bName = butong;
this.mType = type;
this.readCount = readCount;
}
public int getReadCount() {
return this.readCount;
}
public void setReadCount(int readCount) {
this.readCount = readCount;
}
}
DoaPagi:
private List<ModelDoa> getData() {
String[] data = getResources().getStringArray(R.array.doapagi);
String[] baca = getResources().getStringArray(R.array.bacapagi);
List<ModelDoa> list = new ArrayList<ModelDoa>();
for (int i = 0; i < data.length; i++) {
// Here is where you would set the value of readCount.
list.add(new ModelDoa(data[i], baca[i], ModelDoa.DOA_PAGI, i));
}
return list;
}

Android List(RecyclerView Adapter) is changing when Edittext On Text change

İ have a problem about RecyclerView filter.
İ am using edittext on text change method for filter text query in recyclerview but when i filter my Product List is changing.
Note : all of that in fragment and fragment in viewpager.
My problem is that : when i write something it is working but at the same time my product list's elements are changing to result of filter.
So in example at first
MyList Has 40 items
FilteredDataList is empty
After i write "a" in edittext after that FilteredDataList is has 30 items but MyList has same 30 items. But i have not set anything to Mylist
My Data List ,i get it from sqlite
productList = new ArrayList<>();
productList = handler.getAllProduct();
My Filter Method
private List<Product> filter(List<Product> models, String query) {
query = query.toLowerCase();
List<Product> filteredModelList = new ArrayList<>();
filteredModelList.clear();
for (Product model : models) {
final String text = model.get_ProductName().toLowerCase();
if (text.contains(query)) {
filteredModelList.add(model);
}
}
return filteredModelList;
}
My Edittext OnChange Metod
searchEdt.addTextChangedListener(new TextWatcher() {
#Override
public void afterTextChanged(Editable s) {
}
#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 (s.length() != 0) {
List<Product> filteredModelList = filter( productList, s.toString());
rcAdapter.animateTo(filteredModelList);
pager_recycler_view.scrollToPosition(0);
} else {
rcAdapter.animateTo(productList);
pager_recycler_view.scrollToPosition(0);
}
}
});
My AdapterClass
public class ProductRecyclerViewAdapter extends RecyclerView.Adapter< ProductRecyclerViewHolder > {
private List<Product> itemList;
private Context context;
public ProductRecyclerViewAdapter(Context context, List<Product> itemList) {
this.itemList = itemList;
this.context = context;
}
#Override
public ProductRecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.product_card_single_item, null);
ProductRecyclerViewHolder rcv = new ProductRecyclerViewHolder(layoutView);
return rcv;
}
#Override
public void onBindViewHolder(ProductRecyclerViewHolder holder, int position) {
holder.productName.setText(itemList.get(position).get_ProductName());
holder.productWatCode.setText("%" +itemList.get(position).get_ProductWatCode());
holder.productPOR.setText("%" +itemList.get(position).get_ProductPOR());
holder.productRSP.setText("£" +itemList.get(position).get_ProductRSP());
holder.productDescription.setText(itemList.get(position).get_ProductDescription());
holder.productSKU.setText(itemList.get(position).get_ProductSKU());
holder.productPrice.setText("£" + itemList.get(position).get_ProductPrice());
// holder.productCountCart.setText("");
Picasso.with(context)
.load( "http://firmabayi.com/images/ilanK/" +itemList.get(position).get_ProductPhoto())
.placeholder(R.drawable.add_icon)
.error(R.drawable.minus_icon)
.into(holder.productPhoto);
// holder.countryPhoto.setImageResource(itemList.get(position).get_ProductName());
}
#Override
public int getItemCount() {
return this.itemList.size();
}
public void animateTo(List<Product> itemList) {
applyAndAnimateRemovals(itemList);
applyAndAnimateAdditions(itemList);
applyAndAnimateMovedItems(itemList);
}
private void applyAndAnimateRemovals(List<Product> newModels) {
for (int i = itemList.size() - 1; i >= 0; i--) {
final Product model = itemList.get(i);
if (!newModels.contains(model)) {
removeItem(i);
}
}
}
private void applyAndAnimateAdditions(List<Product> newModels) {
for (int i = 0, count = newModels.size(); i < count; i++) {
final Product model = newModels.get(i);
if (!itemList.contains(model)) {
addItem(i, model);
}
}
}
private void applyAndAnimateMovedItems(List<Product> newModels) {
for (int toPosition = newModels.size() - 1; toPosition >= 0; toPosition--) {
final Product model = newModels.get(toPosition);
final int fromPosition = itemList.indexOf(model);
if (fromPosition >= 0 && fromPosition != toPosition) {
moveItem(fromPosition, toPosition);
}
}
}
public Product removeItem(int position) {
final Product model = itemList.remove(position);
notifyItemRemoved(position);
return model;
}
public void addItem(int position, Product model) {
itemList.add(position, model);
notifyItemInserted(position);
}
public void moveItem(int fromPosition, int toPosition) {
final Product model = itemList.remove(fromPosition);
itemList.add(toPosition, model);
notifyItemMoved(fromPosition, toPosition);
}
}
i solved my problem it is only about adapter class one line :(
in adapter class
instead of
this.itemList = itemList;
use that
this.itemList = new ArrayList<>(itemList);
It is about your productList.
When you create a object like doing this;
Class a = b();
You are cloning your object. In deep, they are the same object.
So when you filtered object named a, b is being effected from this.
In short, don't do this. Instead of cloning object you should add each items to a from b by one by.
Like this;
productList = new ArrayList<>();
for( int i = 0 ; i <arrayFromSource.size() ; i++ )
{
productList.add(arrayFromSource.get(i));
}

How to create a full screen Android Wear app without cards

I'm brand new to Android programming and I'm trying to create a full screen Android Wear interface with custom layouts and no cards. I'm trying to go off the sample but I can't figure out how to get around using CardFragments. My MainActivity code is essentially identical to the example, with a few names changed. Here is the code for my GridViewPagerAdaper:
public class MyGridViewPagerAdapter extends FragmentGridPagerAdapter {
private final Context mContext;
public MyGridViewPagerAdapter(Context ctx, FragmentManager fm) {
super(fm);
mContext = ctx;
}
static final int[] BG_IMAGES = new int[]{
R.drawable.bg,
};
/**
* A simple container for static data in each page
*/
private static class Page {
int titleRes;
int textRes;
int iconRes;
int cardGravity = Gravity.BOTTOM;
boolean expansionEnabled = true;
float expansionFactor = 1.0f;
int expansionDirection = CardFragment.EXPAND_DOWN;
public Page(int titleRes) {
this.titleRes = titleRes;
this.textRes = textRes;
this.iconRes = iconRes;
}
public Page(int titleRes, int textRes, int iconRes, int gravity) {
this.titleRes = titleRes;
this.textRes = textRes;
this.iconRes = iconRes;
this.cardGravity = gravity;
}
}
private final Page[][] PAGES = {
{
new Page(R.drawable.tuner),
},
{
new Page(R.drawable.metronome),
new Page(R.drawable.metroplain)
},
};
#Override
public Fragment getFragment(int row, int col) {
Page page = PAGES[row][col];
// String title = page.titleRes != 0 ? mContext.getString(page.titleRes) : null;
// String text = page.textRes != 0 ? mContext.getString(page.textRes) : null;
CardFragment fragment = CardFragment.create("", "", page.iconRes);
// Advanced settings
fragment.setCardGravity(page.cardGravity);
fragment.setExpansionEnabled(page.expansionEnabled);
fragment.setExpansionDirection(page.expansionDirection);
fragment.setExpansionFactor(page.expansionFactor);
return fragment;
}
#Override
public ImageReference getBackground(int row, int column) {
return ImageReference.forDrawable(BG_IMAGES[row % BG_IMAGES.length]);
}
#Override
public int getRowCount() {
return PAGES.length;
}
#Override
public int getColumnCount(int rowNum) {
return PAGES[rowNum].length;
}
}
What's the best way to get rid of the cards and use a custom layout? Thanks for your help.
In your adapter, give your fragments as following:
private final Activity mContext;
private final Fragment[][] mFragment;
public MyGridViewPagerAdapter(Activity ctx, FragmentManager fm, Fragment[][] fragments)
{
super(fm);
mContext = ctx;
this.mFragment = fragments;
}
then override the following methods:
#Override
public Fragment getFragment(int row, int col)
{
return mFragment[row][col];
}
#Override
public int getRowCount()
{
return mFragment.length;
}
#Override
public int getColumnCount(int rowNum)
{
return mFragment[rowNum].length;
}
then in your activity do as following:
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
final GridViewPager pager = (GridViewPager) findViewById(R.id.pager);
final Fragment[][] items = {
{
CusmtomFragment.newInstance("your","arguments"),
CusmtomFragment.newInstance()
},
{
OtherFragment.newInstance(),
AnotherFragment.newInstance(1234)
}
};
// ....
pager.setAdapter(new MyGridViewPagerAdapter(this, getFragmentManager(), items));
}
Hope it helps !
If you implement a custom wearable app you can do what you want including a custom UI.
The problems are more to Is there any way to detect if the clock is round?
Or how to start the app you n the wearable. This is done with a special service. Basically you is the dataApi for that.

Categories

Resources