Categories
discuss

CollapsingToolbarLayout – Hide ImageView when Expanded, show when Collapsed

I would like to hide an ImageView (logo) when CollapsingToolbarLayout is expanded and only show the ImageView when the CollapsingToolbarLayout is collapsed. (I know how to do the reverse of this question).

As you can see from the screenshot below. The big mast head is actually one big logo, image on left and then company name on right. In collapsed mode I only want to show a small thumbnail of the logo.

How can I accomplish this in XML or code please? Code & screenshots below:

<android.support.design.widget.CoordinatorLayout
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:scaleType="fitCenter"
android:adjustViewBounds="true">

<android.support.design.widget.AppBarLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:fitsSystemWindows="true">

    <android.support.design.widget.CollapsingToolbarLayout
        android:id="@+id/collapsing_toolbarlayout_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_scrollFlags="scroll|exitUntilCollapsed"
        app:contentScrim="@color/colorPrimary">

        <ImageView
            android:id="@+id/mast_logo_main"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:scaleType="fitCenter"
            android:adjustViewBounds="true"
            app:layout_collapseMode="parallax"
            app:layout_collapseParallaxMultiplier="0.9"
            android:src="@drawable/uj_logo_rectangle_orange_background" />


        <android.support.v7.widget.Toolbar
            android:layout_width="match_parent"
            android:layout_height="100dp"
            app:contentInsetStart="40dp"
            app:layout_collapseMode="parallax"
            app:layout_scrollFlags="scroll|exitUntilCollapsed|snap" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="80dp"
            android:orientation="horizontal"
            app:layout_collapseMode="pin">

            <ImageView
                android:id="@+id/thumbnail_logo_main"
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:scaleType="fitCenter"
                android:adjustViewBounds="true"
                android:layout_marginTop="50dp"
                android:layout_marginLeft="10dp"
                android:src="@drawable/uj_rgb_logo_01" />

            <LinearLayout
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:layout_weight="4">

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="20dp"
                    android:paddingTop="20dp"
                    android:layout_marginLeft="10dp"
                    android:textSize="20sp"
                    android:textColor="#fff"
                    android:textStyle="bold"

                    android:text="Courses &amp; Programmes"/>

                <android.support.v7.widget.SearchView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"/>

            </LinearLayout>

            <LinearLayout
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1">

                <ImageView
                    android:layout_width="57dp"
                    android:layout_height="40dp"
                    android:layout_marginLeft="5dp"
                    android:layout_marginRight="10dp"
                    android:layout_marginTop="50dp"
                    android:adjustViewBounds="true"
                    android:scaleType="fitCenter"
                    android:src="@drawable/empty_avatar" />

            </LinearLayout>

        </LinearLayout>

    </android.support.design.widget.CollapsingToolbarLayout>

</android.support.design.widget.AppBarLayout>

<include layout="@layout/fragment_all_faculties"/>

Expanded view

enter image description here

Answer

Follow the below code:

AppBarLayout appBarLayout = (AppBarLayout) view.findViewById(R.id.app_bar_layout);
appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
        @Override
        public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
            if (Math.abs(verticalOffset) == appBarLayout.getTotalScrollRange()) {
                // If collapsed, then do this
                imageViewBigLogo.setVisibility(View.GONE);
                imageViewSmallLogo.setVisibility(View.VISIBLE);
            } else if (verticalOffset == 0) {
                // If expanded, then do this
                imageViewBigLogo.setVisibility(View.VISIBLE);
                imageViewSmallLogo.setVisibility(View.GONE);
            } else {
                // Somewhere in between
                // Do according to your requirement
            }
        }
    }););

Thanks to this.

Categories
discuss

Play Store: Set age limit

Is it possible to set an age limit for applications published on Android store?

There is the “Content rating” in the “Store presence” settings, but the age limit is calculated automatically depending on the questionnaires.

How can I restrict play store to list my app only for users aged >18 years for example, without having to give false answers in the questionnaire?

Answer

