ViewPager2 와 Fragments 를 이용한 탭메뉴 (AndroidX)

프로그래밍/Android (Java)|2020. 11. 26. 12:45
반응형

[출처]  http://www.tutorialsface.com/2020/07/android-tablayout-example-using-viewpager2-and-fragments-with-latest-android-api-androidx/


In this tutorial we are going to create 3 Tabs .Every tab have its own Fragment to control over screen. Also user can swipe between 3 tabs.

we are using AndroidX support Library , ViewPager2 and 3 different fragment & 3 different xml for layouts. And TabLayout for Tabs.

Layout Demonstration :

  • Checkout the following pic which explains the complete overview of layout architecture. Basically we are using ViewPager as main layout and for individual pager views we use Fragments. The tabs are part of Action Bar.

STEP 1: CREATING PROJECT

  • Let’s start with creating new project in android studio with package name com.example.manualSliding and class name MainActivity.java and its layout name is activity_main.xml.

STEP 2: ADDING DEPENDENCIES

  • open file Gradle Scripts/build.gradle(Module: app)
  • under dependencies{ } add this:
dependencies {
   
    //this is for ViewPager
    implementation "androidx.viewpager2:viewpager2:1.0.0"
    
    //this is for TabLayout
    implementation 'com.google.android.material:material:1.2.0-alpha01'

}
  • under compileOptions{} add this:
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}

STEP 3: EDIT app/res/values/colors.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#0698bc</color>
<color name="colorPrimaryDark">#067d9b</color>
<color name="colorAccent">#FF4081</color>
<color name="frg1Color">#FEBE29</color>
<color name="frg2Color">#3395FF</color>
<color name="frg3Color">#F6437B</color>
<color name="txtBGColor">#9FA8DA</color>
<color name="white">#FFFFFF</color>
</resources>

STEP 4: EDIT app/res/values/styles.xml : we using this theme because TabLayout component works in this theme.

<resources>
    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.MaterialComponents.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>

</resources>

STEP 6: CREATING LAYOUT FOR EACH FRAGMENT :

  • create new xml layout file under app/res/layout/first_frag.xml and add the below code:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/cLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/frg1Color">

<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="356dp"
android:text="sample text 1"
android:textSize="25dp"
android:textStyle="bold"
android:textColor="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
  • create new xml layout file under app/res/layout/second_frag.xml and add the below code:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/cLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/frg2Color">

<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="356dp"
android:text="sample text 2"
android:textSize="25dp"
android:textStyle="bold"
android:textColor="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
  • create new xml layout file under app/res/layout/third_frag.xml and add the below code:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/cLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/frg3Color">

<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="356dp"
android:textSize="25dp"
android:textStyle="bold"
android:text="sample text 3"
android:textColor="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.497"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

STEP 7: Create FRAGMENT CLASS for each view layout:

  • create new java class under app/java/com.example.manualSliding/FirstFragment.java
package com.example.manualsliding;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.fragment.app.Fragment;

public class FirstFragment extends Fragment {

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.first_frag, container, false);

TextView tv = (TextView) v.findViewById(R.id.textView1);
tv.setText(getArguments().getString("msg"));
return v;
}

public static FirstFragment newInstance(String text) {

FirstFragment f = new FirstFragment();
Bundle b = new Bundle();
b.putString("msg", text);

f.setArguments(b);

return f;
}
}
  • create new java class under app/java/com.example.manualSliding/SecondFragment.java
package com.example.manualsliding;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.fragment.app.Fragment;

public class SecondFragment extends Fragment {

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.second_frag, container, false);

TextView tv = (TextView) v.findViewById(R.id.textView1);
tv.setText(getArguments().getString("msg"));

return v;
}

public static SecondFragment newInstance(String text) {

SecondFragment f = new SecondFragment();
Bundle b = new Bundle();
b.putString("msg", text);

f.setArguments(b);

return f;
}
}
  • create new java class under app/java/com.example.manualSliding/ThirdFragment.java
package com.example.manualsliding;


import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.fragment.app.Fragment;

public class ThirdFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.third_frag, container, false);

        TextView tv = (TextView) v.findViewById(R.id.textView1);
        tv.setText(getArguments().getString("msg"));

        return v;
    }

    public static ThirdFragment newInstance(String text) {

        ThirdFragment  f = new ThirdFragment();
        Bundle b = new Bundle();
        b.putString("msg", text);

        f.setArguments(b);

        return f;
    }
}

STEP 8: app/res/layout/activity_main.xml : here we are creating TabLayout and ViewPager2.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">

<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout"
style="@style/Widget.MaterialComponents.TabLayout.Colored"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

