How to Scroll pdfView automatically with button click or volume buttons - android-studio

I'm using barteksc pdf viewer library to load pdf in my application.
pdfView = findViewById(R.id.pdfView);
pdfView.fromAsset(getResources().getString(R.string.pdfname))
.enableDoubletap(true)
.enableSwipe(true)
.defaultPage(pageNumber)
.onPageChange(mainreading.this)
.pageFitPolicy(FitPolicy.WIDTH)
.pageFling(true)
.linkHandler(null)
.enableAnnotationRendering(true)
.swipeHorizontal(true)
.scrollHandle(new DefaultScrollHandlenew(mainreading.this))
.enableAntialiasing(true)
.load();
}
I want pdf to start scroll automatically when user click the button of volume up and down buttons to start stop. I tried with below code while wrapping it in the handler with handler.performClick(); but it shows blank screen while scrolling up and down.
scrollbutton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
pdfView.scrollTo(0, pdfView.getScrollY() + 24);
}
});
Example :
https://play.google.com/store/apps/details?id=com.emptysheet.pdfreader_autoscroll&hl=en&gl=US
I want to make as like this. Can anyone help please.
Also tried with this. But it shows blank page after some scrolls.
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
int action = event.getAction();
int keyCode = event.getKeyCode();
switch (keyCode) {
case KeyEvent.KEYCODE_VOLUME_UP:
if (action == KeyEvent.ACTION_DOWN) {
pdfView.scrollTo(0, pdfView.getScrollY() -24);
}
return true;
case KeyEvent.KEYCODE_VOLUME_DOWN:
if (action == KeyEvent.ACTION_DOWN) {
pdfView.scrollTo(0, pdfView.getScrollY() + 24);
}
return true;
default:
return super.dispatchKeyEvent(event);
}
}

You can simply use this PDF viewer from github.
It's based on the same 'barsteksc' pdf viewer with the feature to jump to any pages.
It's MagicalPdfViewer and you can use 'jumpTo(pageNo)' method to simply jump to the specific page. It also gives you the option to animate to the specific page with the same method, just pass 'true' as the 2nd parameter.
Moreover, if you pass the values like '-1' and 'bigger than pageNo', It will automatically scroll to the 0 & last page respectively.
Give it a try & let me know if you got what you wanted.

Related

Cannot trigger cancel button action after processing results returned

