Android webview is playing video only once - java

I am using webview in android to play a video. The problem is that video is playing once. I have seen some answers about how to fix it, but still not working. Here's my code:
public class MyChromeClient extends WebChromeClient implements
OnCompletionListener, OnErrorListener {
private Activity _activity;
private VideoView mCustomVideoView;
private LinearLayout mContentView;
private FrameLayout mCustomViewContainer;
private WebChromeClient.CustomViewCallback mCustomViewCallback;
static final FrameLayout.LayoutParams COVER_SCREEN_GRAVITY_CENTER = new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.FILL_PARENT, Gravity.CENTER);
public MyChromeClient(Activity context) {
super();
_activity = context;
}
#Override
public void onShowCustomView(View view, CustomViewCallback callback) {
super.onShowCustomView(view, callback);
if (view instanceof FrameLayout) {
FrameLayout frame = (FrameLayout) view;
if (frame.getFocusedChild() instanceof VideoView) {
mCustomVideoView = (VideoView) frame.getFocusedChild();
frame.removeView(mCustomVideoView);
_activity.setContentView(mCustomVideoView);
mCustomVideoView.setOnCompletionListener(this);
mCustomVideoView.setOnErrorListener(this);
mCustomVideoView.start();
}
}
}
public void onHideCustomView() {
if (mCustomVideoView == null)
return;
// Hide the custom view.
mCustomVideoView.setVisibility(View.GONE);
// Remove the custom view from its container.
mCustomViewContainer.removeView(mCustomVideoView);
mCustomVideoView = null;
mCustomViewContainer.setVisibility(View.GONE);
mCustomVideoView.stopPlayback();
mCustomViewCallback.onCustomViewHidden();
// Show the content view.
mContentView.setVisibility(View.VISIBLE);
}
public void onCompletion(MediaPlayer mp) {
//Intent intent = new Intent(_activity, _activity.getClass());
//intent.setClass(_activity, _activity.getClass());
//_activity.startActivity(intent);
//_activity.finish();
}
public boolean onError(MediaPlayer mp, int what, int extra) {
return true;
}
}

try this
add this in show method
WebChromeClient.CustomViewCallback CustomViewCallback; mCustomViewCallback = callback;
then in hide method...
mCustomViewCallback.onCustomViewHidden(); mCustomViewCallback = null; HTML5WebView.this.goBack();
EDIT :-
public class HTML5WebView extends WebView {
static final String LOGTAG = "HTML5WebView";
private void init(Context context) {
mContext = context;
Activity a = (Activity) mContext;
mLayout = new FrameLayout(context);
mBrowserFrameLayout = (FrameLayout) LayoutInflater.from(a).inflate(R.layout.custom_screen, null);
mContentView = (FrameLayout) mBrowserFrameLayout.findViewById(R.id.main_content);
mCustomViewContainer = (FrameLayout) mBrowserFrameLayout.findViewById(R.id.fullscreen_custom_content);
mLayout.addView(mBrowserFrameLayout, COVER_SCREEN_PARAMS);
// Configure the webview
WebSettings s = getSettings();
s.setBuiltInZoomControls(true);
s.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
s.setUseWideViewPort(true);
s.setLoadWithOverviewMode(true);
s.setSaveFormData(true);
s.setJavaScriptEnabled(true);
mWebChromeClient = new MyWebChromeClient();
setWebChromeClient(mWebChromeClient);
setWebViewClient(new WebViewClient());
setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
s.setDomStorageEnabled(true);
mContentView.addView(this);
}
public HTML5WebView(Context context) {
super(context);
init(context);
}
public HTML5WebView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public HTML5WebView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
public FrameLayout getLayout() {
return mLayout;
}
public boolean inCustomView() {
return (mCustomView != null);
}
public void hideCustomView() {
mWebChromeClient.onHideCustomView();
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if ((mCustomView == null) && canGoBack()){
goBack();
return true;
}
}
return super.onKeyDown(keyCode, event);
}
private class MyWebChromeClient extends WebChromeClient {
private Bitmap mDefaultVideoPoster;
private View mVideoProgressView;
FrameLayout frame;
#Override
public void onShowCustomView(View view, WebChromeClient.CustomViewCallback callback)
{
HTML5WebView.this.setVisibility(View.GONE);
isVideoPlaying = true;
// if a view already exists then immediately terminate the new one
if (mCustomView != null) {
callback.onCustomViewHidden();
return;
}
mCustomViewContainer.addView(view);
mCustomView = view;
frame = (FrameLayout) mCustomView;
mCustomViewCallback = callback;
VideoView mVideoView;
if(frame.getFocusedChild() instanceof VideoView){
mVideoView = (VideoView) frame.getFocusedChild();
}
mCustomViewContainer.setVisibility(View.VISIBLE);
}
#Override
public void onHideCustomView() {
if (mCustomView == null)
return;
// Hide the custom view.
mCustomView.setVisibility(View.GONE);
// Remove the custom view from its container.
mCustomViewContainer.removeView(mCustomView);
mCustomView = null;
mCustomViewContainer.setVisibility(View.GONE);
mCustomViewCallback.onCustomViewHidden();
mCustomViewCallback = null;
HTML5WebView.this.setVisibility(View.VISIBLE);
HTML5WebView.this.goBack();
}
}
}