<androidx.viewpager2.widget.ViewPager2
android:id="@+id/mypager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />

</LinearLayout>

STEP 8: app/java/com.example.manualSliding/MainActivity.java

  • Here we use FragmentStateAdapter class for creating fragment and then we will assign it into Viewpager2.
  • create Strings array of tabs titles.
    • private String[] titles = new String[]{“Tab1”, “Tab2”, “Tab3”};
  • Inflating tab layout
    • TabLayout tabLayout =( TabLayout) findViewById(R.id.tab_layout);
  • Displaying tabs
    • new TabLayoutMediator(tabLayout, viewPager,(tab, position) -> tab.setText(titles[position])).attach();
  • complete code of MainActivity.java
package com.example.manualsliding;

import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import androidx.viewpager2.widget.ViewPager2;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;

public class MainActivity extends AppCompatActivity {
private static final int NUM_PAGES = 3;
//The pager widget, which handles animation and allows swiping horizontally to access previous and next wizard steps.
 public static ViewPager2 viewPager;
// The pager adapter, which provides the pages to the view pager widget.
 private FragmentStateAdapter pagerAdapter;
// Arrey of strings FOR TABS TITLES
 private String[] titles = new String[]{"Tab1", "Tab2", "Tab3"};
// tab titles
 @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = findViewById(R.id.mypager);
pagerAdapter = new MyPagerAdapter(this);
viewPager.setAdapter(pagerAdapter);
//inflating tab layout
 TabLayout tabLayout =( TabLayout) findViewById(R.id.tab_layout);
//displaying tabs
 new TabLayoutMediator(tabLayout, viewPager,(tab, position) -> tab.setText(titles[position])).attach();
}

private class MyPagerAdapter extends FragmentStateAdapter {

public MyPagerAdapter(FragmentActivity fa) {
super(fa);
}


@Override
public Fragment createFragment(int pos) {
switch (pos) {
case 0: {
return FirstFragment.newInstance("fragment 1");
}
case 1: {

return SecondFragment.newInstance("fragment 2");
}
case 2: {
return ThirdFragment.newInstance("fragment 3");
}
default:
return FirstFragment.newInstance("fragment 1, Default");
}
}

@Override
public int getItemCount() {
return NUM_PAGES;
}
}


@Override
public void onBackPressed() {
if (viewPager.getCurrentItem() == 0) {
// If the user is currently looking at the first step, allow the system to handle the
 // Back button. This calls finish() on this activity and pops the back stack.d
 super.onBackPressed();
} else {
// Otherwise, select the previous step.
 viewPager.setCurrentItem(viewPager.getCurrentItem() - 1);
}
}

}


[출처]  http://www.tutorialsface.com/2020/07/android-tablayout-example-using-viewpager2-and-fragments-with-latest-android-api-androidx/


반응형

댓글()

기본 에디터, 기본 편집기 변경하기 (nano -> vim)

리눅스/OS 일반|2020. 11. 26. 09:16
반응형

Ubuntu 20.04 에서 crontab -e 명령을 사용할때 nano 편집기로 열릴 경우 vim 으로 변경하는 방법이 있습니다.


# vi ~/.bashrc

export EDITOR="vim"    // 맨 하단에 추가


적용하기

# source ~/.bash


이제 vim 을 이용한 편집이 가능해 졌습니다.


반응형

댓글()

Apache2 구동 에러 : AH00111: Config variable ${APACHE_RUN_DIR} is not defined

리눅스/APACHE|2020. 11. 25. 15:40
반응형

아파치를 구동이 잘 되지 않아 설정 체크를 해보았더니 아래와 같은 에러 메세지가 출력 되었습니다.


root@sysdocu:/root# systemctl restart apache2

Job for apache2.service failed because the control process exited with error code.

See "systemctl status apache2.service" and "journalctl -xe" for details.


root@sysdocu:/root# apache2 -t

[Wed Nov 25 15:34:44.220065 2020] [core:warn] [pid 52764] AH00111: Config variable ${APACHE_RUN_DIR} is not defined

apache2: Syntax error on line 80 of /etc/apache2/apache2.conf: DefaultRuntimeDir must be a valid directory, absolute or relative to ServerRoot


이 경우 아래와 같이 환경 변수 파일을 다시 적용하면 해결이 됩니다.


root@sysdocu:/root# source /etc/apache2/envvars 


root@sysdocu:/root# apache2 -t

Syntax OK


이상이 없으므로 아파치 재시작을 해줍니다.


root@sysdocu:/root# systemctl restart apache2



반응형

댓글()

CentOS 8 Http 2.4 에 mod_security 설치하기 (YUM)

