im newbie here... I have a problem in getting the item count on my recyclerview? I've try this code but it's not working.
int count = 0;
if (recyclerViewInstance.getAdapter() != null) {
count = recyclerViewInstance.getAdapter().getItemCount();
}
also this one but it's not working too..
int count = 0;
if (mAdapter != null) {
count = mAdapter.getItemCount();
}
this is my code:
mainActivity:
private List<NavDrawerFleetGetterSetter> navList= new ArrayList<>();
private RecyclerView recyclerView;
private NavDrawerFleetAdapter mAdapter;
Button add;
TextView successCount;
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_nav_drawer_fleet);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
add = findViewById(R.id.fab);
successCount=findViewById(R.id.count);
recyclerView =findViewById(R.id.nav_sent);
mAdapter = new NavDrawerFleetAdapter(navList);
RecyclerView.LayoutManager mLayoutManager = new
LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setAdapter(mAdapter);
if (recyclerView.getAdapter() != null) {
successCount.getText(recyclerViewInstance.getAdapter().getItemCount());
}
add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
NavDrawerFleetGetterSetter navD= new
NavDrawerFleetGetterSetter(lati,longi,dateTime);
navList.add(navD);
mAdapter.notifyDataSetChanged();
}
myGetterSetter:
public class NotSentModuleGetterSetter {
String lat,lon,dateTime;
public NotSentModuleGetterSetter(String lat, String lon, String dateTime) {
this.lat = lat;
this.lon = lon;
this.dateTime = dateTime;
}
public String getLat() {
return lat;
}
public void setLat(String lat) {
this.lat = lat;
}
public String getLon() {
return lon;
}
public void setLon(String lon) {
this.lon = lon;
}
public String getDateTime() {
return dateTime;
}
public void setDateTime(String dateTime) {
this.dateTime = dateTime;
}
}
myOutput:
as you see, the success count was turned into zero.
btw, my data was getting on my database and i was pickup the code need since i have a bunch of codes as for now for my project.
an also, using debug, the data of my mAdapter=null.
In this case, i was getting the count data on my adapter but it should be get the "Size" of adapter than getting the "count". It is now working on me. :)
Related
Currently I am displaying a random image using math.random, this part works but I need to check if the users selection from the dropdown list matches this. The only part I can get to work is the incorrect selection displaying the correct name of the car displayed.
My comparison function never becomes true as Im not sure how to compare the tag of the imageview with a random int
See below my activity
public class IdentifyTheBrandActivity extends AppCompatActivity implements AdapterView.OnItemClickListener,
AdapterView.OnItemSelectedListener { String[] Brands = { "Audi", "Bentley", "BMW" };
Button SubmitButton;
ImageView imageView;
int[] images;
int chosenCar;
int locationOfCorrectAnswer;
String[] answers = new String[3];
ArrayList<String> carBrands = new ArrayList<>();
public void brandChosen(View view) {
if (imageView.getTag().toString().equals(carBrands.get(locationOfCorrectAnswer))){
Toast.makeText(getApplicationContext(), "Correct", Toast.LENGTH_LONG).show();
}else{
Toast.makeText(getApplicationContext(), "Wrong it was " + carBrands.get(locationOfCorrectAnswer), Toast.LENGTH_LONG).show();
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_identify_the_brand);
imageView = findViewById(R.id.RandomImage);
imageView.setTag("bg");
carBrands.add("Audi");
carBrands.add("Bentley");
carBrands.add("BMW");
images = new int[]{R.drawable.audi_a3_2010_27_17_200_20_4_77_56_169_21_fwd_5_4_4dr_igm, R.drawable.bentley_bentayga_2017_229_21_600_60_12_78_68_202_12_awd_5_4_suv_cce,
R.drawable.bmw_6_series_2014_82_18_310_30_6_74_53_192_20_rwd_4_2_convertible_mua};
imageView.setTag(R.drawable.audi_a3_2010_27_17_200_20_4_77_56_169_21_fwd_5_4_4dr_igm);
imageView.setTag(R.drawable.bentley_bentayga_2017_229_21_600_60_12_78_68_202_12_awd_5_4_suv_cce);
imageView.setTag(R.drawable.bmw_6_series_2014_82_18_310_30_6_74_53_192_20_rwd_4_2_convertible_mua);
if (imageView.getTag() != null) {
int resourceID = (int) imageView.getTag();
}
Random random = new Random();
chosenCar = random.nextInt(3);
locationOfCorrectAnswer = chosenCar;
imageView.setBackgroundResource(images[chosenCar]);
int incorrectAnswerLocation;
//Get a random between 0 and images.length-1
//int imageId = (int) (Math.random() * images.length);
Spinner spin = (Spinner) findViewById(R.id.spinner);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_item, Brands);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spin.setAdapter(adapter);
spin.setOnItemSelectedListener(this);
}
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
}
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long l) {
Toast.makeText(getApplicationContext(), "Selected Brand: " + Brands[position]
,Toast.LENGTH_SHORT).show();
}
#Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
}
I tried comparing the imageview and the randomly assigned index to the array but it never becomes true
Essentially my issue is how to compare which drawable is actively in the imageview with the users selection
I am making a networking app's chat section from this tutorial: https://blog.sendbird.com/android-chat-tutorial-building-a-messaging-ui.
I have everything hooked up so that I know that the messages are coming in from the database. It seems to be an issue with how the adapter or recyclerview are set up. I can't see any messages on my activity even though I can see them if I poke in my async/background worker.
This is the adapter class with inner view holders from the tutorial, adapted to my needs:
public class MessageListAdapter extends RecyclerView.Adapter {
private static final int VIEW_TYPE_MESSAGE_SENT = 1;
private static final int VIEW_TYPE_MESSAGE_RECEIVED = 2;
private Activity mContext;
private ArrayList<Message> mMessageList;
public MessageListAdapter(Activity context, ArrayList<Message> messageList) {
mContext = context;
mMessageList = messageList;
}
#Override
public int getItemCount() {
return mMessageList.size();
}
// Determines the appropriate ViewType according to the sender of the message.
#Override
public int getItemViewType(int position) {
Message message = (Message) mMessageList.get(position);
if (message.isOther() == "2") {
// If the current user is the sender of the message
return VIEW_TYPE_MESSAGE_SENT;
} else {
// If some other user sent the message
return VIEW_TYPE_MESSAGE_RECEIVED;
}
}
// Inflates the appropriate layout according to the ViewType.
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view;
if (viewType == VIEW_TYPE_MESSAGE_SENT) {
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_message_sent, parent, false);
return new SentMessageHolder(view);
} else if (viewType == VIEW_TYPE_MESSAGE_RECEIVED) {
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_message_received, parent, false);
return new ReceivedMessageHolder(view);
}
return null;
}
// Passes the message object to a ViewHolder so that the contents can be bound to UI.
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
Message message = mMessageList.get(position);
switch (holder.getItemViewType()) {
case VIEW_TYPE_MESSAGE_SENT:
((SentMessageHolder) holder).bind(message);
break;
case VIEW_TYPE_MESSAGE_RECEIVED:
((ReceivedMessageHolder) holder).bind(message);
}
}
private class SentMessageHolder extends RecyclerView.ViewHolder {
TextView messageText, timeText;
SentMessageHolder(View itemView) {
super(itemView);
messageText = (TextView) itemView.findViewById(R.id.text_message_body);
timeText = (TextView) itemView.findViewById(R.id.text_message_time);
}
void bind(Message message) {
messageText.setText(message.getMessage());
// Format the stored timestamp into a readable String using method.
timeText.setText(message.getCreatedAt());
}
}
private class ReceivedMessageHolder extends RecyclerView.ViewHolder {
TextView messageText, timeText, nameText;
ImageView profileImage;
ReceivedMessageHolder(View itemView) {
super(itemView);
messageText = (TextView) itemView.findViewById(R.id.text_message_body);
timeText = (TextView) itemView.findViewById(R.id.text_message_time);
nameText = (TextView) itemView.findViewById(R.id.text_message_name);
profileImage = (ImageView) itemView.findViewById(R.id.image_message_profile);
}
void bind(Message message) {
messageText.setText(message.getMessage());
// Format the stored timestamp into a readable String using method.
timeText.setText(message.getCreatedAt());
nameText.setText(message.getSender());
Picasso.get().load(message.getProfile())
.transform(new RoundedCornersTransformation(150, 0)).into(profileImage);
// Insert the profile image from the URL into the ImageView.
// Utils.displayRoundImageFromUrl(mContext, message.getSender().getProfileUrl(), profileImage);
}
}
}
I create the adapter and pair it to the recyclerview in a background worker during postExecute()
try {
JSONArray messages = new JSONArray(s);
ArrayList<Message> messageList = new ArrayList<Message>();
for (int i = 0; i < messages.length(); i++) {
String currentMessage = (String) messages.get(i);
String[] fields = currentMessage.split(",", 0);
if (fields.length == 5) {
String isOther = fields[0];
String messageText = fields[1];
String dateTime = fields[2];
String author = fields[3];
String pictureLocation = fields[4];
Message newMessage = new Message(isOther, messageText, dateTime, author, pictureLocation);
messageList.add(newMessage);
}
}
mMessageRecycler = (RecyclerView) ha.findViewById(R.id.reyclerview_message_list);
mMessageRecycler.setLayoutManager(new LinearLayoutManager(ha.getApplicationContext()));
mMessageAdapter = new MessageListAdapter(ha, messageList);
mMessageRecycler.setAdapter(mMessageAdapter);
}
I've tried adding alert dialogs to debug within the OnCreateViewHolder, but can't get them to appear. I've tried using ha, ha.getApplicationContext() on every field. There must be something that's just staring me in the face. I've used this pattern before and it works for another section of my app.
It turns out that the tutorial's recyclerview information is just barely off, so I used the one I had in a previous part of the app:
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFFFFF" />
I am trying to use MvxRecyclerView. I have directly binded the ItemSource from the ViewModel and its redering the list. But i want the ListItemDivider in between,. So i made a custom ItemDecorator and used it with the recycler view. Its working for andorid 7.0 but not for marshmallow. I m not using any Holder, LinearLayoutManager or Adapter separately for the MvxRecyclerView.Please find the code below
Activity class
//****************************************************************************//
[Activity(Label = "EmployeeHub", Theme = "#style/MaterialTheme", ScreenOrientation = AndroidSystem.Content.PM.ScreenOrientation.Portrait)]
public class EmployeeHub : BaseView
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.EmployeeHub);
var reclycleView = this.FindViewById<MvxRecyclerView>(Resource.Id.my_recycler_view);
AndroidSystem.Support.V7.Widget.RecyclerView.ItemDecoration dividerItemDecoration = new DividerItemDecoration(this.ApplicationContext);
reclycleView.AddItemDecoration(dividerItemDecoration);
}
}
ItemDecorator
//********************************************************************//
public class DividerItemDecoration : RecyclerView.ItemDecoration
{
private AndroidSystem.Graphics.Drawables.Drawable divider;
private int[] attributes = new int[] {Attribute.ListDivider };
public DividerItemDecoration(Context context)
{
divider = context.GetDrawable(Resource.Drawable.noBorder);
TypedArray ta = context.ObtainStyledAttributes(attributes);
divider = ta.GetDrawable(0);
ta.Recycle();
}
public override void GetItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state)
{
if (parent.GetChildAdapterPosition(view) == 0)
{
return;
}
outRect.Top = divider.IntrinsicHeight;
}
public override void OnDraw(Canvas c, RecyclerView parent, RecyclerView.State state)
{
int left = parent.PaddingLeft;
int right = parent.Width - parent.PaddingRight;
for (int i = 0; i < parent.ChildCount; i++)
{
View child = parent.GetChildAt(i);
var parameters = child.LayoutParameters.JavaCast<RecyclerView.LayoutParams>();
int top = child.Bottom + parameters.BottomMargin;
int bottom = top + divider.IntrinsicHeight;
divider.SetBounds(left, top, right, bottom);
divider.Draw(c);
}
}
}
// layout **********************************************//
<MvxRecyclerView
android:id="#+id/my_recycler_view"
android:layout_below="#+id/hlhrview1"
android:scrollbars="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
local:MvxItemTemplate="#layout/employee_item_template"
local:MvxBind="ItemsSource Employees; ItemClick SelectedEmployee" />
I also had a problem getting this to work. With a tip from here and a few modifications to your code, I was able to get it working. Specifically, I am using the OnDrawOver as opposed to OnDraw
Here is my modified DividerItemDecoration:
public class DividerItemDecoration : RecyclerView.ItemDecoration
{
private readonly Drawable _divider;
public DividerItemDecoration(Context context)
{
_divider = ResourcesCompat.GetDrawable(context.Resources, Resource.Drawable.recyclerview_line_divider, context.Theme);
}
public override void OnDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state)
{
var left = parent.PaddingLeft;
var right = parent.Width - parent.PaddingRight;
for (var i = 0; i < parent.ChildCount; i++)
{
var child = parent.GetChildAt(i);
var parameters = child.LayoutParameters.JavaCast<RecyclerView.LayoutParams>();
var top = child.Bottom + parameters.BottomMargin;
var bottom = top + _divider.IntrinsicHeight;
_divider.SetBounds(left, top, right, bottom);
_divider.Draw(c);
}
}
}
I also put the binding code in my OnCreateView like this:
var reclycleView = _payformView.FindViewById<MvxRecyclerView>(Resource.Id.my_recycler_view);
RecyclerView.ItemDecoration dividerItemDecoration = new DividerItemDecoration(Application.Context);
reclycleView.AddItemDecoration(dividerItemDecoration);
All this is on a KitKat device.
I am trying to display different date in different TextViews in a fragment following the answer of MH to this question at TimePicker onTimeSet not being called but I am not getting the same results for a fragment.
I have added a separate DatePickerFragment class in which I am using an Interface class which is used as a callback method and is defined in a fragment class Medication.
How do I set multiple date pickers in a fragment?
The DatePickerFragment is written as:
public class DatePickerFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener {
private int mId;
DatePickerDialogListener mListener;
protected static DatePickerFragment newInstance(int id) {
Bundle args = new Bundle();
args.putInt("picker_id", id);
DatePickerFragment fragment = new DatePickerFragment();
fragment.setArguments(args);
return fragment;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// ... omitted
final Calendar c = Calendar.getInstance();
int mDay = c.get(Calendar.DAY_OF_MONTH);
int mMonth = c.get(Calendar.MONTH);
int mYear = c.get(Calendar.YEAR);
mId = getArguments().getInt("picker_id");
mListener = getActivity() instanceof DatePickerFragment.DatePickerDialogListener ? (DatePickerFragment.DatePickerDialogListener) getActivity() : null;
// Create a new instance of TimePickerDialog and return it
return new DatePickerDialog(getActivity(), this, mYear, mMonth, mDay);
}
#Override
public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
if (mListener != null) mListener.onDateSet(mId, view, year, month, dayOfMonth);
}
public static interface DatePickerDialogListener {
public void onDateSet(int id, DatePicker view, int year, int month, int dayOfMonth);
}
}
The Fragment class Medication which would use this datepickerdialog has the following code:
public class Medication extends Fragment implements DatePickerFragment.DatePickerDialogListener {
private static final int FIRST_VISIT_ID = 1;
private static final int SECOND_VISIT_ID = 2;
private static final int THIRD_VISIT_ID = 3;
private int mYear;
private int mMonth;
private int mDay;
protected static TextView date1;
protected static TextView date2;
protected static TextView date3;
public Medication() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_medication, container, false);
final Calendar c = Calendar.getInstance();
mYear = c.get(Calendar.YEAR);
mMonth = c.get(Calendar.MONTH);
mDay = c.get(Calendar.DAY_OF_MONTH);
date1 =(TextView) view.findViewById(R.id.visit_date1);
date2 =(TextView) view.findViewById(R.id.visit_date2);
date3 =(TextView) view.findViewById(R.id.visit_date3);
date1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
DialogFragment newFragment = DatePickerFragment.newInstance(FIRST_VISIT_ID);
newFragment.show(getFragmentManager(), "timePicker");
}
});
date2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
DialogFragment newFragment = DatePickerFragment.newInstance(SECOND_VISIT_ID);
newFragment.show(getFragmentManager(), "timePicker");
}
});
date3.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
DialogFragment newFragment = DatePickerFragment.newInstance(THIRD_VISIT_ID);
newFragment.show(getFragmentManager(), "timePicker");
}
});
date1.setText(
new StringBuilder()
// Month is 0 based so add 1
.append(mDay).append("/")
.append(mMonth + 1).append("/")
.append(mYear).append(" "));
date2.setText(
new StringBuilder()
// Month is 0 based so add 1
.append(mDay).append("/")
.append(mMonth + 1).append("/")
.append(mYear).append(" "));
date3.setText(
new StringBuilder()
// Month is 0 based so add 1
.append(mDay).append("/")
.append(mMonth + 1).append("/")
.append(mYear).append(" "));
return view;
}
#Override
public void onDateSet(int id, DatePicker view, int year, int month, int dayOfMonth) {
Log.i("DatePicker", "Date picker set from id " + id + "!");
if(id == FIRST_VISIT_ID)
{
this.date1.setText(
new StringBuilder()
// Month is 0 based so add 1
.append(dayOfMonth).append("/")
.append(month + 1).append("/")
.append(year).append(" "));
}
if(id == SECOND_VISIT_ID)
{
this.date2.setText(
new StringBuilder()
// Month is 0 based so add 1
.append(dayOfMonth).append("/")
.append(month + 1).append("/")
.append(year).append(" "));
}
if(id == THIRD_VISIT_ID)
{
this.date3.setText(
new StringBuilder()
// Month is 0 based so add 1
.append(dayOfMonth).append("/")
.append(month + 1).append("/")
.append(year).append(" "));
}
}
}
I have tried this method of adding multiple pickers for Time Picker Dialog as well but the same problem occurs that onTimeSet method in Medication Class is not being called as in here onDateSet.
The problem is that the dialog opens when I click on a textView but after I change the date, the date of that textView doesn't change. Also the log info message is not shown as the onDateSet method is not being called.
Maybe the mListener is null in this case, I can only guess.
Please help me solve this problem. Thanks in advance.
Try to add some logs in onDateSet of a fragment to see what values are set there and if it calls a listener.
#Override
public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
Log.i("Fragment/onDateSet", "Date picker set from id " + mId+ "!");
if (mListener != null)
mListener.onDateSet(mId, view, year, month, dayOfMonth);
else
Log.w("Fragment/onDateSet", "But no listener available!");
}
And try to put different tags for different fragments, because right now you are marking them with the same tag
newFragment.show(getFragmentManager(), "timePicker2");
I didn't get the answer to why above code doesn't work but after some search on net I found another very useful method for adding date or time in multiple TextView. Here I am adding two dates in fragment, same technique works for activity as well.
public class Medication extends Fragment implements View.OnClickListener{
private DatePickerDialogFragment mDatePickerDialogFragment;
protected static TextView date1;
protected static TextView date2;
#Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_medication, container, false);
date1 = (TextView) view.findViewById(R.id.date1);
date2 = (TextView) view.findViewById(R.id.date2);
displayCurrentDate(); // display current date as default in date1 and date2
mDatePickerDialogFragment = new DatePickerDialogFragment();
date1.setOnClickListener(this);
date2.setOnClickListener(this);
}
public void displayCurrentDate(){
static Calendar calendar = Calendar.getInstance();
private int year = calendar.get(Calendar.YEAR); // get current year
private int month = calendar.get(Calendar.MONTH);// get current month
private int day = calendar.get(Calendar.DAY_OF_MONTH); // get current day
calendar.set(year, month, day);
SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy");
// display Current Date in date1 and date2
date1.setText(format.format(calendar.getTime()));
date2.setText(format.format(calendar.getTime()));
}
#Override
public void onClick(View v) {
int id = v.getId();
if (id == R.id.date1) {
mDatePickerDialogFragment.setDateFlag(FLAG_DATE_ONE);
mDatePickerDialogFragment.show(getFragmentManager(), "datePicker1");
}else if (id == R.id.date2) {
mDatePickerDialogFragment.setDateFlag(FLAG_DATE_TWO);
mDatePickerDialogFragment.show(getFragmentManager(), "datePicker2");
}
}
public static class DatePickerDialogFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener {
protected static final int FLAG_DATE_ONE = 1;
protected static final int FLAG_DATE_TWO = 2;
private int flag = 0;
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DAY_OF_MONTH);
return new DatePickerDialog(getActivity(), this, year, month, day);
}
public void setDateFlag(int i) {
flag = i;
}
#Override
public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
Calendar calendar = Calendar.getInstance();
calendar.set(year, monthOfYear, dayOfMonth);
SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy");
if (flag == FLAG_DATE_ONE) {
date1.setText(format.format(calendar.getTime()));
} else if (flag == FLAG_DATE_TWO) {
date2.setText(format.format(calendar.getTime()));
}
}
}
}
Note: Please add android:clickable = "true" for each TextView in xml layout for enabling the click action, otherwise the TextView won't be clickable.
I hope this will help others :)
I'm trying to create a slider, when users fling left or right, this slider will slide animatedly, translation animation. However, it doesn't work in a right way.
package pete.android.study.home.scrollingindicator;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
public class MainScreen extends Activity {
protected ValueAnimator mScrollIndicatorAnimator;
protected ValueAnimator mScrollator;
protected ImageView mScrollIndicator = null;
protected static final int sScrollIndicatorFadeInDuration = 150;
protected static final int sScrollIndicatorFadeOutDuration = 650;
protected static final int sScrollIndicatorFlashDuration = 650;
public static final int PAGE_COUNT = 4;
private int mPageWidth = 0;
private int mCurrentPage = 0;
private int mIndicatorPos = 0;
private int mIndicatorSpace = 0;
private GestureDetector mGestureDetector;
private static final boolean DEBUG = true;
private static final String TAG = "indicator";
private Handler mHandler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
//ht = displaymetrics.heightPixels;
mPageWidth = displaymetrics.widthPixels;
mHandler = new Handler();
setupScrollingIndicator();
mGestureDetector = new GestureDetector(this, new LearnGestureListener());
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (mGestureDetector.onTouchEvent(event))
return true;
else
return false;
}
public void setupScrollingIndicator() {
if(mScrollIndicator == null) {
mScrollIndicator = (ImageView) findViewById(R.id.indicator);
}
mIndicatorSpace = mPageWidth / PAGE_COUNT;
mIndicatorPos = mIndicatorSpace * mCurrentPage;
if(DEBUG) {
Log.i(TAG, "mIndicatorSpace = " + mIndicatorSpace);
Log.i(TAG, "mCurrentPage = " + mCurrentPage);
Log.i(TAG, "mIndicatorPos = " + mIndicatorPos);
}
if(mScrollIndicator.getMeasuredWidth() != mIndicatorSpace) {
mScrollIndicator.getLayoutParams().width = mIndicatorSpace;
mScrollIndicator.requestLayout();
}
mScrollIndicator.setTranslationX(mIndicatorPos);
mScrollIndicator.invalidate();
}
public void showIndicator() {
setupScrollingIndicator();
mScrollIndicator.setVisibility(View.VISIBLE);
cancelScrollingAnimations();
mScrollIndicatorAnimator = ObjectAnimator.ofFloat(mScrollIndicator, "alpha", 1f);
mScrollIndicatorAnimator.setDuration(sScrollIndicatorFadeInDuration);
mScrollIndicatorAnimator.start();
mScrollator = ObjectAnimator.ofFloat(mScrollIndicator, "translationX", mIndicatorPos);
mScrollator.setDuration(sScrollIndicatorFlashDuration);
mScrollator.start();
}
Runnable hideScrollingIndicatorRunnable = new Runnable() {
#Override
public void run() {
hideIndicator();
}
};
protected void flashIndicator() {
showIndicator();
mHandler.postDelayed(hideScrollingIndicatorRunnable, sScrollIndicatorFlashDuration);
}
public void hideIndicator() {
setupScrollingIndicator();
cancelScrollingAnimations();
mScrollIndicatorAnimator = ObjectAnimator.ofFloat(mScrollIndicator, "alpha", 0f);
mScrollIndicatorAnimator.setDuration(sScrollIndicatorFadeOutDuration);
mScrollIndicatorAnimator.addListener(new AnimatorListenerAdapter() {
private boolean cancelled = false;
#Override
public void onAnimationCancel(android.animation.Animator animation) {
cancelled = true;
}
#Override
public void onAnimationEnd(Animator animation) {
if (!cancelled) {
mScrollIndicator.setVisibility(View.INVISIBLE);
}
}
});
mScrollIndicatorAnimator.start();
}
public void cancelScrollingAnimations() {
if(mScrollIndicatorAnimator != null) {
mScrollIndicatorAnimator.cancel();
}
}
public void scrollToRight() {
flashIndicator();
mCurrentPage++;
if(mCurrentPage >= PAGE_COUNT) {
mCurrentPage = 0;
}
}
public void scrollToLeft() {
flashIndicator();
mCurrentPage--;
if(mCurrentPage < 0) {
mCurrentPage = PAGE_COUNT - 1;
}
}
class LearnGestureListener extends GestureDetector.SimpleOnGestureListener {
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
if(e2.getX() - e1.getX() > 50) {
scrollToLeft();
} else if(e2.getX() - e1.getX() < 50) {
scrollToRight();
}
return true;
}
}
}
Please help me fix this, thanks very much!
mScrollIndicator.setTranslationX(mIndicatorPos) just redraw your view on new position mIndicatorPos. It doesn't do animating.
If you wanna mScrollIndicator move along with your scroll event, try to override onScroll method instead of onFling.
Or another way, create an android.animation.ObjectAnimator object, setup it for your view and call ObjectAnimator.start() on Fling.