Within the Acumatica 19.201.0070 framework I have created a custom processing page that utilizes PXFilteredProcessing with the old style processing UI public override bool IsProcessing => false; I have defined a cancel button (below) that will clear the graph and set some values of the processing filter.
public PXCancel<NPMasterSubGeneratorFilter> Cancel;
[PXCancelButton()]
protected virtual IEnumerable cancel(PXAdapter adapter)
{
NPMasterSubGeneratorFilter row = Filter.Current;
if (row != null)
{
this.Clear();
Filter.SetValueExt<NPMasterSubGeneratorFilter.segmentID>(Filter.Current, row.SegmentID);
if (!(row.NewSegment ?? false)) Filter.SetValueExt<NPMasterSubGeneratorFilter.segmentValue>(Filter.Current, row.SegmentValue);
}
return adapter.Get();
}
This works perfectly fine except for a single use case, after processing results are shown if the user then presses the cancel button the corresponding action is never hit. ( My fellow office devs state that core Acumatica processing pages seem to operate the same. )
Setting of the processing delegate is within the filter RowSelected event.
GeneratedSubs.SetProcessDelegate(list => CreateSubaccounts(list, row));
I have implemented a few iterations of my processing method but the current is below.
protected virtual void CreateSubaccounts(List<NPGeneratedSub> subs, NPMasterSubGeneratorFilter filter)
{
if (filter.NewSegment ?? false)
{
try
{
SegmentMaint segGraph = PXGraph.CreateInstance<SegmentMaint>();
segGraph.Segment.Update(segGraph.Segment.Search<Segment.dimensionID, Segment.segmentID>(AADimension.Subaccount, filter.SegmentID.Value));
SegmentValue value = segGraph.Values.Insert(new SegmentValue() { Value = filter.SegmentValue, Descr = filter.Description });
segGraph.Actions.PressSave();
}
catch
{
throw new PXOperationCompletedSingleErrorException(NonProfitPlusMessages.SegmentValueCannotCreate);
}
}
SubAccountMaint subGraph = PXGraph.CreateInstance<SubAccountMaint>();
NPSubAccountMaintExtension subGraphExt = subGraph.GetExtension<NPSubAccountMaintExtension>();
subGraphExt.save.ConfirmSaving = false;
Sub newSub;
bool errored = false;
foreach (NPGeneratedSub sub in subs)
{
PXProcessing<NPGeneratedSub>.SetCurrentItem(sub);
try
{
newSub = subGraph.SubRecords.Insert(new Sub() { SubCD = sub.SubCD, Description = sub.Description });
subGraph.Save.Press();
subGraph.Clear();
PXProcessing<NPGeneratedSub>.SetProcessed();
}
catch (Exception e)
{
PXProcessing<NPGeneratedSub>.SetError(e);
errored = true;
}
}
if (errored)
{
throw new PXOperationCompletedWithErrorException();
}
}
What needs to be adjusted to allow the buttons action to be triggered on press after processing results have been returned?
After stepping through the javascript I discovered that it wasn't sending a request to the server when you click the cancel button on this screen after processing. The reason is because SuppressActions is getting set to true on the Cancel PXToolBarButton. I compared what I was seeing on this screen to what was happening on screens that work correctly and realized that Acumatica is supposed to set SuppressActions to true on the Schedule drop down PXToolBarButton but for some reason, on this screen, it is incorrectly setting it to true on whatever button is after the Schedule drop down button.
I looked through the code in PX.Web.UI and it looks like they set SuppressActions to true when a drop down button is disabled and PXProcessing adds a FieldSelecting event to the Schedule button which disables the button after you click process. However, I didn't notice any obvious issues as to why the code would be setting it on the wrong PXToolBarButton so someone will likely need to debug the code and see what's going on (we are unable to debug code in PX.Web.UI.dll).
I tried commenting out the other grids in the aspx file that aren't related to the PXProcessing view and this resolved the issue. So my guess would be that having multiple grids on the PXProcessing screen somehow causes a bug where it sets SuppressActions on the wrong PXToolBarButton. However, since the multiple grids are a business requirement, removing them is not a solution. Instead, I would suggest moving all buttons that are after the schedule button to be before the schedule button. To do this, just declare the PXActions before the PXFilteredProcessing view in the graph.
Please try this
Override IsDirty property
Use PXAction instead of PXCancel
Add PXUIField attribute with enable rights
action name should start from lowercase letter
delegate name should start from uppercase letter
see code below
public override bool IsDirty => false;
public override bool IsProcessing
{
get { return false;}
set { }
}
public PXAction<NPMasterSubGeneratorFilter> cancel;
[PXUIField(MapEnableRights = PXCacheRights.Select)]
[PXCancelButton]
protected virtual IEnumerable Cancel(PXAdapter adapter)
{
NPMasterSubGeneratorFilter row = Filter.Current;
if (row != null)
{
this.Clear();
Filter.SetValueExt<NPMasterSubGeneratorFilter.segmentID>(Filter.Current, row.SegmentID);
if (!(row.NewSegment ?? false)) Filter.SetValueExt<NPMasterSubGeneratorFilter.segmentValue>(Filter.Current, row.SegmentValue);
}
return adapter.Get();
}

Prevent collapsingToolbar from expanding for certain fragments