리눅스/Security|2020. 11. 12. 10:30
반응형

CentOS 8, yum 으로 설치된 httpd 에 mod_security 를 추가로 설치하는 방법입니다.


1. 모듈 설치

# dnf -y install mod_security


2. OWASP 룰 설치 및 적용

# cd /etc/httpd

# git clone https://github.com/SpiderLabs/owasp-modsecurity-crs.git


# cd owasp-modsecurity-crs

# cp -arp crs-setup.conf.example /etc/httpd/modsecurity.d/crs-setup.conf

# vi /etc/httpd/modsecurity.d/crs-setup.conf

문서 하단부의 pass 를 deny 로 변경

SecAction \

 "id:900990,\

  phase:1,\

  nolog,\

  deny,\

  t:none,\

  setvar:tx.crs_setup_version=320" 


# cd rules

# cp -arp ./* /etc/httpd/modsecurity.d/activated_rules/


# cd /etc/httpd/modsecurity.d/activated_rules/

# cp -arp REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf

# cp -arp RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf


3. 적용

# systemctl restart httpd


4. 확인

웹브라우저에서 다음과 같이 웹페이지로 공격시도를 해봅니다.


http://도메인/index.html?cmd=rm



반응형

댓글()

CentOS 8 에 YUM 으로 APM 설치하기 (특정 확장자에서 PHP 코드 사용 포함)

리눅스/APACHE|2020. 11. 10. 10:25
반응형

OS 환경 패키지 업데이트

# yum -y update


기본 라이브러리 설치

# yum install -y libjpeg* libpng* freetype* gd-* gcc gcc-c++ gdbm-devel libtermcap-devel


아파치 설치

# yum install -y httpd*


마리아DB 설치

# yum install -y mariadb*


PHP 설치

# yum install -y php php-common php-opcache php-cli php-gd php-curl php-mysqlnd


환경 설정

# vi /etc/httpd/conf/httpd.conf


<IfModule dir_module>

    DirectoryIndex index.html index.php

</IfModule>


# vi /etc/php.ini


short_open_tag = On

date.timezone = "Asia/Seoul"


# vi /etc/my.cnf.d/mariadb-server.cnf


[mysqld] 섹션에 아래 내용 추가 (한글이 웹상에서 잘 표시되도록 설정)

character-set-client-handshake=FALSE

collation-server=utf8_general_ci

character-set-server=utf8 


적용

# systemctl restart httpd

# systemctl restart php-fpm

# systemctl restart mysqld


php 코드를 html 파일에서 사용하려면 아래 작업을 추가로 진행 해줍니다.


# vi /etc/httpd/conf.d/php.conf


<IfModule !mod_php5.c>

  <IfModule !mod_php7.c>

    # Enable http authorization headers

    SetEnvIfNoCase ^Authorization$ "(.+)" HTTP_AUTHORIZATION=$1


    <FilesMatch \.(php|phar|html)$>    // 확장자 추가

        SetHandler "proxy:unix:/run/php-fpm/www.sock|fcgi://localhost"

    </FilesMatch>

  </IfModule>

</IfModule> 


# vi /etc/php-fpm.d/www.conf


security.limit_extensions = .php .php3 .php4 .php5 .php7 .html    // 주석 해제 및 확장자 추가

 listen.allowed_clients = 0.0.0.0    // 수정


적용

# systemctl restart httpd

# systemctl restart php-fpm





반응형

댓글()

아파치 설치 에러 libaprutil-1.so: undefined reference to `XML_SetElementHandler collect2: error: ld returned 1 exit status apache make

리눅스/APACHE|2020. 11. 9. 16:55
반응형

아파치 2.4.46 설치 도중 아래와 같은 메세지를 만났습니다.


(make 에러)

libaprutil-1.so: undefined reference to `XML_SetElementHandler 

collect2: error: ld returned 1 exit status apache make


이경우 아래와 같이 조치합니다.


# vi build/config_vars.mk


AP_LIBS 으로 시작되는 행을 찾아서 맨 뒤에 -lexpat 를  추가하고 다시 컴파일 합니다.


# make clean

# make

반응형

댓글()

쉘스크립트에서 특정시간의 전 후 시간 계산 하기

프로그래밍/BASH SHELL|2020. 11. 4. 09:30
반응형

아래는 현재 시간에서 5분전 시간을 출력합니다. now_time 변수에 특정 날짜, 시간을 넣으면 그 시간에서 부터 계산합니다.


now_time=`date +%Y-%m-d %H:%M:%S`

edit_time=`date -d "${now_time} 5 minute ago"`


echo $edit_time