I would like to offer an alternative, it may not be perfect, but from a web programming point of view, after beating my head against this for some time, the trick was to covert the video to base64 and the feed it to the source tag (jquery in my case). If it isn't in the assets folder it can't get confuse!

Related

How do I get the view position of a clicked checkedbutton and how to set it checked based on it's position

I've been stuck for 2 days trying to solve an error
with the displayed checkboxes in my app. I've created an activity that displays list of installed apps with checkboxes on the side of each displayed app. When I click on a checkbox of a specific app e.g Facebook some of other apps' checkboxes get marked without them been clicked. I don't know why this is happening, I'll appreciate it if you help me :D. I've used a list view with array adapter to display the list of installed apps.
ArrayAdapter
public class ListofAppsAdapter extends ArrayAdapter<ApplicationInfo> {
private List<ApplicationInfo> applicationInfoList;
private Context context;
private PackageManager packageManager;
private int x = 0;
SparseBooleanArray mCheckStates;
public ListofAppsAdapter(#NonNull Context context, int resource, #NonNull List<ApplicationInfo> objects) {
super(context, resource, objects);
this.context = context;
this.applicationInfoList = objects;
packageManager = context.getPackageManager();
mCheckStates = new SparseBooleanArray(applicationInfoList.size());
}
#Override
public int getCount() {
return ((null != applicationInfoList) ? applicationInfoList.size() : 0);
}
#Nullable
#Override
public ApplicationInfo getItem(int position) {
return ((null != applicationInfoList) ? applicationInfoList.get(position) : null);
}
#Override
public long getItemId(int position) {
return position;
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
View view = convertView;
if (view == null) {
LayoutInflater layoutInflater = (LayoutInflater)
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = layoutInflater.inflate(R.layout.listsofapps_layout, null);
}
ApplicationInfo data = applicationInfoList.get(position);
if (data != null) {
ImageView app_logo = view.findViewById(R.id.appicon);
CheckBox checkBox = view.findViewById(R.id.add_app);
app_logo.setImageDrawable(data.loadIcon(packageManager));
// add_app.setText(appDetailsList.get(position).name);
checkBox.setText(data.loadLabel(packageManager));
}
//
// view.setOnClickListener(new View.OnClickListener() {
// #Override
// public void onClick(View view) {
//
// Toast.makeText(context, "Clicked JIMMY", Toast.LENGTH_SHORT).show();
//
// if (x == 4 && !add_app.isChecked()) {
// Toast.makeText(context, "You reached your limit", Toast.LENGTH_SHORT).show();
// add_app.setChecked(false);
// return;
// }
//
// if (!add_app.isChecked()) {
// x++;
// add_app.setChecked(true);
// return;
// }
//
// if (add_app.isChecked()) {
// x--;
// add_app.setChecked(false);
// return;
// }
//
// }
//
// });
return view;
}
}
The Activity
public class SelectAppsActivity extends ListActivity {
private PackageManager packageManager = null;
private List<ApplicationInfo> applist = null;
private ListofAppsAdapter listofAppsAdapter = null;
RelativeLayout goBackappsHolder, proceedappsHolder;
ListView listsofappsrecyclerview;
CharSequence packageName, app_Name;
Drawable icon;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_select_apps);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getWindow().setNavigationBarColor(getResources().getColor(R.color.darkTheme));
}
goBackappsHolder = findViewById(R.id.goBackappsHolder);
proceedappsHolder = findViewById(R.id.proceedappsHolder);
packageManager = getPackageManager();
new loadApps().execute();
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
try {
} catch (ActivityNotFoundException e) {
Toast.makeText(SelectAppsActivity.this, "" + e.getMessage(), Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Toast.makeText(SelectAppsActivity.this, "" + e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
private List<ApplicationInfo> checkForLaunchIntent(List<ApplicationInfo> installedApplications) {
ArrayList<ApplicationInfo> appList = new ArrayList<ApplicationInfo>();
for (ApplicationInfo info : installedApplications) {
try {
if (packageManager.getLaunchIntentForPackage(info.packageName) != null) {
appList.add(info);
}
} catch (Exception e) {
e.printStackTrace();
}
}
return appList;
}
private class loadApps extends AsyncTask<Void, Void, Void> {
private ProgressDialog progressDialog = null;
#Override
protected Void doInBackground(Void... voids) {
applist = checkForLaunchIntent(packageManager.getInstalledApplications(PackageManager.GET_META_DATA));
listofAppsAdapter = new ListofAppsAdapter(SelectAppsActivity.this, R.layout.listsofapps_layout, applist);
return null;
}
#Override
protected void onPostExecute(Void unused) {
setListAdapter(listofAppsAdapter);
progressDialog.dismiss();
super.onPostExecute(unused);
}
#Override
protected void onPreExecute() {
progressDialog = ProgressDialog.show(SelectAppsActivity.this, null, "Loading app info...");
super.onPreExecute();
}
}
}
I now known how to solve it. Override the following methods.
#Override
public int getViewTypeCount() {
return getCount();
}
#Override
public int getItemViewType(int position) {
return position;
}

Android RecyclerView fails to render a SurfaceView (SOLVED)

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

Listener always null in custom view class

I have this structure:
Activity -> RecyclerView Adapter -> Custom View
Here is my code (with some parts left out for clarity).
My activity, MainActivity.java:
public class MainActivity extends AppCompatActivity {
private final String TAG = "MainActivity";
private EditText textField;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
if (toolbar != null) {
setSupportActionBar(toolbar);
}
textField = (EditText) findViewById(R.id.textField);
// Adapter code
}
}
My adapter, MyAdapter.java:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private static final String TAG = "MyAdapter";
private Context context;
public MyAdapter(Context context) {
this.context = context;
}
public class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View v) {
super(v);
}
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
CustomView customView = new CustomView(context);
customView.setCustomViewListener(new CustomView.CustomViewListener() {
#Override
public void onEventComplete() {
Log.d(TAG, "EVENT COMPLETE");
}
});
ViewHolder viewHolder = new ViewHolder(customView);
return viewHolder;
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
//
}
// other methods
}
And my custom view, CustomView.java:
public class CustomView extends RelativeLayout {
private final String TAG = "CustomView";
private CustomViewListener mListener = null;
private RelativeLayout mLayout;
private ImageView mPicture;
public CustomView(Context context) {
super(context);
init();
}
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public interface CustomViewListener {
void onEventComplete();
}
public void setCustomViewListener(CustomViewListener listener) {
this.mListener = listener;
}
private void init() {
inflate(getContext(), R.layout.item_layout, this);
this.mLayout = (RelativeLayout) findViewById(R.id.layout);
this.mPicture = (ImageView) findViewById(R.id.picture);
mPicture.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (mListener != null) {
mListener.onEventComplete();
}
}
});
}
}
But for some reason, the listener is always null, so the onEventComplete() is never actually called.
Why is it always null?
I think your custom view should be like below, I am not sure. but you can try like below.
private void init() {
View view=inflate(R.layout.item_layout, null);
this.mLayout = (RelativeLayout)view. findViewById(R.id.layout);
this.mPicture = (ImageView)view. findViewById(R.id.picture);
this.mPicture.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mListener != null) {
mListener.onEventComplete();
}
}
});
addView(view);
}
UPDATE
create your custom view as xml file named customview and give try.
R.layout.customview
<com.yourpackage.customview
layout_height="match_parent"
layout_width="match_parent"/>
And do following in your adapter onCreateViewHolder(...) method
View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.customview, parent, false)
return new MyViewHolder(view);