No there is no such options in the console and Content Rating act as a warning type message to the users. Here are some points of Content Rating

  • Inform consumers, especially parents, of potentially objectionable
    content within an app.
  • Block or filter your content in certain
    territories or to specific users where legally required.
  • Evaluate your app’s eligibility for special developer programs.
Categories
discuss

Map an arbitrary n-ary Tree with fold

I want to have some general purpose tools for dealing with trees. I’m using JavaScript, so there’s little I can impose, and I’m using existing data structures that I can’t change. I managed to define the following:

reduceTree :: (T a -> [T a]) -> (b -> T a -> b) -> b -> T a -> b
reduceTree(getChildren, f, accumulator, tree)

(I’m using Haskell type signatures because they’re easier to read)

This getChildren function is required because my tree is arbitrary, and I know nothing about how it is constructed.

reduceTree works well. But I would like to have a mapTree function too, preferably reusing my reduceTree function, but I’m stuck. Something is amiss but I can’t figure out what.

Edit

My reduceTree implementation:

export function reduceTree(getChildren, f, accumulator, tree) {
  const children = getChildren(tree);
  if (!children || children.length === 0) {
    return f(accumulator, tree)
  } else {
    const childrenResult = children.reduce(
      (accumulator, subTree) => reduceTree(getChildren, f, accumulator, subTree),
      accumulator
    );
    return f(childrenResult, tree)
  }
}

It was tested and works.

(My pseudo Haskell implementation I used to construct/prove the javascript above:

reduceTree f a (Node val []) = f a val
reduceTree f a (Node val xs) = f (fold (reduceTree f) acc) val

)

Answer

I see that your tree data structure is defined as follows:

data T a = Node a [T a]

If that’s the case then the fold for your tree data structure would be:

reduceTree :: (a -> [b] -> b) -> T a -> b
reduceTree f = let g (Node a xs) = f a (map g xs) in g

You can now define mapTree using reduceTree as follows:

mapTree :: (a -> b) -> T a -> T b
mapTree f = reduceTree (Node . f)

Converting it all to JavaScript:

const Node = (a, xs) => ({a, xs});

const reduceTree = (f, node) => {
    const g = node => f(node.a, node.xs.map(g));
    return g(node);
};

const mapTree = (f, node) => reduceTree((a, xs) => Node(f(a), xs), node);

const tree = Node(2, [ Node(3, [ Node(11, [])
                               , Node(13, []) ])
                     , Node(5, [])
                     , Node(7, [ Node(17, [])
                               , Node(19, []) ]) ]);

console.log(mapTree(x => 2 * x, tree));

Hope that helps.

Categories
discuss

Google Play Install Referrer API vs. INSTALL_REFERRER broadcast

Recently Google released Google Play Install Referrer API (announcement).

Comparing to the INSTALL_REFERRER broadcast from Google Play, it provides extra information like click and installs time in addition to referrer itself.

First question: is it a complete replacement for INSTALL_REFERRER broadcast? Should we just drop the broadcast receiver and start using a new API?

Second: is there any information in what particular cases new API is more reliable then INSTALL_REFERRER broadcast?

Answer

It’s all about SECURITY and SIMPLICITY. As the doc implies, you can use the Google Play Store’s Install Referrer API to securely retrieve more accurate and reliable referral content from Google Play and also you can consider switch to Install Referrer API Client Library to simplify your development process. and as u mentioned in the query it returns ReferrerDetails object that hold extra info related to the install with the below three methods.

ReferrerDetails response = mReferrerClient.getInstallReferrer();
response.getInstallReferrer();
response.getReferrerClickTimestampSeconds();
response.getInstallBeginTimestampSeconds();

The API works only from Play Store version 8.3.73 onwards. Any developers that would like to begin using it can start right away, but a connection must be established between their app and the Play Store.

Also, check an article from Adjust that explains how new API can prevent click injection fraud for mobile ads.

P.S. You need to keep track with the latest API levels to be able to deliver the best solutions to the problems you face in your projects.

Categories
discuss

Set class in HTML table, but not for the entire column