[ 결과 ]


# echo $edit_time

Wed 04 Nov 2020 09:22:19 AM KST  // 5분 전 시간


# date

Wed 04 Nov 2020 09:27:22 AM KST  // 현재 시간



분 외에 시간이나 초, 날짜 등 전후의 시간계산을 원하시는 분은 아래 링크를 참조하여 진행하시면 됩니다.

정리가 잘 되어 있습니다.


https://soft.plusblog.co.kr/97


반응형

댓글()

Error 403, 404 를 특정 html 페이지로 출력하기

리눅스/APACHE|2020. 11. 4. 08:17
반응형

없는 파일이나 접근 불가능한 페이지에 접근할 경우 특정 html 파일을 출력할 수 있습니다.

각각의 사이트 VirtualHost 설정에 아래 내용을 추가 합니다.


ErrorDocument 403 /404.html

ErrorDocument 404 /404.html


그리고 DocumentRoot (소스 최상위 디렉토리) 에 404.html 파일을 만들어 안내하고 싶은 내용으로 채우면 됩니다.

아파치 데몬을 재시작 하여 적용합니다.


# systemctl restart apache2



반응형

댓글()

MongoDB 내용을 텍스트 파일로 추출하기

리눅스/MongoDB|2020. 10. 28. 09:03
반응형

MongoDB 내용을 텍스트 파일로 추출해야 할 일이 있어서 알아봤는데

그 방법에는 두 가지가 있습니다.



[ 첫번째 방법 ]


우선 아래와 같이 도큐멘트의 개수를 확인합니다.

# mongo sysdocu -u prince -p --quiet --eval 'db.members.count()'

12


* 설명 : prince 계정으로 sysdocu 데이터베이스의 members 컬렉션 도큐멘트 개수 확인


그리고 출력된 개수와 동일하거나 많은 수의 범위까지 파일로 추출합니다.

저장 형태는 toArray() 로 인해 key 별로 줄바꿈이 되어 예쁘게 출력 되지만,

리눅스에서 텍스트를 가공하고자 할때는 한줄로 표시되는 것이 편하므로 해당 toArray() 는 제외합니다.


# mongo sysdocu -u prince -p --quiet --eval 'DBQuery.shellBatchSize = 20; db.members.find({}).limit(20).toArray()' > result.json


* 설명 : 도큐멘트 개수 조회 결과가 12 이므로 12로 하거나 더 많은 20으로 해도 됩니다.


result.json 파일에 내용이 저장 되었습니다.



[ 두번째 방법 ]


# mongo sysdocu -u prince -p |tee result.txt


위와 같이 실행하면 별다른 반응없이 일반적인 MongoDB 콘솔 로그인이 됩니다.

하지만 MongoDB 콘솔을 빠져 나올때 까지 (exit) 화면에 출력되는 내용은

result.txt 파일에 저장되게 됩니다.

화면 출력이 이루어져야 하므로 도큐멘트 개수가 많은 경우 첫번째 방법보다 속도가 느립니다.


반응형

댓글()

TTS 를 이용한 음성 (wav) 다운로드 및 mp3 변환 사이트

자료실|2020. 10. 26. 09:23
반응형

https://imtranslator.net/translate-and-speak/

 

Translate and Speak

How to Use ImTranslator Translate and Speak • How to translate text and listen to the translation Do the following: •  make sure that the Translate check mark box is ON •  choose the target language for translation •  adjust the speed of the voi

imtranslator.net

음성 다운로드를 위해서 아래 절차를 거칩니다.

 

1. Translate 체크 해제

 

2. 언어 Korean 선택

 

3. 텍스트를 입력합니다.

 

4. 상단에 Speak Korean 버튼이나 TTS Voice 아이콘을 선택합니다.

 

5. 출력된 오디오 컨트롤러를 마우스 우클릭하여 '오디오를 다른 이름으로 저장' 합니다.

 

* 저장된 wav 파일은 아래 사이트에서 mp3 로 변환 가능합니다.

online-audio-converter.com/ko/

convertio.co/kr/wav-mp3/

 

 

반응형

댓글()

MySQL 중복된 데이터만 조회하기

리눅스/MySQL|2020. 10. 23. 15:59
반응형

아래 쿼리 예제는 contents 테이블에서 title 컬럼의 값이 중복일 때, title 과 개수를 출력 합니다.


SELECT title, count(*) as CNT FROM contents GROUP BY title HAVING CNT > 1;


+--------------+-----+

| title              | CNT |

+--------------+-----+

| family         |   2 |

| other           |   3 |

+--------------+-----+

2 rows in set (0.00 sec)



반응형

댓글()