So i'm making a xylophone app for android and i've run into a problem, i'm not sure how to correctly use onTouch. Right now I can press an image and play the sound, but I cannot play two sounds at once, nor can I slide my finger down the xylophone and play all the sounds, it will only play the first image pressed. I know this is because of onTouch and Multitouch but i'm not sure how to do this and I can't find any relevant sample code, any help is appreciated!
This is my main activity
public class Xylophone extends Activity {
private Player mSoundManager;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_xylophone);
mSoundManager = new Player();
mSoundManager.initSounds(getBaseContext());
mSoundManager.addSound(1, R.raw.note01);
mSoundManager.addSound(2, R.raw.note02);
mSoundManager.addSound(3, R.raw.note03);
mSoundManager.addSound(4, R.raw.note04);
mSoundManager.addSound(5, R.raw.note05);
mSoundManager.addSound(6, R.raw.note06);
mSoundManager.addSound(7, R.raw.note07);
mSoundManager.addSound(8, R.raw.note08);
ImageView img01 = (ImageView) findViewById(R.id.imageView1);
img01.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
mSoundManager.playSound(1);
return false;
}
});
ImageView img02 = (ImageView) findViewById(R.id.imageView2);
img02.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
mSoundManager.playSound(2);
return false;
}
});
This is my SoundPool activity
public class Player {
private SoundPool mSoundPool;
private HashMap<Integer, Integer> mSoundPoolMap;
private AudioManager mAudioManager;
private Context mContext;
public Player()
{
}
public void initSounds(Context theContext) {
mContext = theContext;
mSoundPool = new SoundPool(8, AudioManager.STREAM_MUSIC, 0);
mSoundPoolMap = new HashMap<Integer, Integer>();
mAudioManager = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
}
public void addSound(int Index,int SoundID)
{
mSoundPoolMap.put(Index, mSoundPool.load(mContext, SoundID, 1));
}
public void playSound(int index) {
int streamVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
mSoundPool.play(mSoundPoolMap.get(index), streamVolume, streamVolume, 1, 0, 1f);
}
public void playLoopedSound(int index) {
int streamVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
mSoundPool.play(mSoundPoolMap.get(index), streamVolume, streamVolume, 1, -1, 1f);
}
}
This is my layout
<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" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerVertical="true"
android:orientation="horizontal" >
<ImageView
android:id="#+id/imageView1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:adjustViewBounds="true"
android:cropToPadding="false"
android:scaleType="fitXY"
android:src="#drawable/button01" />
<ImageView
android:id="#+id/imageView2"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:scaleType="fitXY"
android:src="#drawable/button02" />
hopefully you figured it out until now. Still here's my shot at it:
First of all your second class, SoundPool, is not an activity.
What you have to try is not overriding each button's onTouch method.
Instead, in your main activity, make it implement OnTouchListener.
Then of course, you need to implement/override the OnTouchListener's methods. So now, if you register your main view and/or every button(see for yourself which works!) to OnTouchListener, you will get all touches (multi touch as well).
Have a look at the MotionEvent class for more details
public class Xylophone extends Activity implements onTouchLister{
public static final String TAG = "Xylophone";
#Override
public void onCreate(Bundle savedInstanceState) {
/*Either have your parent view register THIS (Xylophone) as its listener, or have each button register THIS(Xylophone) as its listener.*/
yourParentView.setOnTouchListener(this);
//or
img02.setOnTouchListener(this);
}
#Override
public boolean onTouch(View v, MotionEvent event) {
Log.i(TAG, "ID:" + Integer.toString(v.getId()));
Log.i(TAG, "Pointer count: " + event.getPointerCount());
Log.i(TAG, "Action: " + event.getActionMasked());
Log.i(TAG, "Action index: " + event.getActionIndex());
}
Related
I'm using StyledPlayerView for controls. I want to implement that while user moves TimeBar video also change its position simultaneously(not after user stopped scrubbing).
I know that I can use TimeBar.OnScrubListener(), but I cannot find a way to implement that method to default StyledPlayerView. Is there a way to do that? Thanks.
public class ShowTutorialFragment extends Fragment {
private ExoPlayer player;
private NavController navController;
private ImageView imageViewClose;
private StyledPlayerView videoViewTutorial;
private boolean goBackLockScreen = false;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Bundle bundle = getArguments();
if (bundle != null && bundle.getString("whereItCame") == "LockScreen")
goBackLockScreen = true;
return inflater.inflate(R.layout.fragment_show_tutorial, container, false);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
initialize(view);
setListeners();
}
#Override
public void onPause() {
super.onPause();
player.pause();
}
private void initialize(View view) {
player = new ExoPlayer.Builder(requireContext()).build();
navController = Navigation.findNavController(view);
imageViewClose = view.findViewById(R.id.image_view_close_dialog);
videoViewTutorial = view.findViewById(R.id.video_view_tutorial);
playVideo();
}
private void playVideo() {
String path = "android.resource://" + getActivity().getPackageName() + "/" + R.raw.tutorial_video;
MediaItem mediaItem = MediaItem.fromUri(path);
videoViewTutorial.setPlayer(player); // Set the media item to be played.
videoViewTutorial.setShowPreviousButton(false);
videoViewTutorial.setShowNextButton(false);
player.setMediaItem(mediaItem); // Prepare the player.
player.prepare();
player.play();
Log.i("track", "playVideo: "+ player.getTrackSelector().toString());
/* setXButtonVisible();*/
}
private void setListeners() {
imageViewClose.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
player.release();
if (goBackLockScreen) {
navController.navigate(R.id.action_showTutorialFragment_to_lockScreenFragment);
} else navController.navigate(R.id.action_showTutorialFragment_to_mainMenu);
}
});
videoViewTutorial.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
player.pause();
videoViewTutorial.hideController();
return false;
}
});
}
}
my xml code
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/layout_fl_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/black"
android:clickable="true"
android:focusable="true"
android:orientation="vertical"
tools:context="com.atgeotech.erpintel.views.tutorial.ShowTutorialFragment">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
>
<com.google.android.exoplayer2.ui.StyledPlayerView
android:id="#+id/video_view_tutorial"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:longClickable="true"
app:show_buffering="when_playing"
app:show_shuffle_button="true"
app:surface_type="surface_view"
tools:ignore="SpeakableTextPresentCheck" />
<ImageView
android:id="#+id/image_view_close_dialog"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_gravity="end"
android:layout_margin="8dp"
android:background="#color/faded_black"
android:clickable="true"
android:focusable="true"
android:visibility="visible"
app:srcCompat="#drawable/ic_close_dialog"
tools:ignore="SpeakableTextPresentCheck" />
</FrameLayout>
Issue which I tried to explain is that if I want to change video position during scrubbing, I must use TimeBar.OnScrubListener.onScrubMove(). In order to use this, function must access to DefaultTimeBar inside StyledPlayerView, and I did not know how to do it, yet solution is easy.
I just need to add global DefaultTimeBar variable,
private DefaultTimeBar timeBar;
then initialize it through videoViewTutorial variable
timeBar = videoViewTutorial.findViewById(R.id.exo_progress);//Solution
then I just use the listener to achieve my desired result
timeBar.addListener(new TimeBar.OnScrubListener() { //Solution
#Override
public void onScrubStart(TimeBar timeBar, long position) {
}
#Override
public void onScrubMove(TimeBar timeBar, long position) {
player.seekTo(position);
}
#Override
public void onScrubStop(TimeBar timeBar, long position, boolean canceled) {
}
});
I am currently making an exercise app and I made a Viewpager with 5 pages and has previous and next buttons that work just fine and a one-minute countdown timer that starts after the activity is opened. I am looking forward to making the Viewpager go to the next page after the timer is finished, resume the timer when the page is opened, and do the same no matter if the page is the next or previous. I am new to coding and I have no clue how to do that. If there is someone to show me what to change in the code or show me a working code it would be amazing.
The activity :
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_morning);
findViewById(R.id.imageBackMorning).setOnClickListener(v -> onBackPressed());
countdownText = findViewById(R.id.countdownText);
countdownButton = findViewById(R.id.countdownButton);
countdownButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startStop();
}
});
startTimer();
btnPrev = findViewById(R.id.prev);
btnNext = findViewById(R.id.next);
btnPrev.setVisibility(View.GONE);
setupViewPager();
pageChange();
}
private void startStop() {
if (timerRunning) {
stopTimer();
} else {
startTimer();
}
}
private void startTimer() {
countdownTimer = new CountDownTimer(timeLeft, 1000) {
#Override
public void onTick(long l) {
timeLeft = l;
update();
}
#Override
public void onFinish() {
}
}.start();
countdownButton.setText("Pause");
timerRunning = true;
}
private void stopTimer() {
countdownTimer.cancel();
countdownButton.setText("Resume");
timerRunning = false;
}
private void update() {
int minutes = (int) timeLeft / 60000;
int seconds = (int) timeLeft % 60000 / 1000;
String timeLeftText;
timeLeftText = "" + minutes;
timeLeftText += ":";
if (seconds < 10) timeLeftText += "0";
timeLeftText += seconds;
countdownText.setText(timeLeftText);
}
private void pageChange() {
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
page = position;
switch (position) {
case 0:
btnPrev.setVisibility(View.GONE);
btnNext.setVisibility(View.VISIBLE);
break;
case 1:
case 2:
case 3:
btnPrev.setVisibility(View.VISIBLE);
btnNext.setVisibility(View.VISIBLE);
break;
case 4:
btnPrev.setVisibility(View.VISIBLE);
btnNext.setVisibility(View.GONE);
break;
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
}
private void setupViewPager() {
adapter = new Adapter(this);
viewPager = findViewById(R.id.viewpager);
viewPager.setAdapter(adapter);
}
public void prev(View view) {
viewPager.setCurrentItem(viewPager.getCurrentItem() - 1, true);
}
public void next(View view) {
viewPager.setCurrentItem(viewPager.getCurrentItem() + 1, true);
}
private class Adapter extends PagerAdapter {
Context context;
LayoutInflater inflater;
public Adapter(Context context) {
this.context = context;
}
// list img
int[] list_img = {
R.drawable.email_pic,
R.drawable.email_pic,
R.drawable.email_pic,
R.drawable.email_pic,
R.drawable.email_pic
};
// list judul
int[] list_judul = {
R.string.judul_1,
R.string.judul_2,
R.string.judul_3,
R.string.judul_4,
R.string.judul_5
};
// list deskripsi
int[] list_desk = {
R.string.desk_1,
R.string.desk_2,
R.string.desk_3,
R.string.desk_4,
R.string.desk_5
};
// list color bg
int[] list_bg = {
getResources().getColor(R.color.blue),
getResources().getColor(R.color.white),
getResources().getColor(R.color.blue),
getResources().getColor(R.color.white),
getResources().getColor(R.color.blue)
};
#Override
public int getCount() {
return list_judul.length;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return (view == object);
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
inflater = (LayoutInflater) context.getSystemService(LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.item_layout,container,false);
LinearLayout linearLayout = view.findViewById(R.id.item_layout);
ImageView imageView = view.findViewById(R.id.img);
TextView judul = view.findViewById(R.id.judul);
TextView desk = view.findViewById(R.id.deskripsi);
linearLayout.setBackgroundColor(list_bg[position]);
imageView.setImageResource(list_img[position]);
judul.setText(list_judul[position]);
desk.setText(list_desk[position]);
container.addView(view);
return view;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((LinearLayout)object);
}
}
The xml:
<LinearLayout
android:id="#+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:background="#color/white"
android:backgroundTint="#color/remain_black"
android:gravity="center_vertical"
android:orientation="horizontal"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="#+id/imageBackMorning"
android:layout_width="50dp"
android:layout_height="45dp"
android:paddingLeft="0sp"
android:paddingTop="10sp"
android:scaleX="0.9"
android:scaleY="0.9"
android:src="#drawable/white_arrow_back_24"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</LinearLayout>
<androidx.viewpager.widget.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="#dimen/_40sdp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/linearLayout"></androidx.viewpager.widget.ViewPager>
<TextView
android:id="#+id/countdownText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="01:00"
android:textColor="#color/red"
android:textSize="40sp"
android:layout_marginBottom="#dimen/_8sdp"
app:layout_constraintBottom_toTopOf="#+id/countdownButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="#+id/countdownButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:scaleX="1.2"
android:scaleY="1.2"
android:backgroundTint="#color/red"
android:text="Start"
android:src="#drawable/play"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginBottom="#dimen/_50sdp"/>
<Button
android:id="#+id/prev"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:onClick="prev"
android:text="prev"
android:backgroundTint="#color/red"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="#+id/next"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:onClick="next"
android:text="next"
android:backgroundTint="#color/red"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
Screenshot:
Thank you in advance.
making the Viewpager go to the next page after the timer is finished
When your countdown timer has fired, it'll call onFinish(), so you could just call set next index in there.
private void startTimer() {
countdownTimer = new CountDownTimer(timeLeft, 1000) {
#Override
public void onTick(long l) {
timeLeft = l;
update();
}
#Override
public void onFinish() {
// do something in here, like
viewPager.setCurrentItem(viewPager.getCurrentItem() + 1, true);
// think about what would happen if currently on the last page?
// go back to 0, stop? reverse maybe?
}
}.start();
countdownButton.setText("Pause");
timerRunning = true;
}
resume the timer when the page is opened
Do you mean that there will be a separate timer for each page? In this case you'll need to think about how to retain the timer value for each page individually. (Think about what happens when a page changes, and how you've gone about keeping resources and strings for each page.) Then when each page changes, pull out the correct value for the selected page and resume the timer from there.
I am developing in Android Canvas.
But the onDraw() has not called after invalidate();
In the layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.wen.MainActivity">
<com.wen.Drawpath_view
android:id="#+id/view_path"
android:layout_weight="0.7"
android:layout_width="match_parent"
android:layout_height="0dp"/>
<RelativeLayout
android:layout_weight="0.3"
android:layout_width="match_parent"
android:layout_height="0dp">
<Button
android:id="#+id/test"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
</LinearLayout>
In the MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private static final String TAG = "MainActivity";
private Drawpath_view View_path;
private Button test_btn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
View_path = findViewById(R.id.view_path);
View_path = new Drawpath_view(MainActivity.this);
test_btn = findViewById(R.id.test);
test_btn.setOnClickListener(this);
View_path.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
#Override
public boolean onPreDraw() {
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
View_path.getViewTreeObserver().removeOnPreDrawListener(this);
View_path.setMinimumHeight(View_path.getHeight());
View_path.setMinimumWidth(View_path.getWidth());
return true;
}
});
}
#Override
public void onClick(View v) {
if (v.getId() == R.id.test){
View_path.Testdraw();
}
}
}
In the customer View.
public class Drawpath_view extends View {
private static final String TAG = "view";
private Paint paint;
private Path path = new Path();
public Drawpath_view(Context context) {
super(context);
setWillNotDraw(false);
initView();
}
public Drawpath_view(Context context, AttributeSet attrs) {
super(context, attrs);
}
private void initView() {
paint = new Paint();
paint.setAntiAlias(true);
paint.setDither(true);
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.GREEN);
paint.setStrokeWidth(3);
}
public void Testdraw(){
Log.d(TAG,"draw");
path.moveTo(60,60);
path.lineTo(460,460);
invalidate();
}
#Override
protected void onDraw(Canvas canvas) {
Log.d(TAG,"onDraw");
super.onDraw(canvas);
canvas.drawPath(path,paint);
}
}
When I click the button in Activity. It will call
View_path.Testdraw();
But the onDraw in Drawpath_view has not been called. Did I missing something ?
Thanks in advance.
You can remove View_path = new Drawpath_view(MainActivity.this); from your code,
as you already attached view in xml.
By default all ViewGroup sub-classes do not call their onDraw method, you will enable it by calling setWillNotDraw(false) on View_path.
Add setWillNotDraw(false); initView();
into the second constructor as well.
I have a recyclerview which shows multiple cardviews with items. In the recyclerview, I have a popup menu to delete that current cardview.
When the dataset is empty I would like to show an empty view. Something with an image and text saying "empty" I have tried some online examples. No success.
My layout is a cardview(card_view_row.xml) is a simple view with a cardview that shows a few items.
Here is my recyclerview
public class AlarmRecyclerViewAdapter extends
RecyclerView.Adapter<AlarmRecyclerViewAdapter.DataObjectHolder> {
private ArrayList<Alarm> mDataset;
private static AlarmRecyclerViewAdapter.MyClickListener myClickListener;
private AlarmDataAccess dataAccess;
private Alarm alarm;
private int switchOn = 1;
private int switchOff = 0;
private static Context context;
private PopupMenu popupMenu;
public static class DataObjectHolder extends RecyclerView.ViewHolder
implements View
.OnClickListener {
TextView label;
TextView dateTime;
TextView label2;
TextView textViewLabel;
TextView gender;
TextView daysofweek;
Switch aSwitch;
ImageView trash;
public DataObjectHolder(View itemView) {
super(itemView);
dateTime = (TextView) itemView.findViewById(R.id.textView2);
label = (TextView) itemView.findViewById(R.id.textView);
label2 =(TextView) itemView.findViewById(R.id.textView3);
aSwitch = (Switch)itemView.findViewById(R.id.switchButton);
trash = (ImageView)itemView.findViewById(R.id.imageTrash);
gender = (TextView)itemView.findViewById(R.id.textViewGender);
daysofweek = (TextView)itemView.findViewById(R.id.textViewDays);
textViewLabel = (TextView)itemView.findViewById(R.id.textViewLabel);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
myClickListener.onItemClick(getAdapterPosition(), v);
}
}
public void setOnItemClickListener(AlarmRecyclerViewAdapter.MyClickListener myClickListener) {
this.myClickListener = myClickListener;
}
public AlarmRecyclerViewAdapter(ArrayList<Alarm> myDataset, Context context2) {
mDataset = myDataset;
context = context2;
}
#Override
public AlarmRecyclerViewAdapter.DataObjectHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_view_row, parent, false);
AlarmRecyclerViewAdapter.DataObjectHolder dataObjectHolder = new AlarmRecyclerViewAdapter.DataObjectHolder(view);
return dataObjectHolder;
}
#Override
public void onBindViewHolder(final AlarmRecyclerViewAdapter.DataObjectHolder holder, final int position) {
boolean status = false;
int gender;
alarm = new Alarm();
dataAccess = new AlarmDataAccess(context);
dataAccess.open();
holder.label.setText(mDataset.get(position).getHourOfDay() + ":" + mDataset.get(position).getMinute() + " " + mDataset.get(position).getTimeSet());
holder.textViewLabel.setText(mDataset.get(position).getLabel());
gender = mDataset.get(position).getGender();
if(gender == 0){
holder.gender.setText("Male voice");
}else{
holder.gender.setText("Female voice");
}
holder.daysofweek.setText(mDataset.get(position).getDays());
holder.label2.setText("" + mDataset.get(position).getAffirmationName());
holder.trash.setImageResource(R.drawable.menu2);
if( mDataset.get(position).getStatus() == 0){
status = false;
}else {
status = true;
}
holder.aSwitch.setChecked(status);
holder.aSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (buttonView.isPressed()) {
if (isChecked) {
mDataset.get(position).setStatus(switchOn);
} else {
mDataset.get(position).setStatus(switchOff);
}
alarm.setId(mDataset.get(position).getId());
alarm.setStatus(mDataset.get(position).getStatus());
dataAccess.updateStatus(alarm);
}
}
});
holder.trash.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
popupMenu = new PopupMenu(AlarmRecyclerViewAdapter.context, v);
popupMenu.inflate(R.menu.popup_menu);
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.edit:
long selectedAlarmId = mDataset.get(position).getId();
Intent intent = new Intent(AlarmRecyclerViewAdapter.context, EditAlarmActivity.class);
intent.putExtra("id", selectedAlarmId);
intent.putExtra("Edit", "FromEdit");
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);
AlarmRecyclerViewAdapter.context.startActivity(intent);
return true;
case R.id.delete:
long id = mDataset.get(position).getId();
mDataset.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, mDataset.size());
dataAccess.deleteAlarm(id);
return true;
}
return false;
}
});
popupMenu.show();
}
});
}
public void deleteItem(int index) {
mDataset.remove(index);
notifyItemRemoved(index);
}
#Override
public int getItemCount() {
return mDataset.size();
}
}
My recyclerview is inside a fragment view
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/fragment_place">
<ImageButton
android:id="#+id/add_button"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="end|bottom"
android:tint="#color/icon"
android:elevation="12dp"
android:background="#drawable/oval_ripple"
tools:backgroundTint="#96ceb4"
android:src="#android:drawable/ic_input_add"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:layout_marginStart="12dp"
android:layout_marginTop="14dp" />
<android.support.v7.widget.RecyclerView
android:id="#+id/my_recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical"
android:layout_below="#+id/add_button"
android:layout_centerHorizontal="true"
android:layout_marginTop="16dp" />
</RelativeLayout>
Is there a way to detect if the data set is empty to show an empty view with text saying empty or something? I need this done inside recyclerview since I am deleting items inside there.
EDIT
I finally figured out how to do it. I am posting this incase anyone else has the same problem.
http://akbaribrahim.com/empty-view-for-androids-recyclerview/
For my personal use I use this trick :
I use two LinearLayout, one with my RecyclerView and another with a simple TextView saying "Empty". Both are in the same parent view.
<LinearLayout
android:id="#+id/linearContent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:visibility="invisible">
<android.support.v7.widget.RecyclerView
android:id="#+id/my_recycler_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:scrollbars="vertical" />
</LinearLayout>
<LinearLayout
android:id="#+id/linearEmpty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/textEmpty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="30dp"
android:text="#string/dialog_no_result"
android:textColor="#color/cardview_dark_background" />
</LinearLayout>
And when I update my list of item I call this method :
if (linearContent != null && linearEmpty != null) {
if (mListItems.isEmpty()) {
linearContent.setVisibility(View.GONE);
linearEmpty.setVisibility(View.VISIBLE);
textEmpty.setVisibility(View.VISIBLE);
} else {
linearContent.setVisibility(View.VISIBLE);
linearEmpty.setVisibility(View.GONE);
textEmpty.setVisibility(View.GONE);
}
}
Then I use the same layout, but just change the visibility of some objects.
Hope it help.
I have a fragment where when an item of the list is clicked, you can determine which position using onListItemClick. Now I have a button on each list item (a delete button) and I want to know which position was clicked when it is pressed. How can I do this? it seems like the onClick method for the button has to be in a different Activity so I don't know how I can know which position of it was clicked. Here is the fragment code:
public class MapListFragment extends ListFragment implements
LoaderManager.LoaderCallbacks<Cursor> {
private static final int LOADER_ID = 1;
private static final String[] FROM = { Database.Maps.DATA,
Database.Maps.NAME };
private static final String[] CURSOR_COLUMNS = { Database.Maps.ID,
Database.Maps.DATA, Database.Maps.NAME };
private static final int[] TO = { R.id.li_map_image, R.id.li_map_name };
private SimpleCursorAdapter mAdapter;
// FIXME isn't this unnecessary?
public MapListFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// FIXME reverse the order so the newest sessions are at the top
mAdapter = new SimpleCursorAdapter(getActivity(),
R.layout.map_list_item, null, FROM, TO, 0);
mAdapter.setViewBinder(new SimpleCursorAdapter.ViewBinder() {
#Override
public boolean setViewValue(View view, Cursor cursor,
int columnIndex) {
if (view.getId() == R.id.li_map_image) {
((ImageView) view).setImageURI(Uri.parse(cursor
.getString(columnIndex)));
return true;
}
return false;
}
});
setListAdapter(mAdapter);
getLoaderManager().initLoader(LOADER_ID, null, this);
}
#Override
public void onListItemClick(ListView list, View v, int position, long id) {
final Intent nextIntent = new Intent(getActivity(),
ViewMapActivity.class);
nextIntent.putExtra(Utils.Constants.MAP_ID_EXTRA, id);
startActivity(nextIntent);
}
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return new CursorLoader(getActivity(), DataProvider.MAPS_URI,
CURSOR_COLUMNS, null, null, null);
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
if (loader.getId() == LOADER_ID)
mAdapter.swapCursor(cursor);
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
mAdapter.swapCursor(null);
}
}
and the XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp"
android:descendantFocusability="blocksDescendants"
android:orientation="horizontal" >
<ImageView
android:id="#+id/li_map_image"
android:layout_width="50dp"
android:layout_height="match_parent"
android:contentDescription="thumbnail" />
<TextView
android:id="#+id/li_map_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:paddingLeft="8dp"
android:textSize="16sp" />
<ImageButton
android:layout_width="60dp"
android:layout_height="match_parent"
android:id="#+id/delete"
android:focusableInTouchMode="true"
android:background="#drawable/red_x"
android:layout_gravity="center|left"
android:onClick="deleteMap"/>
</LinearLayout>
You should be able to get the parent of the ImageButton inside the ImageButton click handler. Assuming you add each button listener inside the list item creation for the adapter
ImageButton btn_image = (ImageButton) itemview.findViewById(R.id.delete);
btn_image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
View parentItem = view.getParent();
}
});
Where itemview is the inflated view in the getView method of your list adapter.
You have a rather complicated need for an simple adapter. Take a look at this tutorial http://www.vogella.com/tutorials/AndroidListView/article.html#adapterown where he walks you through making your own custom adapter. You'll see the "getView" method inside the custom list view adapter. This is where you setup each list item and would add the button.
First you can put a hidden field in the list item so that when you click. From the view you can find this field (id) and get its value.