Here is the situation, I have a HTML file with a table, the table gets filled with XML data. The last column (10) got a number in it: 1, 2, 3, 4 or 5. I’ve got 5 lines of jQuery which look for the number and give the cell with the corresponding number a specific class, this works fine (The cell has 0% opacity because it’s not meant to be “shown”, but for our means, it works fine like that).

Now the problem is: Column 7 and 8 need to get that class to without the whole column getting it, just the row with the specific number.

I’ve got a jsfiddle so you can see the code and stuff:

The jQuery:

$("td:nth-child(10):contains('1')").addClass('disaster');
$("td:nth-child(10):contains('2')").addClass('high');
$("td:nth-child(10):contains('3')").addClass('average');
$("td:nth-child(10):contains('4')").addClass('warning');
$("td:nth-child(10):contains('5')").addClass('information');

Note: The data in the table is just for testing, the real xml will have those number of 1, 2, 3, 4, 5 in like 100 rows in a random order.

EDIT: Got a picture of how it should look: enter image description here

$("td:nth-child(10):contains('1')").addClass('disaster');
$("td:nth-child(10):contains('2')").addClass('high');
$("td:nth-child(10):contains('3')").addClass('average');
$("td:nth-child(10):contains('4')").addClass('warning');
$("td:nth-child(10):contains('5')").addClass('information');
td:nth-child(10) { 
opacity: 0;
}
.disaster{	
background-color: #E45858
}
.high{	
background-color: #E87658
}
.average{	
background-color: #FEA058
}
.warning{	
background-color: #FEC858
}
.information{
background-color: #7498FE
}
/*CSS for main elements*/
div {	
max-width: 2600px;
display: block;
}
body { 	
font-family: Arial, Tahoma, Verdana, sans-serif;
background-color: #FFFFFF;
}
table { 	
text-align: left;
border-collapse: collapse;
}
th	{	
font-size: 75%;	
font-weight: normal;
color: 	#768C98;
padding-top: 5px;
padding-bottom: 5px;
border-bottom: 2px solid #DCE2E4;
}
td	{	
font-size: 75%;	
color: #1F2C33;
height: 25px;
padding-top: 1px;
padding-bottom: 1px;
border-bottom: 1px solid #EAEEF0;
}	
img {	
position: absolute; left: -100px;
margin-top: 165px;
transform: rotate(270deg);
}
/*CSS for Hover*/
td:nth-child(1):hover{	
text-decoration: underline;
}
td:nth-child(1) {	
background-color: #FFFFFF;
}
td:nth-child(2) {	
background-color: #FFFFFF;
}
tr.NoHover:hover{ 	
background-color: #FFFFFF;
}
tr:hover {		
background-color: #E8F5FF;
}
/*Column specific CSS*/
th.col1 {	
text-align: right;
width: 240px;
padding-right: 18px
}
th.col2 {	
width: 11px;
padding: none;	
}
th.col3 {	
text-align: left;
width: 188px;
padding-left: 10px;
}
th.col4 {	
text-align: left;
width: 70px;
}
th.col5 {	
text-align: left;
width: 77px;
padding-left: 82px;
}
th.col6 {	
text-align: left;
width: 430px;
}
th.col7 {	
text-align: left;
padding-left: 10px;
width: 497px;
}
th.col8 {	
text-align: left;
width: 498px;
}
th.col9 {	
text-align: left;
padding-left: 10px;
width: 75px;
}
td:nth-child(1)	{	
text-align: right;
color: #0274B8;
padding-right: 18px;
border-right: 2px solid #AAD6F0;
border-bottom: none;
}
td:nth-child(2) { 
color: white;
border-bottom: none;
width: 11px;
padding: none;
}
td:nth-child(3) {	
text-align: left;
text-decoration: underline dotted; 
padding-left: 10px;
border-bottom: 1px solid #EAEEF0;
}
td:nth-child(4) {	
text-align: left;
color: #DC0000;
border-bottom: 1px solid #EAEEF0;
}
td:nth-child(5) {	
text-align: right;
text-decoration: underline dotted;
padding-right: 15px;
border-bottom: 1px solid #EAEEF0;
}
td:nth-child(6) {	
text-align: left;
text-decoration: underline dotted; 	
border-bottom: 1px solid #EAEEF0;						
}
td:nth-child(7) {	
text-align: left;
text-decoration: underline dotted ;
padding-left: 10px;
border-bottom: 1px solid #EAEEF0;
}
td:nth-child(8) {	
text-align: left;
text-decoration: underline dotted;
border-bottom: 1px solid #EAEEF0;
}
td:nth-child(9) {	
text-align: left;
padding-left: 10px; 
border-bottom: 1px solid #EAEEF0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<body>
<br><br>
<div id="main">
	<table id="Table">
		<thead>
			<tr class="NoHover">
				<th class="col1" scope='col' >Time&#9660;</th>
				<th class="col2" scope='col' ></th>
				<th class="col3" scope='col' >Client</th>
				<th class="col4" scope='col' >Status</th>
				<th class="col5" scope='col' >Site</th>
				<th class="col6" scope='col' >Host</th>
				<th class="col7" scope='col' >Problem &bull; Cause</th>
				<th class="col8" scope='col' ></th>
				<th class="col9" scope='col' >Frequency</th>
				<th class="col10" scope='col'></th>
			</tr>
		</thead>
	<tbody id="TableData"> 
	  <tr>
    <td>2017-11-22</td>
    <td>1</td>
    <td>Client 1</td>
    <td>FAILING</td>
    <td>Site 1</td>
    <td>PC1</td>
    <td>test1</td>
    <td>Unable to open service</td>
    <td>24x7</td>
    <td>1</td>
  </tr>
  <tr>
    <td>2017-11-22</td>
    <td>1</td>
    <td>Client 2</td>
    <td>FAILING</td>
    <td>Site 2</td>
    <td>PC2</td>
    <td>test2</td>
    <td>Unable to open service</td>
    <td>24x7</td>
    <td>2</td>
  </tr>
  <tr>
    <td>2017-11-22</td>
    <td>1</td>
    <td>Client 3</td>
    <td>FAILING</td>
    <td>Site 3</td>
    <td>PC3</td>
    <td>test3</td>
    <td>Unable to open service</td>
    <td>24x7</td>
    <td>3</td>
  </tr>
  <tr>
    <td>2017-11-22</td>
    <td>1</td>
    <td>Client 4</td>
    <td>FAILING</td>
    <td>Site 4</td>
    <td>PC4</td>
    <td>test4</td>
    <td>Unable to open service</td>
    <td>24x7</td>
    <td>4</td>
  </tr>
  <tr>
    <td>2017-11-22</td>
    <td>1</td>
    <td>Client 5</td>
    <td>FAILING</td>
    <td>Site 5</td>
    <td>PC5</td>
    <td>test5</td>
    <td>Unable to open service</td>
    <td>24x7</td>
    <td>5</td>
  </tr>
 </tbody>
	</table>
</div>
</body>

Answer

I think you are looking for the .siblings() selector:

    $("td:nth-child(10):contains('1')").siblings('td:nth-child(7), td:nth-child(8)').addClass('disaster');
    $("td:nth-child(10):contains('2')").siblings('td:nth-child(7), td:nth-child(8)').addClass('high');
    $("td:nth-child(10):contains('3')").siblings('td:nth-child(7), td:nth-child(8)').addClass('average');
    $("td:nth-child(10):contains('4')").siblings('td:nth-child(7), td:nth-child(8)').addClass('warning');
    $("td:nth-child(10):contains('5')").siblings('td:nth-child(7), td:nth-child(8)').addClass('information');

Fiddle: https://jsfiddle.net/8sL86sc7/2/

Source: stackoverflow
Text is available under the Creative Commons Attribution-ShareAlike License; additional terms may apply. By using this site, you agree to the Privacy Policy, and Copyright Policy. Content is available under CC BY-SA 3.0 unless otherwise noted. The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 © No Copyrights, All Questions are retrived from public domain..