I'm trying to prevent a CollapsingToolbar from expanding for one of my fragments.
Currently, when I use the method setExpanded(), I am able to see the toolbar in its collapsed state.
appBarLayout.setExpanded(false, true);
However, the collapsingToolbar is still expandable, which is not what I want. I want the collapsingToolbar to not be expandable for this particular fragment.
In other words, I want the collapsingToolbar to behave and look like a regular toolbar (i.e. "not expandable") for this particular fragment only.
I am using Mike Penz's Material Drawer. The code below shows the relevant code, with notes indicating what I have tried.
private void buildDrawer(){
Drawer drawer = new DrawerBuilder()
.withActivity(this)
.withFullscreen(true)
.withTranslucentStatusBar(true)
.withToolbar(toolbar)
.withAccountHeader(accountHeader)
.addDrawerItems(
item1,
item2,
new DividerDrawerItem(),
item3,
item4
)
.withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() {
#Override
public boolean onItemClick(View view, int position, IDrawerItem drawerItem) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
Fragment f = new Fragment();
switch (position) {
//other cases not shown
case 2:
f = new LocateFragment();
appBarLayout.setExpanded(false, true);
//Adding the following three lines don't work - causes the toolbar to be unscrollable, but in its expanded form
//AppBarLayout.LayoutParams p = (AppBarLayout.LayoutParams)collapsingToolbarLayout.getLayoutParams();
//p.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SNAP);
//collapsingToolbarLayout.setLayoutParams(p);
//toolbar.setCollapsible(false); doesn't work either
collapsingToolbarLayout.setTitle("Locate Events");
setInvisibleAddPhotoFab();
break;
//other cases not shown
}
fragmentTransaction.replace(R.id.frame_fragments, f);
fragmentTransaction.commit();
return false; //close drawer onclick
}
})
.build();
loadBackdrop();
}
This is what I want - I want the toolbar to be unexpandable:
Currently, however, it is still expandable, so the image below is NOT what I want:
UPDATE:
I was able to collapse the toolbar and prevent it from expanding like so (code below), but I've run into another issue - the title no longer appears on the collapsingToolbar when I set it like so: collapsingToolbarLayout.setTitle("string");
appBarLayout.setExpanded(false, true);
int px = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 80, getResources().getDisplayMetrics());
CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams)appBarLayout.getLayoutParams();
lp.height = px;
appBarLayout.setLayoutParams(lp);
I was able to resolve this problem using the following (as shown here by #DanielPersson):
collapsingToolbarLayout.setTitleEnabled(false);
toolbar.setTitle(title);

Using a button as a boolean switch

I'm trying to make a button in android function as a boolean switch. I want it to do something on the first click and do something else on the second click. On the third click, I want it to do the same thing on the first click et cetera. The main reason I want this due to the text element on the button that changes with each click. Switches and checkboxes have no texts to change.
I've tried finding documentations on doing this online but can't seem to find any previous examples of doing this. Would appreciate if anyone has any ideas or just tell me outright that this is not workable.
yourButton
.setOnClickListener(new View.OnClickListener() {
private boolean state = false;
public void onClick(View v) {
if ( state ) {
state = false;
yourButton.setText("False");
} else {
state = true;
yourButton.setText("True");
}
}
});
You can try something like this, by the way i DIDN'T test this code i'm just trying to show you a way you could try to do it
1. set button to change drawable background and remove
button.setOnClickListener ( new View.OnClickListener () {
private boolean state=false;
#Override
public void onClick(View v) {
if (state){
state=false;
textView.setBackground ( getDrawable(R.drawable.led_mode ) );
}
else{
state=true;
textview.setbackground(null);
}
}
});

jTabbedPane set active tab text properties

I have a jTabbedPane with multiple tabs in it. I am trying to make the title text of the selected/active tab bold. Is there a simple way to do this?
JTabbedPane pane = new JTabbedPane();
pane.addChangeListener(new ChangeListener(){
#Override
public void stateChanged(ChangeEvent e) {
JTabbedPane source = (JTabbedPane) e.getSource();
// Set all tabs to PLAIN font
for(int i = 0; i < source.getTabCount(); i++) {
Component c = source.getTabComponentAt(i);
c.setFont(c.getFont().deriveFont(Font.PLAIN));
}
Component selectedComp = source.getTabComponentAt(source.getSelectedIndex());
// Set selected component to BOLD
selectedComp.setFont(selectedComp.getFont().deriveFont(Font.BOLD));
}
});
Try this, i wrote it quickly, maybe you need to do some adjustments for the initial tab, don't know for sure.
Also not so sure if you need JTabbedPane.getTabComponentAt(int idx) or JTabbedPane.getComponentAt(int idx) although i suppose first version is correct.
I know that this question was asked a long time ago, but I recently wanted to do this as well. I found the answer here. The solution was one of two things:
Use tabbedPane.setTitleAt(currSelextedIdx, "<html><b>My tab title</b></html>");
Create your own UI implementation for the tabbed pane
I personally used the first option and set all the other tabs back to the regular tab title on a change. I also made the initial tab bold after initializing all the tabs (this can be done upon initialization).
The simplest solution I've found until now. In a subclass of JTabbedPane, override two methods as below. When the tab is added, the raw title is persisted as a client property of the tab component. When the selected tab changes, the current tab title is restored to the raw title and the next tab title is set to bold with HTML.
public class MyTabbedPane extends JTabbedPane {
...
#Override
public void insertTab(String title, Icon icon, Component component, String tip, int index) {
((JComponent)component).putClientProperty("title", title);
super.insertTab(title, icon, component, tip, index);
}
#Override
public void setSelectedIndex(int index) {
int currentIndex = getSelectedIndex();
if (currentIndex >= 0) {
JComponent previous = (JComponent) getComponentAt(currentIndex);
String title = (String) previous.getClientProperty("title");
setTitleAt(currentIndex, title);
}
super.setSelectedIndex(index);
JComponent current = getSelectedComponent();
String title = (String) current.getClientProperty("title");
setTitleAt(index, "<html><b>" + title + "</b></html>");
}
}

How to reselect item in Telerik's RadGrid?

I have 2 Telerik's rad grids. First one is master and second one is detail. I can delete rows from both grids independently by pressing "Delete" button on toolbar above each grid. I also have "Refresh" buttons in toolbar of both grids.
The problem is with detail grid. When I delete item(s) the grid doesn't refresh. Calling Rebind method doesn't help. The only thing that helps is to press "Refresh" button in toolbar of master grid and select the row in master grid by mouse that was previously selected. After that I can see refreshed detail grid.
So, I don't need to press "Refresh" button in toolbar of master grid and select the row in master grid by mouse. I can refresh the master grid programmatically and only want to reselect the item that was originally selected also programmatically. I've tried this:
item.Selected = true;
But, it only visually selects the item in master grid and doesn't refresh the detail grid.
So, how to select the item in master grid programmatically in order to get the same effect as selecting it by mouse?
Thank you in advance.
I've just realised that your probably using different DataSource for both grids, but pointing to the same database, right? My example below uses the same datasource for both grids. However I made on a detail view versus a normal view by making some columns not visible. Maybe this strategy could fix your issue?
My first thought was to try implement the SelectionChanged event, or if not that, the SelectionChanging event. Put a refresh in there you see. But I didn't end up doing it that way.
I wrote a small program as below. It saves the edits to disk with any row change as long as its not a remove (I had trouble saving remove edits when the button was clicked it gave a null pointer exception on the remove command). It also saves changes just before closing the program (so that any delete rows are also saved then). I did find that the deleteOne and deleteTwo buttons (that delete from the first or second grid, respectively) do in fact cause the deletion to occur in both grids. So a possibility is you could use the radGridView1.Rows.Remove(row) or RemoveAt(i) command if that works in your situation?
Another possibility is that if refresh isn't working you could set the DataSource to null and then set it to the data source again, after deleting the row. This is a bit drastic but if it's the only thing that works? I'm talking about the data source for both grids.
My code is below:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Telerik.WinControls;
using Telerik.WinControls.Data;
using Telerik.WinControls.UI;
namespace RadControlsWinFormsApp1
{
public partial class RadForm1 : Telerik.WinControls.UI.RadForm
{
public RadForm1()
{
InitializeComponent();
}
private void RadForm1_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the 'testdbDataSet.Customers' table. You can move, or remove it, as needed.
this.customersTableAdapter.Fill(this.testdbDataSet.Customers);
radGridView1.Columns["Address"].IsVisible = false;
}
private void radGridView1_RowsChanged(object sender, Telerik.WinControls.UI.GridViewCollectionChangedEventArgs e)
{
// if removing don't update, because if my delete button is pressed this
// will otherwise cause all sorts of problems and freezes the grid
if (e.Action != NotifyCollectionChangedAction.Remove)
{
try
{
customersTableAdapter.Update(testdbDataSet);
}
catch (DBConcurrencyException ex)
{
// unable to save right now, don't worry about it
}
}
radGridView2.Refresh();
}
private void butDeleteOne_Click(object sender, EventArgs e)
{
bool haveRemoved = false;
for (int i = 0; i < radGridView1.Rows.Count && !haveRemoved; ++i)
{
GridViewRowInfo row = radGridView1.Rows[i];
if (row.IsSelected)
{
haveRemoved = true;
radGridView1.Rows.RemoveAt(i);
}
}
}
private void butDeleteTwo_Click(object sender, EventArgs e)
{
bool haveRemoved = false;
for (int i = 0; i < radGridView2.Rows.Count && !haveRemoved; ++i)
{
GridViewRowInfo row = radGridView2.Rows[i];
if (row.IsSelected)
{
haveRemoved = true;
radGridView2.Rows.RemoveAt(i);
}
}
}
private void radGridView2_RowsChanged(object sender, GridViewCollectionChangedEventArgs e)
{
// if removing don't update, because if my delete button is pressed this
// will otherwise cause all sorts of problems and freezes the grid
if (e.Action != NotifyCollectionChangedAction.Remove)
{
try
{
customersTableAdapter.Update(testdbDataSet);
}
catch (DBConcurrencyException ex)
{
// unable to save right now, don't worry about it
}
}
radGridView1.Refresh();
}
private void RadForm1_FormClosing(object sender, FormClosingEventArgs e)
{
// ensure all data is saved back into database on close
customersTableAdapter.Update(testdbDataSet);
}
//private void radGridView1_CellEndEdit(object sender, Telerik.WinControls.UI.GridViewCellEventArgs e)
//{
//}
}
}

Resources