Using onClick() defined in separate class in ViewHolder

I have a RecyclerView holding CardViews with a favorite button within each card. I would like the favorite button to only be clicked for each specific card. I am currently using a ViewHolder to maintain each of the components in each card and the favorite button is one of those components.
How can I use an onClick() defined in a separate class within the ViewHolder?
Using this code currently only actives the onTouchEvent() for the favoriteButton
viewHolder.favoriteButton.setOnClickListener(new LikeButtonView(mContext));
AppAdapter.java
public class AppAdapter extends RecyclerView.Adapter<AppAdapter.ViewHolder> {
PackageManager packageManager;
private List<App> apps;
private int rowLayout;
private Context mContext;
public AppAdapter(List<App> apps, int rowLayout, Context context) {
this.apps = apps;
this.rowLayout = rowLayout;
this.mContext = context;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
packageManager = this.mContext.getPackageManager();
View v = LayoutInflater.from(viewGroup.getContext()).inflate(rowLayout, viewGroup, false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {
App appObject = apps.get(i);
viewHolder.appName.setText(appObject.getApplicationName());
viewHolder.versionNumber.setText(String.valueOf(appObject.getVersionNumber()));
viewHolder.updateDate.setText(String.valueOf(appObject.getLastUdpateTime()));
viewHolder.appIcon.setImageDrawable(appObject.getAppIcon());
viewHolder.appChangelog.setText(appObject.getChangelogText());
viewHolder.favoriteButton.setOnClickListener(new LikeButtonView(mContext));
}
LikeButtonView.java
public class LikeButtonView extends FrameLayout implements View.OnClickListener {
private static final DecelerateInterpolator DECCELERATE_INTERPOLATOR = new DecelerateInterpolator();
private static final AccelerateDecelerateInterpolator ACCELERATE_DECELERATE_INTERPOLATOR = new AccelerateDecelerateInterpolator();
private static final OvershootInterpolator OVERSHOOT_INTERPOLATOR = new OvershootInterpolator(4);
#Bind(R.id.ivStar)
ImageView ivStar;
private boolean isChecked;
private AnimatorSet animatorSet;
public LikeButtonView(Context context) {
super(context);
init();
}
public LikeButtonView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public LikeButtonView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public LikeButtonView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
private void init() {
LayoutInflater.from(getContext()).inflate(R.layout.view_like_button, this, true);
ButterKnife.bind(this);
setOnClickListener(this);
}
#Override
public void onClick(View v) {
isChecked = !isChecked;
ivStar.setImageResource(isChecked ? R.drawable.ic_star_rate_on : R.drawable.ic_star_rate_off);
if (animatorSet != null) {
animatorSet.cancel();
}
if (isChecked) {
ivStar.animate().cancel();
ivStar.setScaleX(0);
ivStar.setScaleY(0);
animatorSet = new AnimatorSet();
ObjectAnimator starScaleYAnimator = ObjectAnimator.ofFloat(ivStar, ImageView.SCALE_Y, 0.2f, 1f);
starScaleYAnimator.setDuration(350);
starScaleYAnimator.setStartDelay(0);
starScaleYAnimator.setInterpolator(OVERSHOOT_INTERPOLATOR);
ObjectAnimator starScaleXAnimator = ObjectAnimator.ofFloat(ivStar, ImageView.SCALE_X, 0.2f, 1f);
starScaleXAnimator.setDuration(350);
starScaleXAnimator.setStartDelay(0);
starScaleXAnimator.setInterpolator(OVERSHOOT_INTERPOLATOR);
animatorSet.playTogether(
starScaleYAnimator,
starScaleXAnimator
);
animatorSet.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationCancel(Animator animation) {
ivStar.setScaleX(1);
ivStar.setScaleY(1);
}
});
animatorSet.start();
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
ivStar.animate().scaleX(0.7f).scaleY(0.7f).setDuration(150).setInterpolator(DECCELERATE_INTERPOLATOR);
setPressed(true);
break;
case MotionEvent.ACTION_MOVE:
float x = event.getX();
float y = event.getY();
boolean isInside = (x > 0 && x < getWidth() && y > 0 && y < getHeight());
if (isPressed() != isInside) {
setPressed(isInside);
}
break;
case MotionEvent.ACTION_UP:
ivStar.animate().scaleX(1).scaleY(1).setInterpolator(DECCELERATE_INTERPOLATOR);
if (isPressed()) {
performClick();
setPressed(false);
}
break;
}
return true;
}
}

Overriding getContextMenuInfo() from custom Adapter

I am building a list that had to be able to reorder the item's position.
Fortunately for me, I've found an external library which has exactly what I needed.
Unfortunately, I could not implement a delete item action using onContextItemSelected() because menuInfo keeps always returning null, so I cannot read the position of selected item I wish to delete.
This user blog post gave a solution by overriding getContextMenuInfo().
If item.getMenuInfo() is null in onContextItemSelected(MenuItem item) method, I guess you are using custom ListView or GridView instead of android default ones. In such case, your custom View is not implementing getContextMenuInfo() method. Don’t worry we can fix that if you have its source. Open the view file and override the method getContextMenuInfo().
I have tried this in many ways, but it seems I am doing things wrong.
Is this the only solution or am I missing something?
Activity
public class SurveyAdd extends AppCompatActivity {
private ArrayList<Pair<Long, String>> mItemArray = new ArrayList<>();
private DragListView mDragListView;
ItemAdapter listAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_survey_add);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mDragListView = (DragListView) findViewById(R.id.surveyadd_list);
mDragListView.getRecyclerView().setVerticalScrollBarEnabled(true);
mDragListView.setDragListListener(new DragListView.DragListListener() {
#Override
public void onItemDragStarted(int position) {
}
#Override
public void onItemDragEnded(int fromPosition, int toPosition) {
if (fromPosition != toPosition) {
setSurveyChange(true);
}
}
});
mDragListView.setCanDragHorizontally(false);
mDragListView.setCustomDragItem(new MyDragItem(context, R.layout.item_survey_add));
mDragListView.setLayoutManager(new LinearLayoutManager(context));
mDragListView.setLayoutManager(new LinearLayoutManager(context));
ItemAdapter listAdapter = new ItemAdapter(mItemArray, R.layout.item_survey_add, R.id.item_add_image_button, false);
mDragListView.setAdapter(listAdapter, true);
registerForContextMenu(mDragListView);
}
#Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_survey_add_item, menu);
}
#Override
public boolean onContextItemSelected(MenuItem item) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
switch (item.getItemId()) {
case R.id.surveyadd_action_delete:
if (item.getMenuInfo() == null) {
Toast.makeText(SurveyAdd.this, "NULL", Toast.LENGTH_SHORT).show();
}
int position = info.position; // CAN'T USE THIS, ALWAYS THROWS NULLPOINTEREXCEPTION
Toast.makeText(SurveyAdd.this, "" + position, Toast.LENGTH_SHORT).show();
return true;
}
}
}
// The activity was simplified for posting
ItemAdapter
imported and edited class
public class ItemAdapter extends DragItemAdapter<Pair<Long, String>, ItemAdapter.ViewHolder> {
private int mLayoutId;
private int mGrabHandleId;
public ItemAdapter(ArrayList<Pair<Long, String>> list, int layoutId, int grabHandleId, boolean dragOnLongPress) {
super(dragOnLongPress);
mLayoutId = layoutId;
mGrabHandleId = grabHandleId;
setHasStableIds(true);
setItemList(list);
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(mLayoutId, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
super.onBindViewHolder(holder, position);
String text = mItemList.get(position).second;
String[] separated = text.split("::");
holder.mText.setText(separated[1]);
holder.itemView.setTag(text);
}
#Override
public long getItemId(int position) {
return mItemList.get(position).first;
}
public class ViewHolder extends DragItemAdapter<Pair<Long, String>, ItemAdapter.ViewHolder>.ViewHolder {
public TextView mText;
public ImageView mIcon;
public ViewHolder(final View itemView) {
super(itemView, mGrabHandleId);
mText = (TextView) itemView.findViewById(R.id.item_add_question);
mIcon = (ImageView) itemView.findViewById(mGrabHandleId);
}
#Override
public void onItemClicked(View view) {
}
#Override
public boolean onItemLongClicked(View view) {
return false;
}
}
}
DragListView
imported and locked class
public class DragListView extends FrameLayout {
public interface DragListListener {
void onItemDragStarted(int position);
void onItemDragEnded(int fromPosition, int toPosition);
}
private DragItemRecyclerView mRecyclerView;
private DragListListener mDragListListener;
private DragItem mDragItem;
private boolean mDragEnabled = true;
private float mTouchX;
private float mTouchY;
public DragListView(Context context) {
super(context);
}
public DragListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public DragListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
mDragItem = new DragItem(getContext());
mRecyclerView = createRecyclerView();
mRecyclerView.setDragItem(mDragItem);
addView(mRecyclerView);
addView(mDragItem.getDragItemView());
}
#Override
public boolean onInterceptTouchEvent(MotionEvent event) {
boolean retValue = handleTouchEvent(event);
return retValue || super.onInterceptTouchEvent(event);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
boolean retValue = handleTouchEvent(event);
return retValue || super.onTouchEvent(event);
}
private boolean handleTouchEvent(MotionEvent event) {
mTouchX = event.getX();
mTouchY = event.getY();
if (isDragging()) {
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
mRecyclerView.onDragging(event.getX(), event.getY());
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
mRecyclerView.onDragEnded();
break;
}
return true;
}
return false;
}
private DragItemRecyclerView createRecyclerView() {
final DragItemRecyclerView recyclerView = (DragItemRecyclerView) LayoutInflater.from(getContext()).inflate(R.layout.drag_item_recycler_view, this, false);
recyclerView.setMotionEventSplittingEnabled(false);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setVerticalScrollBarEnabled(false);
recyclerView.setHorizontalScrollBarEnabled(false);
recyclerView.setDragItemListener(new DragItemRecyclerView.DragItemListener() {
private int mDragStartPosition;
#Override
public void onDragStarted(int itemPosition, float x, float y) {
getParent().requestDisallowInterceptTouchEvent(true);
mDragStartPosition = itemPosition;
if (mDragListListener != null) {
mDragListListener.onItemDragStarted(itemPosition);
}
}
#Override
public void onDragging(int itemPosition, float x, float y) {
}
#Override
public void onDragEnded(int newItemPosition) {
if (mDragListListener != null) {
mDragListListener.onItemDragEnded(mDragStartPosition, newItemPosition);
}
}
});
return recyclerView;
}
public RecyclerView getRecyclerView() {
return mRecyclerView;
}
public DragItemAdapter getAdapter() {
if (mRecyclerView != null) {
return (DragItemAdapter) mRecyclerView.getAdapter();
}
return null;
}
public void setAdapter(DragItemAdapter adapter, boolean hasFixedItemSize) {
mRecyclerView.setHasFixedSize(hasFixedItemSize);
mRecyclerView.setAdapter(adapter);
adapter.setDragEnabled(mDragEnabled);
adapter.setDragStartedListener(new DragItemAdapter.DragStartedListener() {
#Override
public void onDragStarted(View itemView, long itemId) {
mRecyclerView.onDragStarted(itemView, itemId, mTouchX, mTouchY);
}
});
}
public void setLayoutManager(RecyclerView.LayoutManager layout) {
mRecyclerView.setLayoutManager(layout);
}
public void setDragListListener(DragListListener listener) {
mDragListListener = listener;
}
public boolean isDragEnabled() {
return mDragEnabled;
}
public void setDragEnabled(boolean enabled) {
mDragEnabled = enabled;
if (mRecyclerView.getAdapter() != null) {
((DragItemAdapter) mRecyclerView.getAdapter()).setDragEnabled(mDragEnabled);
}
}
public void setCustomDragItem(DragItem dragItem) {
removeViewAt(1);
DragItem newDragItem;
if (dragItem != null) {
newDragItem = dragItem;
} else {
newDragItem = new DragItem(getContext());
}
newDragItem.setCanDragHorizontally(mDragItem.canDragHorizontally());
newDragItem.setSnapToTouch(mDragItem.isSnapToTouch());
mDragItem = newDragItem;
mRecyclerView.setDragItem(mDragItem);
addView(mDragItem.getDragItemView());
}
public boolean isDragging() {
return mRecyclerView.isDragging();
}
public void setCanDragHorizontally(boolean canDragHorizontally) {
mDragItem.setCanDragHorizontally(canDragHorizontally);
}
public void setSnapDragItemToTouch(boolean snapToTouch) {
mDragItem.setSnapToTouch(snapToTouch);
}
public void setCanNotDragAboveTopItem(boolean canNotDragAboveTop) {
mRecyclerView.setCanNotDragAboveTopItem(canNotDragAboveTop);
}
public void setScrollingEnabled(boolean scrollingEnabled) {
mRecyclerView.setScrollingEnabled(scrollingEnabled);
}
}
This is an old post but i figured it out using that same draglistview.
Im using Xamarin but it's close enough to the same. Just type the C# in Java as necessary:
protected override IContextMenuContextMenuInfo ContextMenuInfo
{
get
{
IContextMenuContextMenuInfo menuInfo = base.ContextMenuInfo;
if (menuInfo == null)
{
IListAdapter adapter = Adapter;
int pos = GetPositionForView(selectedView);
menuInfo = new AdapterContextMenuInfo(selectedView, pos, adapter.GetItemId(pos));
}
return menuInfo;
}
}
public void OnLongPress(MotionEvent e){
int position = PointToPosition(mDownX, mDownY);
int itemNum = position - FirstVisiblePosition;
selectedView = GetChildAt(itemNum); //class variable
...
}

Categories